範囲選択して移動している途中で[選択されている部分だけ左右反転]を選択すると問題がおきます。[選択されている部分だけ左右反転]をすることで白抜きになっていた部分が元にもどってしまいます。さらにどこか別の部分(矩形の内部でも外部でも同じ)をクリックすると白抜きになっている部分がもとに戻ります。
これは選択範囲の移動の処理をするときにblankBitmapやblankColorPointsを追加しました。これに関する処理がそれ以前に追加された機能では無視されていたのが原因です。新しい機能を追加したら以前の機能がうまくできなくなったでは困るので修正します。
Contents
SelectionRotateFlipメソッドの一部修正
選択範囲を回転・反転させるSelectionRotateFlipメソッドを一部修正します。また範囲指定が解除されるまでBitmapプロパティは変更しないことにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
public partial class UserControlImage : UserControl { public bool SelectionRotateFlip(RotateFlipType rotateFlipType) { if(Bitmap == null) return false; if(BitmapRectangle == null) return false; Bitmap bitmap = BitmapRectangle.Bitmap; Rectangle rect = BitmapRectangle.Rectangle; bitmap.RotateFlip(rotateFlipType); Bitmap bitmap1 = new Bitmap(bitmap); // Bitmapとは別にnewBitmapを作成する Bitmap newBitmap = new Bitmap(Bitmap); Graphics g = Graphics.FromImage(newBitmap); // これを追加 if(blankBitmap != null) g.DrawImage(blankBitmap.Bitmap, blankBitmap.Location); if(blankColorPoints != null) { foreach(var cp in blankColorPoints) bitmap1.SetPixel(cp.X, cp.Y, cp.Color); } // 追加部分ここまで Rectangle srcRect = new Rectangle(0, 0, bitmap1.Width, bitmap1.Height); g.DrawImage(bitmap1, rect, srcRect, GraphicsUnit.Pixel); g.Dispose(); bitmap1.Dispose(); // 範囲指定がクリアされるまでBitmapプロパティは変更しない ShowBitmap(DrawBoderRectangle(newBitmap)); return true; } } |
ReverseColorInRectangleメソッドの一部修正
選択範囲の色を反転させるReverseColorInRectangleメソッドも一部修正が必要です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
public partial class UserControlImage : UserControl { public bool ReverseColorInRectangle() { if(Bitmap == null) return false; if(BitmapRectangle == null) return false; Bitmap bitmap = BitmapRectangle.Bitmap; Rectangle rect = BitmapRectangle.Rectangle; Bitmap rectBitmap = new Bitmap(rect.Width, rect.Height); for(int x = 0; x < rect.Width; x++) { for(int y = 0; y < rect.Height; y++) { Color color = bitmap.GetPixel(x, y); int red = 255 - color.R; int green = 255 - color.G; int blue = 255 - color.B; rectBitmap.SetPixel(x, y, Color.FromArgb(red, green, blue)); } } BitmapRectangle.Bitmap = rectBitmap; Bitmap newBitmap = new Bitmap(Bitmap); Graphics g = Graphics.FromImage(newBitmap); // これを追加 if(blankBitmap != null) g.DrawImage(blankBitmap.Bitmap, blankBitmap.Location); if(blankColorPoints != null) { foreach(var cp in blankColorPoints) newBitmap.SetPixel(cp.X, cp.Y, cp.Color); } // 追加部分ここまで Rectangle srcRect = new Rectangle(0, 0, rectBitmap.Width, rectBitmap.Height); g.DrawImage(rectBitmap, rect, srcRect, GraphicsUnit.Pixel); g.Dispose(); // 範囲指定がクリアされるまでBitmapプロパティは変更しない ShowBitmap(DrawBoderRectangle(newBitmap)); return true; } } |
ReplaceColorInRectangleメソッドの一部変更
選択部分の色を置換するReplaceColorInRectangleメソッドも一部変更しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
public partial class UserControlImage : UserControl { public bool ReplaceColorInRectangle(Color oldColor, Color newColor, bool isOldColorTransparent, bool isNewColorTransparent, int differenceR, int differenceG, int differenceB) { if(BitmapRectangle == null) return false; if(isOldColorTransparent) oldColor = Color.FromArgb(0, 0, 0, 0); if(isNewColorTransparent) newColor = Color.FromArgb(0, 0, 0, 0); Bitmap oldSelectedBitmap = BitmapRectangle.Bitmap; Rectangle rect = BitmapRectangle.Rectangle; Bitmap newSelectedBitmap; Bitmap newBitmap; if(isNewColorTransparent) { newBitmap = SetSelectionTransparent(rect, oldColor, differenceR, differenceG, differenceB); } else { if(!isOldColorTransparent) newSelectedBitmap = GetBitmapReplaceColor(oldSelectedBitmap, oldColor, newColor, differenceR, differenceG, differenceB); else newSelectedBitmap = GetBitmapReplaceColor(oldSelectedBitmap, oldColor, newColor, 0, 0, 0); BitmapRectangle.Bitmap = newSelectedBitmap; newBitmap = new Bitmap(Bitmap); Graphics g = Graphics.FromImage(newBitmap); // これを追加 if(blankBitmap != null) g.DrawImage(blankBitmap.Bitmap, blankBitmap.Location); if(blankColorPoints != null) { foreach(var cp in blankColorPoints) newBitmap.SetPixel(cp.X, cp.Y, cp.Color); } // 追加部分ここまで Rectangle srcRect = new Rectangle(0, 0, rect.Width, rect.Height); g.DrawImage(newSelectedBitmap, rect, srcRect, GraphicsUnit.Pixel); g.Dispose(); } // 範囲指定がクリアされるまでBitmapプロパティは変更しない ShowBitmap(DrawBoderRectangle(newBitmap)); return true; } } |
SetSelectionTransparentメソッドの修正
選択されている部分の色を透明に変えるSetSelectionTransparentメソッドは大幅に修正することになりました。第一引数は使われていません。直接BitmapRectangleにアクセスしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
public partial class UserControlImage : UserControl { public Bitmap SetSelectionTransparent(Rectangle rect, Color beforeColor, int differenceR, int differenceG, int differenceB) { int minR = beforeColor.R - differenceR; int maxR = beforeColor.R + differenceR; int minG = beforeColor.G - differenceG; int maxG = beforeColor.G + differenceG; int minB = beforeColor.B - differenceB; int maxB = beforeColor.B + differenceB; if(minR < 0) minR = 0; if(maxR > 255) maxR = 255; if(minG < 0) minG = 0; if(maxG > 255) maxG = 255; if(minB < 0) minB = 0; if(maxB > 255) maxB = 255; for(int x = 0; x < BitmapRectangle.Bitmap.Width; x++) { for(int y = 0; y < BitmapRectangle.Bitmap.Height; y++) { Color color = BitmapRectangle.Bitmap.GetPixel(x, y); if(minR <= color.R && color.R <= maxR && minG <= color.G && color.G <= maxG && minB <= color.B && color.B <= maxB) { BitmapRectangle.Bitmap.SetPixel(x, y, Color.FromArgb(0, 0, 0, 0)); } else { BitmapRectangle.Bitmap.SetPixel(x, y, color); } } } Bitmap newBitmap = new Bitmap(Bitmap); Graphics g = Graphics.FromImage(newBitmap); if(blankBitmap != null) g.DrawImage(blankBitmap.Bitmap, blankBitmap.Location); if(blankColorPoints != null) { foreach(var cp in blankColorPoints) newBitmap.SetPixel(cp.X, cp.Y, cp.Color); } g.DrawImage(BitmapRectangle.Bitmap, BitmapRectangle.Location); g.Dispose(); return newBitmap; } } |
以下は範囲選択した状態で移動し、そのあと[色の置換(選択されている部分だけ)]で赤を透明に置換した場合の実行結果です。背景のみが透明になっているのが確認できます。
選択範囲だけではなく全体を反転させたり色を変えるメソッドは呼び出されたときにUniteBitmapRectangleメソッドを呼び出しているので変更する箇所はありません。
サイズ変更されたときの処理
範囲指定されているときにサイズ変更の処理をすると範囲選択されている部分がそのまま残ってしまうので、処理の前にUniteBitmapRectangleメソッドで範囲指定されている部分を結合させてから処理をしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public partial class UserControlImage : UserControl { public void SizeChange(int newWidth, int newHeight) { UniteBitmapRectangle(new Point()); Bitmap newBmp = new Bitmap(newWidth, newHeight); Graphics g = Graphics.FromImage(newBmp); g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; g.DrawImage(Bitmap, 0, 0, newWidth, newHeight); g.Dispose(); Bitmap = newBmp; ShowBitmap(Bitmap); } } |
スクロールされたときの処理
それからスクロールされたときの処理も変更する必要があります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
public partial class UserControlImage : UserControl { private void HScrollBar1_Scroll(object sender, ScrollEventArgs e) { OnSeroll(); } private void HScrollBar1_Scroll(object sender, ScrollEventArgs e) { OnSeroll(); } void OnSeroll() { Bitmap newBitmap = new Bitmap(Bitmap); // 追加部分 if(BitmapRectangle != null) { Graphics g = Graphics.FromImage(newBitmap); if(BitmapRectangle != null) { if(blankBitmap != null) { g.DrawImage(blankBitmap.Bitmap, blankBitmap.Location); } } if(blankColorPoints != null) { foreach(ColorPoint cp in blankColorPoints) newBitmap.SetPixel(cp.X, cp.Y, cp.Color); } g.DrawImage(BitmapRectangle.Bitmap, BitmapRectangle.Location); g.Dispose(); } // 追加部分ここまで ShowBitmap(DrawBoderRectangle(newBitmap)); } } |