2016-04-24 8 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 рисовать вещи он показывает на экране в нового Bitmap, который затем можно сохранить!

Как это Image будет сохранен в первоначальном виде, и ничего вы сделали в Paint события, которое фактически painst на поверхность PictureBox будет сохранена.

Таким образом, чтобы сохранить все, т.е. Image, возможно, BackgroundImage и все вы рисуете в Paint случае вы бы назвали DrawToBitmap somehwere.

Где-то значит где-то , а не в Paint случае, как это будет вызывать Paint событие, чтобы создать новый Bitmap, вызывая бесконечный цикл ..

Для вызова вы могли бы сделать что-то вроде это:

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

Возможно, это не совсем то, что вы хотите? Может быть, вы действительно хотите изменить Image? В этом случае do не использовать событие 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.

Но если вы хотите, чтобы сделать прямое масштабирование почему бы не использовать 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. Как и другие решения не изменит Image отображаться, пока вы не назначите его обратно в PictureBox ..:

pictureBox1.Image = bmp ; 

Не забудьте избавиться от старого изображения ..

+0

Привет спасибо за Ваш ответ, могу ли я сказать, что если я использую этот bmpSave, он сохранит искаженное изображение, а также область вокруг изображения до границ изображения? (картинка - 640x480), изображение меньше. цель состоит в том, чтобы сохранить только искаженное изображение, верно? – hephestos

+0

Да, в этом случае не используйте старый размер PictureBox для нового Bitmap! – TaW

+0

Дорогой Тау, второй фрагмент, который вы дали, ближе к тому, что я хочу. Что я могу пересчитать размер нового растрового изображения? Поскольку scaletransform возникает после создания bmpsave. Вы создаете bmpSave с «newwidth», но на самом деле я не знаю новую ширину, пока не назову scaletransform. Правильно? – hephestos

0

Давненько я перепутались с GDI, но я думаю, что вам нужно скопировать обратно Растровое изображение здесь.

g.DrawImage(bmp, scaledwidth, scaledheight); 

Попробуйте что-нибудь подобное раньше bmp.Save

Edit Извинения для не видя, что вы копировали обратно в растровом изображении. Возможно, перегрузка, которая задает выходной прямоугольник, вам нужна. Попробуйте перегрузку DrawImage, у которой есть Rect места назначения. https://msdn.microsoft.com/en-us/library/ms142040(v=vs.110).aspx