2010-12-15 7 views
3

Angenommen, ich habe sehr große (3000 X 4000) WPF Canvas.Scheibe große WPF Canvas in viele kleine PNG-Bilder

Ich bin auf der Suche nach der besten Möglichkeit, diese Leinwand in eine Reihe von n by n .png Bildkacheln zu schneiden.

Irgendwelche Vorschläge?

+0

Wie definieren Sie am besten? Irgendwelche Speicher- oder CPU-Einschränkungen? – BenMaddox

+0

Dafür möchte ich für "einfachste" optimieren. :-) Ich möchte Expression Blend verwenden, um Spielstufen zu erstellen und dann das Spielniveau in .png aufzuteilen, damit sie in eine Spielengine gesaugt werden können. –

Antwort

4

Nicht sicher entweder am besten oder am einfachsten, aber hier ist ein Weg :)

private void SaveFrameworkElement(FrameworkElement frameworkElement) 
{ 
    BitmapImage bitmapImage = VisualToBitmapImage(frameworkElement); 
    for (int startX = 0; startX <= 400; startX += 100) 
    { 
     for (int startY = 0; startY <= 100; startY += 100) 
     { 
      SaveImage(bitmapImage, startX, startY, 100, 100, "C:\\CutImage_" + startX.ToString() + "-" + startY.ToString() + ".png"); 
     } 
    } 
} 

public BitmapImage VisualToBitmapImage(FrameworkElement frameworkElement) 
{ 
    RenderTargetBitmap rtb = new RenderTargetBitmap((int)frameworkElement.ActualWidth, 
                (int)frameworkElement.ActualHeight, 
                96d, 
                96d, 
                PixelFormats.Default); 
    rtb.Render(frameworkElement); 

    MemoryStream stream = new MemoryStream(); 
    PngBitmapEncoder encoder = new PngBitmapEncoder(); 
    encoder.Frames.Add(BitmapFrame.Create(rtb)); 
    encoder.Save(stream); 

    BitmapImage bitmapImage = new BitmapImage(); 
    bitmapImage.BeginInit(); 
    bitmapImage.StreamSource = stream; 
    bitmapImage.EndInit(); 

    return bitmapImage;    
} 
public void SaveImage(BitmapImage sourceImage, 
         int startX, 
         int startY, 
         int width, 
         int height, 
         string filePath) 
{ 
    TransformGroup transformGroup = new TransformGroup(); 
    TranslateTransform translateTransform = new TranslateTransform(); 
    translateTransform.X = -startX; 
    translateTransform.Y = -startY; 
    transformGroup.Children.Add(translateTransform); 

    DrawingVisual vis = new DrawingVisual(); 
    DrawingContext cont = vis.RenderOpen(); 
    cont.PushTransform(transformGroup); 
    cont.DrawImage(sourceImage, new Rect(new Size(sourceImage.PixelWidth, sourceImage.PixelHeight))); 
    cont.Close(); 

    RenderTargetBitmap rtb = new RenderTargetBitmap(width, height, 96d, 96d, PixelFormats.Default); 
    rtb.Render(vis); 

    FileStream stream = new FileStream(filePath, FileMode.Create); 
    PngBitmapEncoder encoder = new PngBitmapEncoder(); 
    encoder.Frames.Add(BitmapFrame.Create(rtb)); 
    encoder.Save(stream); 
    stream.Close(); 
} 
+0

Danke, versuchen Sie es und markieren Sie als Antwort, wenn Sie fertig sind. –

+0

@Jeff Weber: Hat die Methode für dich funktioniert? –

+0

Es ist schon eine Weile her, aber ich habe mich endlich wieder daran gewöhnt. :-) Und ja. Es klappt. Vielen Dank. –

0

Sie können so etwas wie diese (nicht meinen Code, von Msdn sozialen genommen) tun:

public static RenderTargetBitmap GetJpgImage(UIElement targetUIElement, double scale, int quality) 
{ 
double actualHeight = targetUIElement.RenderSize.Height; 
double actualWidth = targetUIElement.RenderSize.Width; 

double renderedHeight = actualHeight * scale; 
double renderedWidth = actualWidth * scale; 

RenderTargetBitmap renderTarget = new RenderTargetBitmap((int)renderedWidth, (int)renderedHeight, 96, 96, PixelFormats.Pbgra32); 
VisualBrush sourceBrush = new VisualBrush(targetUIElement); 

DrawingVisual drawingVisual = new DrawingVisual(); 
DrawingContext drawingContext = drawingVisual.RenderOpen(); 

using (drawingContext) 
{ 
    drawingContext.PushTransform(new ScaleTransform(scale, scale)); 
    drawingContext.DrawRectangle(sourceBrush, null, new Rect(new System.Windows.Point(0, 0), new System.Windows.Point(actualWidth, actualHeight))); 
} 
renderTarget.Render(drawingVisual); 

JpegBitmapEncoder jpgEncoder = new JpegBitmapEncoder(); 
jpgEncoder.QualityLevel = quality; 
jpgEncoder.Frames.Add(BitmapFrame.Create(renderTarget)); 
MemoryStream memoryStream = new MemoryStream(); 
jpgEncoder.Save(memoryStream); 

File.WriteAllBytes(@"D:\a.jpg", memoryStream.ToArray()); 

return renderTarget; 
} 

Aufwendige an diesem Code Abschnitt aus der JPG in Quadrate, dann können Sie ein Gitter verwenden, programmatisch zu schaffen eine Reihe von Spalten und Zeilen und die programmierten Eigenschaften Grid.Row und Grid.Column für die Bilder, um anzugeben, welche (geschnittenen) Bilder vorhanden sind.

+0

Das ist ziemlich nah an der Antwort, die ich geben würde. Beachten Sie, dass die Anforderung für ein PNG-Bild galt. – BenMaddox

+0

mein schlechtes. Wie Meleak darauf hinweist, können Sie die PngBitmapEncoder-Klasse anstelle von JpegBitmapEncoder verwenden. – Guy

Verwandte Themen