2012-01-23 21 views
1

イメージの色を変更してサイズを変更しようとすると、元のイメージのサイズが変更されます。なぜこれが起こっているのですか、どうすれば修正できますか?私はまた、ユーザーがボタンをクリックし、正しいメソッドを呼び出すように、適切な値にboolsを設定する場合の対処方法を持っている変更されたイメージのサイズを変更できませんか? C#WinForms

private PrintDocument printDoc = new PrintDocument(); 
private PageSettings pgSettings = new PageSettings(); 
private PrinterSettings prtSettings = new PrinterSettings(); 

Bitmap myBitmapImage;  // image (bitmap) for some background mountains 
Boolean isInvert = false; 
Boolean isLOaded = false; 
Boolean isGrayscale = false; 
Boolean isThreshold = false; 
Boolean isResize = false; 

OpenFileDialog ofd; 
Bitmap bmBack; 

public EditImage() 
{ 
    printDoc.PrintPage += new PrintPageEventHandler(printDoc_PrintPage); 

    InitializeComponent(); 
    this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.DoubleBuffer, true); 
} 

private void EditImage_Load(object sender, EventArgs e) 
{ 

} 

private void EditImage_Paint(object sender, PaintEventArgs e) 
{ 
    if (isLOaded == true) 
    { 
     Graphics gWindow; // reference to the graphic surface of this window 
     Graphics gBack;  // reference to in-memory surface 

     bmBack = new Bitmap(Width, Height);  // bitmap for window surface copy 

     gWindow = e.Graphics; // get our current window's surface 
     gBack = Graphics.FromImage(bmBack);  // create surfaces from the bitmaps 

     gBack.DrawImage(myBitmapImage, 0, 0, Width, Height); 

     if (isInvert == true) 
     { 
      InvertBitmap(bmBack); 
     } 
     else if (isGrayscale == true) 
     { 
      GrayscaleBitmap(bmBack); 
     } 
     else if (isThreshold == true) 
     { 
      ThresholdBitmap(bmBack); 
     } 
     else if (isResize == true) 
     { 
      bmBack = resizeImage(bmBack, 10, 100); 
     } 

     gWindow.DrawImage(bmBack, 0, 0); 
    } 
} 
private void toolStripMenuItemLoadImage_Click(object sender, EventArgs e) 
{ 
    using (ofd = new OpenFileDialog()) 
    { 
     ofd.Title = "Load Image"; 

     if (ofd.ShowDialog() == DialogResult.OK) 
     { 
      myBitmapImage = new Bitmap(ofd.FileName); 
      this.Invalidate(); 
     } 
    } 
    isLOaded = true; 
} 


private void GrayscaleBitmap(Bitmap bmp) 
{ 
    Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height); 
    System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, 
     System.Drawing.Imaging.PixelFormat.Format32bppRgb); 

    IntPtr ptr = bmpData.Scan0; 

    int numPixels = bmpData.Width * bmp.Height; 
    int numBytes = numPixels * 4; 
    byte[] rgbValues = new byte[numBytes]; 

    System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, numBytes); 

    for (int i = 0; i < rgbValues.Length; i += 4) 
    { 
     byte gray = (byte)(.3 * rgbValues[i + 0]); //blue 
     gray += (byte)(.59 * rgbValues[i + 1]); //green 
     gray += (byte)(.11 * rgbValues[i + 2]); //red 

     rgbValues[i + 0] = gray; //blue 
     rgbValues[i + 1] = gray; //green 
     rgbValues[i + 2] = gray; //red 
    } 

    System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, numBytes); 

    bmp.UnlockBits(bmpData); 
} 

private Bitmap resizeImage(Bitmap sourceBMP, int width, int height) 
{ 
    Bitmap result = new Bitmap(width, height); 
    using(Graphics g = Graphics.FromImage(result)) 
    g.DrawImage(sourceBMP, 0, 0, width, height); 

    return result; 
} 

は、ここに私のコードです。イメージは意図したように色が変わりますが、サイズ変更をクリックすると元のイメージではなく色が変更されたイメージのサイズを変更します。

答えて

4

ここには多くのものがあります:あなたは、グラフィックスを処分する必要があり

resizeImage()

  • は、(使用して()文でそれをラップ)
  • この機能は、ここから無効に呼び出さないでくださいここで作成し、そのオブジェクトあなたのイメージをサイズ変更するだけです。画像がペイントされ、変更された画像がペイントされます。
  • また、関数を使用しなくなったときに関数を返す前に、sourceBMPを破棄することを検討する必要があります。

GrayscaleBitmap()

  • これは右のように見えますが、ここで再び無効にする理由はありません。呼び出し元の関数でこのメソッドを呼び出した後は、無効にする必要があります。もっと理にかなっている。

EditImage_Paint

  • あなたのPaintイベント内からこれらの関数を呼び出すべきではありません。また、新しいペイントごとに新しいビットマップと新しいGraphicsクラスを作成するべきではありません。これは、必要以上に多くの作業です。これらの関数は、ユーザー入力に基づいてデータを変更する必要がある場合(ユーザーがグレースケール効果を適用するためにボタンをクリックする)にのみ実行する必要があります。

あなたがしたいことは、多くても2つのビットマップ変数のみが必要です。ユーザーに "リセット"させるか、エフェクトを元に戻す(ほとんどのエフェクトが永久的なデータ損失を引き起こす場合は、再度グレースケールのイメージカラーを作成することはできません)ために、オリジナルの未修正ビットマップを保存します。もう1つは塗りつぶされたビットマップを格納します。ユーザーがエフェクトを適用するたびに、2番目のビットマップが変更され、invalidateが呼び出されます。

すべての第二ビットマップを描画されて行う必要があり、あなたのペイント機能:

Bitmap originalBitmap; // load from file, do not modify 
Bitmap currentBitmap; // when user clicks an effect, modify this bitmap and then Invalidate afterward 

private void EditImage_Paint(object sender, PaintEventArgs e) 
{ 
    e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; 

    // Draw the currentBitmap centered on the window 
    SizeF clientSize = this.ClientSize; 

    double zoomRatio = Math.Min(
     clientSize.Width/currentBitmap.Width, 
     clientSize.Height/currentBitmap.Height 
    ); 

    SizeF zoomedSize = new SizeF(
     (float)(currentBitmap.Width * zoomRatio), 
     (float)(currentBitmap.Height * zoomRatio) 
    ); 

    PointF imageOffset = new PointF(
     (clientSize.Width - zoomedSize.Width)/2, 
     (clientSize.Height - zoomedSize.Height)/2 
    ); 

    e.Graphics.Clear(Color.White); 
    e.Graphics.DrawImage(currentBitmap, imageOffset.X, imageOffset.Y, zoomedSize.Width, zoomedSize.Height); 
} 

これは、制御上の画像を中心とウィンドウに合わせて、それを描画する簡単なズーム効果をエミュレートします。

+0

ありがとう、私はあなたが提案したすべての変更を加えました...私は私のペイント方法を修正する方法を理解していない以外は...私はそれをやる方法の例を教えてくれますか? – BigBug

+0

+1のヘルプ – BigBug

+0

できることの例で更新しました。 –

関連する問題