2016-04-24 11 views
0

Hallo Ich habe das Problem, dass, wenn ich ScaleTransform (ZoomFactor, ZoomFactor) verwenden, das Bild auf der Festplatte gespeichert ist immer die Originalversion, während auf dem Bildschirm in der Bildbox das Bild verzerrt ist proportional zum ZoomFaktor. Warum könnte das passieren? Sollte ich nicht das Endergebnis wie von e.Graphics auf Disketten geschriebenes Bild anwenden?C# GDI + ScaleTransform ok auf Bildbox aber Bild gespeichert ist Original

Mein Code ist der folgende, der eine Version mit Matrix ist. aber statt der Matrix habe ich auch die ScaleTransform benutzt. Das Ergebnis ist immer das gleiche:

   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); 

ich verwendet habe, wie auch das folgende Idiom, aber mit gleichen Ergebnissen:

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

Antwort

1

Sie müssen die PictureBox ziehen, um die Dinge, die es zeigt auf dem Bildschirm in ein neuen Bitmap machen, die Sie dann sparen können!

Da es sich um die Image wird in der ursprünglichen Form und nichts, was man in dem Paint Ereignisse tat gespeichert werden, die eigentlich painst auf die Oberfläche der PictureBox wird gespeichert.

Also alles, das heißt die Image, speichern ein möglicherweise BackgroundImage und alles, was Sie in der Paint Ereignis ziehen Sie DrawToBitmap somehwere nennen würde.

Irgendwo bedeutet irgendwo sonst, nicht in der Paint Ereignis, da es das Paint Ereignis nennen die neue Bitmap, wodurch eine Endlosschleife zu schaffen ..

es nennen Sie etwas tun würde, wie dies:

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

Aber vielleicht ist das nicht wirklich das, was Sie wollen? Vielleicht möchten Sie tatsächlich die Image ändern? Verwenden Sie in diesem Fall nicht das Ereignis Paint überhaupt!

Statt etwas tun:

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(...); 
} 

Man könnte dies nennen von irgendwo, wo die Skalierung von ausgelöst wird.

Beachten Sie, dass die Skalierung wiederholt und jedes Mal von der vorher skalierten Version wird die Qualität eher schnell verschlechtern. Dazu skalieren Sie immer aus einer gespeicherten Version des Originals !!

Btw: Die Verwendung einer Matrix für die Skalierung macht keinen wirklichen Unterschied über ScaleTransform.

Aber wenn Sie wollen eine direkte Skalierung tun, warum nicht die DrawImage Überlastung benutzen, die zweiRectangles nimmt? Dies ist die häufigste Lösung, wenn alles, was Sie skalieren möchten und vielleicht andere Sachen zusätzlich zu ziehen ..:

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); 
} 

Und da gibt es die Skalierung BitmapKonstruktor:

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

, das ich empfehlen, wenn alles, was Sie wollen, ist die Image skalieren. Wie bei den anderen Lösungen wird es nicht die Image ändern angezeigt, bis Sie sie wieder in den PictureBox zuweisen ..:

pictureBox1.Image = bmp ; 

nicht von dem alten Bild ..

+0

Hallo vielen Dank für Ihre Antwort zu entsorgen Vergessen, Bin ich richtig zu sagen, wenn ich das bmpSave verwende, wird es das verzerrte Bild aber auch einen Bereich um das Bild bis zu den Grenzen der Bildbox speichern? (Bildbox ist 640x480), Bild ist weniger. Ziel ist es, nur das verzerrte Bild zu speichern, habe ich recht? – hephestos

+0

Ja, verwenden Sie in diesem Fall nicht die alte Größe der PictureBox für die neue Bitmap! – TaW

+0

Dear Taw ja der zweite Ausschnitt, den Sie gaben, ist näher an dem, was ich will. Wie könnte ich die Größe der neuen Bitmap neu berechnen? Da die Scaletransform nach der Erstellung von bmpsave kommt. Sie erstellen einen bmpSave mit "newwidth", aber tatsächlich kenne ich die newwidth nicht, bis ich scaletransform anrufe. Recht? – hephestos

0

Schon eine Weile, da ich mit GDI verwirrte, aber ich glaube, Sie müssen kopieren zurück zu die Bitmap hier.

g.DrawImage(bmp, scaledwidth, scaledheight); 

etwas wie das vor bmp.Save Versuchen

bearbeiten Apologies für das Sehen nicht, dass Sie auf die Bitmap wurden kopiert zurück. Vielleicht ist die Überladung, die das Ausgabe-Rechteck angibt, das, was Sie brauchen. Versuchen Sie eine DrawImage-Überladung mit dem Ziel Rect. https://msdn.microsoft.com/en-us/library/ms142040(v=vs.110).aspx