I'm working with WPF, .NET 3.5, C#. I have jpeg file byte array in memory loaded from database, and I'd like to resize it to smaller size on memory.
input is jpeg file byte array in memory.
output is jpeg file byte array in memory, presenting resized jpeg image.
resize (and re-encode) should be done on memory, without using FILE.
resize can be done with bi-liner operation.
Please help me to do this.
A quick google search yields an MSDN article stating how to do this.
A simple example:
System.Drawing.Image source = System.Drawing.Image.FromFile(#"Z:\Temp\temp.bmp");
System.Drawing.Image destination = new System.Drawing.Bitmap(128, 128);
using (var g = Graphics.FromImage(destination))
{
g.InterpolationMode = InterpolationMode.HighQualityBilinear;
g.DrawImage(source, new System.Drawing.Rectangle(0,0,128,128), new System.Drawing.Rectangle(0, 0,source.Width, source.Height), GraphicsUnit.Pixel);
}
destination.Save(#"Z:\Temp\outpt.png", ImageFormat.Png);
Note my example uses files, but that is just for the loading and saving. All of the work is done in memory and you can load and save from memory streams if that suits your workflow better.
You also can use this function :
public static BitmapImage BitmapImageFromBitmapSourceResized(BitmapSource bitmapSource, int newWidth)
{
BmpBitmapEncoder encoder = new BmpBitmapEncoder();
MemoryStream memoryStream = new MemoryStream();
BitmapImage bImg = new BitmapImage();
encoder.Frames.Add(BitmapFrame.Create(bitmapSource));
encoder.Save(memoryStream);
bImg.BeginInit();
bImg.StreamSource = new MemoryStream(memoryStream.ToArray());
bImg.DecodePixelWidth = newWidth;
bImg.EndInit();
memoryStream.Close();
return bImg;
}
The use of this function is recommanded by microsoft, because the image is not saved in its original size but with the size newWidth. It can avoid you memory overflow if the user enter huge images.
Related
My DB holds byte[] data for different images, png and bmp extensions work fine but strangely images with jpeg extension seem to be rotated 90deg anti-clockwise. I can only assume this is a problem with the encoder and decoder. The jpegs are encoded by an iPhone and decoded in a silverlight app using the following code:
using (MemoryStream ms = new MemoryStream(bImage, 0, bImage.Length))
{
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.SetSource(ms);
img.Source = bitmapImage;
tempList.Add(img);
}
For bmps I use the following:
ExtendedImage image = new ExtendedImage();
var bmp = new BmpDecoder();
var png = new PngEncoder();
try
{
bmp.Decode(image, new MemoryStream(bImage));
}
catch (NotSupportedException)
{
new MessageWindow("Incorrect image format", DisplayStrings.ErrorDisplay, MessageButtons.OK, MessageImage.Error).Show();
continue;
}
MemoryStream ms = new MemoryStream();
png.Encode(image, ms);
BitmapImage bi = new BitmapImage();
bi.SetSource(new MemoryStream(ms.ToArray()));
img.Source = bi;
tempList.Add(img);
Neither option will display the image in the correct orientation. Am I missing a specific jpeg decoder class?
EDIT
As it turns out, the iPhone was doing something strange to the byte array. As a result: rotating the image on the iPhone before saving apparently does nothing to the image on the iPhone visibly but uploads the correct orientation of image onto the server. Why this happens is anyone's guess but it is so.
Solved by rotating the image on the iPhone before uploading the byte array to the server. This saves the image with the correct orientation and apparently causes no visible difference to the original image on the iPhone.
I have a wcf service which returns a bmp in byte[]. However Silverlight's Image control doesnt support displaying bmp's so i need to convert the bmp byte[] to png or jpg byte[]. Is there a library out there which does this conversion? Or any other way of displaying the bmp byte[] on the silverlight client?
Thanks!
Update1
In order to achieve the conversion I would have done something like this in .NET
private byte[] ConvertBmpToJpeg(byte[] bmp)
{
using (System.Drawing.Image image = System.Drawing.Image.FromStream(new MemoryStream(bmp)))
{
MemoryStream ms = new MemoryStream();
image.Save(ms, ImageFormat.Jpeg);
return ms.ToArray();
}
}
Since System.Drawing is not available in Silverlight, how do I achieve what the code does above in Silverlight?
Answer
using the library mentioned by dj kraze below-
ExtendedImage img = new ExtendedImage();
var bd = new BmpDecoder();
var je = new JpegEncoder();
bd.Decode(img, new MemoryStream(bitmapBytes));
MemoryStream ms = new MemoryStream();
je.Encode(img, ms);
BitmapImage bi = new BitmapImage();
bi.SetSource(new MemoryStream(ms.ToArray()));
display_ScreenShot.Source = bi;
Here is an even easier way of doing it..
This site may help out a lot
Image Converting
I'm having some trouble reading JPEG files in my class. I need to load metadata and bitmap from a JPEG file. So far, I have this:
public void Load()
{
using (Stream imageStream = File.Open(this.FilePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
BitmapDecoder decoder = new JpegBitmapDecoder(imageStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
BitmapSource source = decoder.Frames[0];
// load metadata
this.metadata = source.Metadata as BitmapMetadata;
// prepare buffer
int octetsPerPixel = source.Format.BitsPerPixel / 8;
byte[] pixelBuffer = new byte[source.PixelWidth * source.PixelHeight * octetsPerPixel];
source.CopyPixels(pixelBuffer, source.PixelWidth * octetsPerPixel, 0);
Stream pixelStream = new MemoryStream(pixelBuffer);
// load bitmap
this.bitmap = new Bitmap(pixelStream); // throws ArgumentException
}
this.status = PhotoStatus.Loaded;
}
But the Bitmap constructor throws an ArgumentException when trying to create a Bitmap instance from a stream.
The documentation says:
System.ArgumentException
stream does not contain image data or is null.
-or-
stream contains a PNG image file with a single dimension greater than 65,535 pixels.
I'm not sure, what I did wrong. Can you please help me?
You're using the Bitmap constructor which is usually used to load an image file in a known format - JPEG, PNG etc. Instead, you've just got a bunch of bytes, and you're not telling it anything about the format you want to use them in.
It's not clear why you want to use BitmapDecoder and BitmapSource at all - why aren't you just using:
Stream imageStream = File.Open(this.FilePath, FileMode.Open,
FileAccess.Read, FileShare.Read));
this.bitmap = new Bitmap(imageStream);
Note that you mustn't use a using statement here - the Bitmap "owns" the stream after you've called the constructor.
Aside from all of this, you seem to be trying to mix WPF and WinForms ideas of images, which I suspect is a generally bad idea :(
I have found how to do this in .NET 4.0, but I think JpegBitmapEncoder doesn't exist in Silverlight:
MemoryStream memStream = new MemoryStream();
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(imageC));
encoder.Save(memStream);
var bytes = memStream.GetBuffer();
How can I convert an image to bytes[] in silverlight?
UPDATE:
I have a Contact model, which has a Photo property. Whenever I add a new Contact, I would like to load a local default Image and convert it and set the Photo property to it.
var bitmapImage = new BitmapImage
{
UriSource = new Uri("pack://application:,,,/xxx;component/Images/default.JPG")
};
var image = new Image{Source = bitmapImage};
Is this the correct way to load an image in first place?
Use
myImage.Save(memStream, ImageFormat.Jpeg);
return memStream.ToArray();
UPDATE
OK it turns out that the image is a BitmapImage.
It seems that BitmapImage does not expose the functionality to save the image. The solution is to get the image from the embedded resource:
Stream s = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourcePath);
byte[] buffer = new byte[s.Length];
s.Read(buffer, 0, buffer.Length);
Have a look at this library: Imagetools
It contains some nice utilities and jpg and png encoders,
I also want to display in a datagridview. I tried searching here and tried for hours to do it in all kinds of ways turning it to bitmap through drawtobitmap method and then turning it to a bite array and saving it to database
the database shows me 0X89 what does it mean?
And it doesn't show me the image on a datagridview
Can someone just give me a code that works and I'll improvise thank you very much.
For Saving
Bitmap bmp =new Bitmap(panel1.Width,panel1.Height);
panel1.DrawToBitmap(bmp, panel1.Bounds);
System.IO.MemoryStream ms = new System.IO.MemoryStream();
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
byte[] result = new byte[ms.Length];
ms.Seek(0,System.IO.SeekOrigin.Begin);
ms.Read(result, 0, result.Length);
and save result to your sqlserver table
and to Convert Byte array to image use this
public static Bitmap ConvertBinaryDataToImage(byte[] buffer)
{
System.IO.MemoryStream ms = new System.IO.MemoryStream(buffer);
Bitmap bmap = new Bitmap(ms);
return bmap;
}