Image cropped in rendering with GDI+ - c#

I am using my own class for image processing , like load , thumbnail , ....
In general , this code create images object;
Bitmap result = new Bitmap(width, height, PixelFormat.Format32bppArgb);
and this code post it to response object to show in browser.
HttpContext.Current.Response.AddHeader("ContentType", "image/png");
using (MemoryStream memStream = new MemoryStream())
{
memStream.Seek(0, SeekOrigin.Begin);
Result.Save(memStream, ImageFormat.Png);
memStream.WriteTo(HttpContext.Current.Response.OutputStream);
}
Result.Dispose();
In some cases , the browser(s) show the correct image but sometimes show the cropped image like this.
Is this image breaking related to my code or related to browsers ?

If the image format is PNG, you need to use an intermediate MemoryStream (because PNGs require a seekable stream to be saved). Try using jpg file to see that your code is working.
Check ASP.NET [Image Handler]

Related

Set image resolution

I have array of image bytes and I would like to set resolution. Original image can be JPEG, PNG, BMP. Output - PNG. I am using ImageMagic to convert image and do some manipulations.
using (var image = this.Convert(originalImage, height, width))
using (var stream = new MemoryStream())
{
image.Quality = 90;
image.Write(stream, MagickFormat.Png);
return stream.GetBuffer();
}
I tryed to modify image.GetExifProfile, but has no success (at least for PNG images).
I can't use any comandline tool (like ImageMagic or ExifTool) here.
There are 3 exiff tags I need to modify
XResolution
YResolution
ResolutionUnit
I can successfully achieve this with bitmap, but it also resource overhead (need to create MemoryStream ...).
I have found some Pdf specification, but it will consume time to make it all work.
Does any can point me to right direction?
Thanks.

Preserving Image quality

I have a winform C# desktop application.
I have a constant stream of jpegs coming in.
I am comparing the current image with the previous 1.
By using a 3rd party tool - Emgu - I can create a new image that contains just the differences.
I then convert that image to a memory stream and then to a byte array.
In the receiving application I take this byte array and load the image via a memory stream using these bytes.
The trouble is that the image degrades quite a lot.
If I save the image to the hard drive before converting it to a memory stream on the client side the quality of the image is good.
The problem lies when i load it as a memory stream.
I encode it as jpeg.
If I encode it as a PNG before sending to the server the quality is good again.
The trouble with encoding to PNG the size in the byte array shoots up.
What my intention was all along was to reduce the number of bytes I have to upload to improve response time.
Am I doing something wrong or can this not be done?
This is my code:
Bitmap imgContainingDifference
= GetDiffFromEmgu(CurrentJpegImage, PreviousJpegImage);
using (System.IO.MemoryStream msIn = new System.IO.MemoryStream())
{
holding.Save(msIn, System.Drawing.Imaging.ImageFormat.Jpeg);
data = msIn.ToArray();
}
//test here
using (System.IO.MemoryStream msOut = new System.IO.MemoryStream(_data))
{
Bitmap testIMG = (Bitmap)Image.FromStream(msOut);
}
//result is image is poor/degrades
If I do this instead:
using (System.IO.MemoryStream msIn = new System.IO.MemoryStream())
{
holding.Save(msIn, System.Drawing.Imaging.ImageFormat.Png);
data = msIn.ToArray();
}
using (System.IO.MemoryStream msOut = new System.IO.MemoryStream(_data))
{
Bitmap testIMG = (Bitmap)Image.FromStream(msOut);
}
//Image is good BUT the size of the byte array is
//10 times the size of the CurrentFrame right at the start.
This is what the image looks like when using the kid suggestion from :
I have now tried using a encoder from the kind suggestion from #MagnatLU and I also get the same quality of image if I use FreeImage.Net.
You can set JPEG compression level when encoding your file to value that is the best empirical tradeoff between quality and size.

saved bitmap is larger than the bitmap i read C#

Actually the bitmap created has a file size larger than the input bitmap. I opened the bitmap that was created and it looked completely different to what i inputted. why is that ?
I read a bitmap through FileStream and then i write its contents to a bitmap object.Next i write it as a bitmap file onto harddisk. I cant figure out why the output bitmap is larger than the input bitmap. Could someone please help me.
Bitmap.Save (Image.Save) will, by default, save the image as in PNG format.
If you call Save with an ImageFormat value, you should get your bitmap.
b.Save("test.bmp", ImageFormat.Bmp);
When a bitmap file is created there is often padding added to each row to ensure that each row is a multiple of 4 bytes. When you read the bitmap file into a FileStream the padding is also read.
This can mean that the FileStream is larger than expected and when you write it to a bitmap it will display unexpected behaviour since when you write it to a new Bitmap it treats the padding as if it were your image data.
Sorry I did not understand your problem well. But did you try like this?
private System.Drawing.Bitmap readfromFile(string filename)
{
FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read);
byte[] bytes = new byte[fs.Length];
fs.Read(bytes, 0, Convert.ToInt32(fs.Length));
MemoryStream ms = new MemoryStream(bytes);
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(ms);
return bmp;
}
and saved like this:
System.Drawing.Bitmap bmp = readfromFile("xxxx --- Path");
bmp.Save("test.bmp", ImageFormat.Bmp);
I tried that and it always returns the same image for me.

.NET BitmapSource is locking file

I am using this C# code to access an image file in order to read metadata from it.
BitmapSource img = BitmapFrame.Create(uri);
Unfortunately the image file specified by uri becomes locked until the program ends. How do I prevent the image from being locked?
maybe this could help ?
edit
BitmapSource img = BitmapFrame.Create(uri,BitmapCreateOptions.None,BitmapCacheOption.OnLoad);
BitmapCreateOptions.None = default option
BitmapCacheOption.OnLoad = Caches the entire image into memory at load time. All requests for image data are filled from the memory store.
from here
If you want to be able to delete/change the file immediately afterwards, read the whole file into memory, and then give it the MemoryStream instead. For example:
MemoryStream data = new MemoryStream(File.ReadAllBytes(file));
BitmapSource bitmap = BitmapFrame.Create(data);
You can also use generic stream:
Stream stream = File.OpenRead(filename);
Bitmap template = new Bitmap(stream); // or (Bitmap) Bitmap.FromStream(stream)
stream.Close();

WPF BitmapSource ImageSource

I am binding an Image.Source property to the result of the property shown below.
public BitmapSource MyImageSource
{
get
{
BitmapSource source = null;
PngBitmapDecoder decoder;
using (var stream = new FileStream(#"C:\Temp\logo.png", FileMode.Open, FileAccess.Read, FileShare.Read))
{
decoder = new PngBitmapDecoder(stream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None);
if (decoder.Frames != null && decoder.Frames.Count > 0)
source = decoder.Frames[0];
}
return source;
}
}
For some reason this is failing during the rendering of the image (Deep in the PresentationCore assembly). I am certain the image is not corrupt as I can successfully show the same image w/o the binding
<Image Name="FooImage" Source="/logo.png" />
I have to bind the image source in code because I will eventually be creating the image stream from a base64 string.
Anyone know if this is a bug w/ WPF? or am I doing something incorrectly?
The problem was the BitmapCacheOption option, changing to BitmapCacheOption.OnLoad works.
With BitmapCacheOption.None the BitmapSource isn’t decoded until the image is rendered, but the stream with the png in it is already disposed at that point. If you cache OnLoad, it’ll decode right away and cache the results, rather than trying to decode later when the stream no longer exists.
Also, have you tried just using a BitmapImage to load the image? It works fine with PNG, BMP, and JPEG.
It's also a specialized type of BitmapSource, so you could just replace your code in your property with this:
BitmapImage img = new BitmapImage(new Uri(#"C:\Temp\logo.png"));
return img;
Are you positive it's a PNG and not just a renamed Bitmap or Jpeg? If you create a new Bitmap image and then just rename it and change the file extension, this error is reproducible.
If I use a known PNG with your code, I don't get your issue, but a COM exception is thrown:
The handle is invalid. (Exception from HRESULT: 0x80070006 (E_HANDLE))
Can you try it out with a random PNG off the web and see if you get the same result?

Categories

Resources