UIElement to image file (WP7) - c#

I have a StackPanel which includes a few Rectangles that I want put to an image file (e.g. PNG). I'm developing this on Windows Phone 7 and most of the information I found on the internet wasn't applicable (I think) to WP7.
I think the System.Windows.Media.Imaging namespace is the key to this, but I'm not sure where to begin.
This is basically what I want to do:
StackPanel stack = new StackPanel();
List<Rectangle> recList = new List<Rectangle>();
add some rectangles to recList
foreach(var x in recList)
stack.Children.Add(x);
then save the stackpanel to an image file...

You can use a WriteableBitmap to save the image.
WriteableBitmap wb = new WriteableBitmap(stack, null);
MemoryStream ms = new MemoryStream();
wb.SaveJpeg(ms, myWidth, myHeight, 0, 100);
You can change the MemoryStream to be an Isolated Storage stream instead. If you want to display the above MemoryStream in an Image control:
BitmapImage bmp = new BitmapImage();
bmp.SetSource(ms);
image1.Source = bmp;
Or, saving to Isolated Storage:
using (var isoFileStream = new IsolatedStorageFileStream("myPicture.jpg", FileMode.OpenOrCreate, IsolatedStorageFile.GetUserStoreForApplication()))
{
wb.SaveJpeg(isoFileStream, myWidth, myHeight, 0, 100);
}

Related

Imagetool Grid to PNG silverlight

I have a project using Imagetools library transfer grid to PNG image, this is
part of the picture :
image (bad one)
image2 (good one)
it's textblock inside grid, and set color
looks normal when show on the screen, but when output to PNG image
it will looks like this, with black line under
here is my code
WriteableBitmap bitmap = new WriteableBitmap((int)tempGrid.Width, (int)tempGrid.Height);
bitmap.Render(tempGrid, new TranslateTransform());
bitmap.Invalidate();
ExtendedImage img = bitmap.ToImage() ;
MemoryStream ms = new MemoryStream() ;
PngEncoder encoder = new PngEncoder() ;
encoder.Encode(img, ms);
ms.Position = 0;
long bytesRead = stream.Read(binaryData, 0, (int)stream.Length);
string base64String = System.Convert.ToBase64String(binaryData, 0,
binaryData.Length);
then I write the bas64 string to png image
did I miss any setting ?
is it possible to get rid of the black line ?
thanks

Converting FileStream to WriteableBitmap to JPEG to Byte Array for SSRS

I'm trying to save an Image to SQL Server so SSRS can read it. I need to convert to WriteableBitmap (and possibly JPEG?) so I can make changes to the image size before saving. However, when I try to pull the converted image out of SQL Server, it will not render in SSRS at all. What am I doing wrong?
byte[] m_Bytes = ReadToEnd(fileStream); //this works fine
WriteableBitmap bmp1 = new WriteableBitmap(166, 166);
bmp1.FromByteArray(m_Bytes); //this works fine
ExtendedImage image = bmp1.ToImage();
MemoryStream stream = new MemoryStream();
ImageTools.IO.Encoders.AddEncoder<JpegEncoder>();
JpegEncoder encoder = new JpegEncoder();
encoder.Encode(image, stream);
BitmapImage img = new BitmapImage();
img.SetSource(stream);
WriteableBitmap bmp2 = new WriteableBitmap(img);
byte[] buffer1 = bmp2.ToByteArray();
CurrentOrder.CompanyImage = buffer1; //this does save a byte array but it will not render in SSRS. If I set buffer1 to bmp1.ToByteArray() then it works fine but I am still unable to resize it using the resize method in WriteableEx without it not rendering in SSRS.
This is another try at the same thing and it won't render either:
And this is simpler and won't work either:
byte[] m_Bytes = ReadToEnd(fileStream);
WriteableBitmap bmp1 = new WriteableBitmap(166, 166);
bmp1.FromByteArray(m_Bytes);
WriteableBitmap resizedImage = bmp1.Resize(25, 25, WriteableBitmapExtensions.Interpolation.Bilinear);
byte[] buffer1 = resizedImage.ToByteArray();
CurrentOrder.CompanyImage = buffer1;
What you want is to resize 166x166 (or 25x25), export as byte[] and reload picture from this byte array ?
Can you try with BitmapImage ?
BitmapImage image = new BitmapImage();
image.SetSource(fileStream);
WriteableBitmap bitmap = new WriteableBitmap(image);
WriteableBitmap resizedBitmap = bitmap.Resize(25, 25, WriteableBitmapExtensions.Interpolation.Bilinear);
CurrentOrder.CompanyImage = resizedBitmap.ToByteArray();

How do I save WriteableBitmap to a file with a specific size with Windows Forms?

I am using the following code in Windows Phone 7 to save a JPEG image with a specific size:
WriteableBitmap wBitmap = new WriteableBitmap(resizedImage);
MemoryStream m = new MemoryStream();
wBitmap.SaveJpeg(m, h, w, 0, 100);
I am getting the error:
"WritableBitmap does contain a definition for SaveJpeg"
How do I do the same thing on a desktop Windows Forms app with C#?
Here's how you would do this (okay, was facetious, now am srs) using the JpegBitmapEncoder
//Assuming resizedImage is a BitmapSource
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(resizedImage));
using(var stream = File.Open(theAristocratsFilename))
encoder.Save(stream);

error in editing byte[] from images

I'm trying to do image processing on wp7,
and now i finished convertImagetoBytes and convertByteToBitmapImage.
I suppose I can change the values in the byte array to do some image processing work,
but it turns out to be a black image in the picturebox.
(Now I just wanna process .jpg images)
convertImagetoBytes
byte[] data = null;
using (MemoryStream stream = new MemoryStream())
{
WriteableBitmap wBitmap = new WriteableBitmap(bitmapImage);
wBitmap.SaveJpeg(stream, wBitmap.PixelWidth, wBitmap.PixelHeight, 0, 100);
stream.Seek(0, SeekOrigin.Begin);
data = stream.GetBuffer();
}
convertBytestoImage
MemoryStream stream = new MemoryStream(bytes);
stream.Position = 0;
BitmapImage bi = new BitmapImage();
bi.SetSource(stream);
return bi;
now if i change the values in the byte array,just like this(grayscale)
for (int i = 0; i < bytesCount; i+=4)
{
colorTemp = data[i+2];
data[i+1 ] =data[i+2]= data[i + 3] = (byte)colorTemp;
}
the image turns out to be black.
You've saved it as a JPEG - but you appear to be trying to change it as if it were raw data. You can't just mess around with the data of a JPEG file to fake greyscale.
By the way, you should use stream.ToArray instead of stream.GetBuffer() as the latter will usually be larger than the real data.
You should also look into using René Schulte's WriteableBitmapEx library.
And consider reading this article about a Windows Phone Picture Effects Application

Rendering an image at runtime in WPF

I have posted several questions related to this problem I am having and I am starting to believe this cannot be done. Here is the back story.
I have an ASP.NET application from which I want to generate a .png image. This .png image needs to be constructed from either XAML or a WPF Visual Tree. Because of this, I must generate the .png image in an STA thread. Everything works fine until my XAML/WPF Visual Tree includes an Image (as in a System.Windows.Controls.Image). My .png file gets generated correctly except the Image element does not show the referenced picture. The referenced picture is located at a remote URL. No errors or exceptions are thrown.
How do I create a .png image from some XAML/WPF Visual Tree that includes a System.Windows.Controls.Image element? The resulting .png must include the picture referenced in the Image element. I have tried the following code in a variety of ways:
string address = "http://imgtops.sourceforge.net/bakeoff/o-png24.png";
WebClient webClient = new WebClient();
byte[] imageContent = webClient.DownloadData(address);
Image image = new Image();
using (MemoryStream memoryStream = new MemoryStream(imageContent))
{
BitmapImage imageSource = new BitmapImage();
imageSource.BeginInit();
imageSource.StreamSource = memoryStream;
imageSource.EndInit();
image.Source = imageSource;
}
// Set the size
image.Height = 200;
image.Width = 300;
// Position the Image within a Canvas
image.SetValue(Canvas.TopProperty, 1.0);
image.SetValue(Canvas.LeftProperty, 1.0);
Canvas canvas = new Canvas();
canvas.Height = 200;
canvas.Width = 300;
canvas.Background = new SolidColorBrush(Colors.Purple);
canvas.Children.Add(image);
// Create the area
Size availableSize = new Size(300, 200);
frameworkElement.Measure(availableSize);
frameworkElement.Arrange(new Rect(availableSize));
// Convert the WPF representation to a PNG file
BitmapSource bitmap = RenderToBitmap(frameworkElement);
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmap));
// Generate the .png
FileStream fileStream = new FileStream(filename, FileMode.Create);
encoder.Save(fileStream);
public BitmapSource RenderToBitmap(FrameworkElement target)
{
int actualWidth = 300;
int actualHeight = 200;
Rect boundary = VisualTreeHelper.GetDescendantBounds(target);
RenderTargetBitmap renderBitmap = new RenderTargetBitmap(actualWidth, actualHeight, 96, 96, PixelFormats.Pbgra32);
DrawingVisual drawingVisual = new DrawingVisual();
using (DrawingContext context = drawingVisual.RenderOpen())
{
VisualBrush visualBrush = new VisualBrush(target);
context.DrawRectangle(visualBrush, null, new Rect(new Point(), boundary.Size));
}
renderBitmap.Render(drawingVisual);
return renderBitmap;
}
Thank you for your help.
You are rendering the output bitmap correctly, it is just the input bitmap you are screwwing up :).
BitmapImage requires access to the StreamSource property until it fires the DownloadCompleted event, but the 'using' block Dispose()s of the MemoryStream before it has a chance! You could simply unwrap the MemoryStream from the using block and let the GC handle it (if you do, I would recommend setting the BitmapImage.CacheOption to BitmapCacheOption.None, so it uses the stream directly, rather than a copy), but I would use the UriSource property and wait for the DownloadComplete event before rendering.

Categories

Resources