2016-04-24 4 views
0

ScaleTransform(zoomFactor、zoomFactor)を使用すると、ディスクに保存された画像は常に元のバージョンになります。 zoomFactorに比例します。 これがなぜ起こっているのでしょうか? e.Graphicsからディスクに書き込まれたイメージに適用される最終的な結果はありませんか?C#GDI + ScaleTransform画像ボックスでOKですが、保存された画像はオリジナルです

私のコードは以下のとおりですが、これはマトリックスのあるバージョンです。行列の代わりにScaleTransformも使用しています。結果は常に同じです:

   g=e.Graphics;//inside picturebox_paint() 
       g.ScaleTransform(ratio * zoomFac, ratio * zoomFac); 
       e.Graphics.DrawImage((Bitmap)bmp, 0, 0); 
       int seed = Convert.ToInt32(Regex.Match(Guid.NewGuid().ToString(), @"\d+").Value); 
       String destinationFile = @"C:\tmp\photoid\" + new Random(seed).Next() + "_conv.jpg"; 
//Here I get always the original image back!!!! 
       bmp.Save(destinationFile); 

私は同様に、次のイディオムが、同じ結果を伴って使用している:

  //Matrix matrix = new Matrix(); 
      //matrix.Scale(zoomFac, zoomFac); 
      //e.Graphics.Transform = matrix;            

答えて

1

あなたはあなたがして保存することができます新しいビットマップ、にそれが画面に表示さのものを描くPictureBoxを作成する必要があります!

Imageは元の形式で保存されるため、実際にはPictureBoxの表面に痛みを伴うPaintイベントでは何も保存されませんが保存されます。だから、おそらくすべてのもの、すなわちImageBackgroundImage、あなたがDrawToBitmap somehwereを呼ぶだろうPaintイベントで描くすべてを保存するために

。それは無限ループを引き起こし、新しいBitmapを作成するPaintイベントを呼び出しますよう

どこかはそれを呼び出すには..ないPaint場合には、どこか

を他を意味あなたのような何かをするだろうこの:

Bitmap bmpSave = new Bitmap(pictureBox1.ClientSize.Width, pictureBox1.ClientSize.Height); 
pictureBox1.DrawToBitmap(bmpSave, pictureBox1.ClientRectangle); 

これは本当にあなたが望むものではありませんか?実際にImageを変更したいのですか?その場合、ではなくPaintイベントを使用してください。あなたは、スケーリングからトリガされているどこからこれを呼び出すことができ

Bitmap bmpSave = new Bitmap(yourNewWidth, yourNewHeight); 
using (Graphics g = Graphics.FromImage(bmpSave)) 
{ 
    g.ScaleTransform(ratio * zoomFac, ratio * zoomFac); 
    g.DrawImage((Bitmap)pictureBox1.Image, 0, 0); // 
    pictureBox1.Image = bmpSave; 
    bmpSave.Save(...); 
} 

代わりにこのような何かを行います。

スケーリングを繰り返すと、以前のスケーリングされたバージョンから毎回が品質が低下することに注意してください。かなり高速です。これは、オリジナルの保存されたバージョンから常に拡大縮小されます。

Btw:スケーリングにMatrixを使用しても、実際にはScaleTransformとの違いはありません。

しかし、直接スケーリングを行う場合は、という2つの数値を持つDrawImageのオーバーロードを使用しないでください。Rectangles

int newWidth = 100; int newHeight = 100; string yourFileName = "D:\\xyz123.jpg"; 

Bitmap bmpSave = new Bitmap(pictureBox1.ClientSize.Width, pictureBox1.ClientSize.Height); 
Rectangle newRectangle = new Rectangle(0, 0, newWidth, newHeight); 
Rectangle oldRectangle = new Rectangle(Point.Empty, pictureBox1.Image.Size); 
using (Graphics g = Graphics.FromImage(bmpSave)) 
{ 
    g.DrawImage((Bitmap)pictureBox1.Image, newRectangle, oldRectangle, GraphicsUnit.Pixel); 
    bmpSave.Save(yourFileName, ImageFormat.Jpeg); 
} 

とスケーリングBitmapコンストラクタそこにある:すべてはあなたが拡大し、多分さらに他のものを描くようにしたい場合、これは...最も一般的なソリューションです私は希望

Bitmap bmp = new Bitmap(pictureBox1.Image, newWidth, newHeight); 

は、 Imageの縮尺を変更することをお勧めします。他の解決策として、それはあなたがPictureBoxに戻ってそれを割り当てるまでImageが表示変更されません..:

は古いイメージを処分することを忘れないでください

pictureBox1.Image = bmp ; 
...あなたの答えのための

+0

こんにちはおかげで、そのbmpSaveを使用すると、ゆがんだ画像が保存されますが、画像の周りの領域も画像ボックスの境界まで保存されます。 (ピクチャーボックスは640x480です)、画像は少なくなります。目的は歪んだ画像だけを保存することです、私はそうですか? – hephestos

+0

はい、その場合、新しいBitmapのPictureBoxの古いサイズを使用しないでください! – TaW

+0

親愛なるTawはい、あなたが与えた2番目のスニペットは、私が望むものに近いです。どうすれば新しいビットマップのサイズを再計算できますか? scaletransformはbmpsaveの作成後に来るからです。 "newwidth"でbmpSaveを作成しますが、実際にscaletransformを呼び出すまではnewwidthはわかりません。右? – hephestos

0

は、しばらくして、私はGDIと混乱が、私はあなたが戻ってコピーする必要があると思うので、ここのビットマップ

g.DrawImage(bmp, scaledwidth, scaledheight); 

は、あなたが戻ってビットマップにコピーされたことを見ていないためbmp.Save

を編集する前に 謝罪をそのような何かを試してみてください。おそらく出力矩形を指定するオーバーロードが必要なものです。デスティネーションRectを持つDrawImageオーバーロードを試してください。 https://msdn.microsoft.com/en-us/library/ms142040(v=vs.110).aspx

関連する問題