2010-12-15 69 views
3

Supposons que j'ai de très grandes toiles WPF (3000 X 4000).Découper une grande toile WPF dans de nombreuses petites images PNG

Je suis à la recherche de la meilleure façon de découper cette toile en un groupe de n par n images .png.

Des suggestions?

+0

Comment définissez-vous le mieux? Toute limite de mémoire ou de processeur? – BenMaddox

+0

Pour cela, je voudrais optimiser pour "plus facile". :-) Je veux utiliser Expression Blend pour créer des niveaux de jeu, puis couper le niveau de jeu. Png afin qu'ils puissent être aspirés dans un moteur de jeu. –

Répondre

4

ne suis pas sûr soit meilleur ou plus facile, mais est ici une façon :)

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

Merci, je vais essayer et marquer comme réponse une fois terminé. –

+0

@Jeff Weber: La méthode a-t-elle fonctionné pour vous? –

+0

Cela fait un moment, mais j'ai finalement fait un retour en arrière à cela. :-) Et oui. Ça marche. Merci. –

0

Vous pouvez faire quelque chose comme ça (pas mon code, pris de msdn sociale):

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

Elaborate sur ce code à l'article JPG divisé en carrés, vous pouvez utiliser une grille, la création par programme un tas de colonnes et de lignes, et en utilisant les propriétés attachées Grid.Row et Grid.Column sur les images par programme pour spécifier quelles images (tranchées) sont présentes.

+0

C'est assez proche de la réponse que je donnerais. Notez que la requête était pour une image png. – BenMaddox

+0

mon mauvais. Comme le souligne Meleak, vous pouvez utiliser la classe PngBitmapEncoder à la place de JpegBitmapEncoder. – Guy