2013-04-03 17 views
5

Mam obraz i chcę go ponownie rozmiar i trzeba zapisać w moim folderze temp.Zmień rozmiar obrazu w WPF

co próbowałem to jak poniżej:

UIElement uie = CanvasHost.Child; 
int width = 800; 
int height = (int)((width/(double)((FrameworkElement)uie).Width) * (int)((FrameworkElement)uie).Height);   
RenderTargetBitmap rtb = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32); 
rtb.Render(uie); 

string dir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\temp\"; 
if (!Directory.Exists(dir)) 
     Directory.CreateDirectory(dir); 

long size = 0; 

string filePath = dir + DateTime.Now.Ticks.ToString() + (isPng ? ".png" : ".jpg"); 
BitmapEncoder enc = null; 

using (FileStream fs = File.Create(filePath)) 
{ 
    if (isPng) 
     enc = new PngBitmapEncoder(); 
    else 
     enc = new JpegBitmapEncoder(); 

    enc.Frames.Add(BitmapFrame.Create(rtb)); 
    enc.Save(fs); 

    size = fs.Length; 
} 

ale gdy tworzę obraz tak oszczędza część obrazu w folderze Temp. (Jak pokazano w powyższym pic)

enter image description here

jak mogę ponownie w pełnym rozmiarze zdjęcie? co tu przegapiłem?

EDIT: Jak wspomniano w powyższym odpowiedź jak wspomniano przez Erti-Chris Eelmaa mam zmienić w poniższy kod. i to działa ......

UIElement uie = CanvasHost.Child; 
int width = DataCache.Instance.CurrentProject.MaxPhotoEdgeSize; 
int height = (int)((width/(double)((FrameworkElement)uie).Width) * (int)((FrameworkElement)uie).Height); 

RenderTargetBitmap rtb = new RenderTargetBitmap((int)((FrameworkElement)uie).Width, (int)((FrameworkElement)uie).Height, 96, 96, PixelFormats.Pbgra32); 
rtb.Render(uie); 

ImageSource im = (ImageSource)rtb.Clone(); 
BitmapFrame bp = CreateResizedImage(im, width, height, 1); //method suggested by Erti-Chris Eelmaa 
string dir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\temp\"; 

if (!Directory.Exists(dir)) 
    Directory.CreateDirectory(dir); 

long size = 0; 

string filePath = dir + DateTime.Now.Ticks.ToString() + (isPng ? ".png" : ".jpg"); 
BitmapEncoder enc = null; 

using (FileStream fs = File.Create(filePath)) 
{ 
    if (isPng) 
     enc = new PngBitmapEncoder(); 
    else 
     enc = new JpegBitmapEncoder(); 


    enc.Frames.Add(BitmapFrame.Create(bp)); 
    enc.Save(fs); 

    size = fs.Length; 
} 
+0

Musisz zmienić wysokość i szerokość bitmapy po stworzeniu. To, co tu robisz, polega na tym, że tworzysz nową bitmapę o małych rozmiarach i wypełniasz ją oryginalnym obrazem bez zmiany rozmiaru. Tworzysz bitmapę o oryginalnym rozmiarze, a następnie używasz jej wysokości i szerokości do zmiany jej rozmiaru. –

+0

@FaisalHafeez możesz wyjaśnić więcej na ten temat? jak mogę to zmienić? – DevT

+0

Tutaj tworzysz bitmapę o wielkości i wysokości. Teraz ma on mniejszy rozmiar. Ale kiedy wypełnisz go obrazem, skopiuje on tylko część obrazu (dzieje się to w twoim przypadku). Aby to zaimplementować, musisz użyć innej funkcji. –

Odpowiedz

14

Wystarczy użyć tej metody, aby uzyskać BitmapFrame, po tym można po prostu zapisać go na dysk twardy przy użyciu PngBitmapEncoder.

private static BitmapFrame CreateResizedImage(ImageSource source, int width, int height, int margin) 
{ 
    var rect = new Rect(margin, margin, width - margin * 2, height - margin * 2); 

    var group = new DrawingGroup(); 
    RenderOptions.SetBitmapScalingMode(group, BitmapScalingMode.HighQuality); 
    group.Children.Add(new ImageDrawing(source, rect)); 

    var drawingVisual = new DrawingVisual(); 
    using (var drawingContext = drawingVisual.RenderOpen()) 
     drawingContext.DrawDrawing(group); 

    var resizedImage = new RenderTargetBitmap(
     width, height,   // Resized dimensions 
     96, 96,    // Default DPI values 
     PixelFormats.Default); // Default pixel format 
    resizedImage.Render(drawingVisual); 

    return BitmapFrame.Create(resizedImage); 
} 
+0

Użyłem tej funkcji i masz na myśli zamiast 'RenderTargetBitmap' używać' PngBitmapEncoder' r8? jeśli tak, w jaki sposób mogę zapisać 'enc.Frames.Add (BitmapFrame.Create (rtb));' ponieważ tutaj potrzebował obiektu wizualnego. – DevT

+0

Edytowałem moje pytanie. kiedy zapisuję w ten sposób, zapisuje się czarny obraz. dlaczego? – DevT

+0

w stanie rozwiązać problem. dzięki.... – DevT

14

Co do rozmiaru się, używając WPF na TransformedBitmap wydaje się nieco łatwiejsze:

var bitmap = new TransformedBitmap(bitmapSource, 
    new ScaleTransform(
     newWidth/bitmapSource.PixelWidth, 
     newHeight/bitmapSource.PixelHeight));