I have an image in PNG or BMP format. I would like to find out the filesize of that image after compressing it to a jpeg without saving the jpeg.
Up to now I did it the following way:
frameNormal.Save("temp.jpg", ImageFormat.Jpeg);
tempFile = new FileInfo("temp.jpg");
filesizeJPG = tempFile.Length;
But because of the slow disk access, the program takes too long.
Is there a way to calculate the filesize of the newly created jpeg? Like converting the PNG in memory and read the size...
Any help is very much appreciated :-)
You can write the image data to a Stream instead of supplying a filename:
using (MemoryStream mem = new MemoryStream())
{
frameNormal.Save(mem, ImageFormat.Jpeg);
filesizeJPG = mem.Length;
}
You can to something like this:
MemoryStream tmpMs = new MemoryStream();
frameNormal.Save(tmpMs, ImageFormat.Jpeg);
long fileSize = tmpMs.Length;
Try loading it into memory without saving to disk. Look up MemoryStream.
Also, this answer might help: How to get the file size of a "System.Drawing.Image"
Related
I'm attempting to save a bitmap file as a jpeg into Azure without saving it locally in the process, so I am first saving the bitmap as a jpeg in a MemoryStream.
But when I execute the following code, the file uploads but it did not convert the bitmap correctly. If I view the file, the viewer displays 'Invalid Image.'
I read somewhere that bitmaps cannot be converted to jpegs in memory. Could that be what is happening here?
// Retrieve reference to a blob
var blobContainer = GetBlobContainer(Properties.Settings.Default.BlobContainerName);
var blob = blobContainer.GetBlockBlobReference(blobFilePath);
// Save bitmap to jpeg in MemoryStream, then upload to Azure blob
//var writer = new StreamWriter(blob.OpenWrite());
MemoryStream memStr = new MemoryStream();
bitmap.Save(memStr, System.Drawing.Imaging.ImageFormat.Jpeg);
blob.UploadFromStream(memStr);
After writing to the MemoryStream you need to "rewind" it by setting memStr.Position = 0 before any attempts to read it (in your case, uploading it to Azure)
"Be kind, please rewind."
I have to create multiple thumbnails and save on amazon s3 in c#. I don't find library which can create thumbnail from memory stream only from source file. But can't have file source, I have only the stream from the upload and I don't want save localy the file.
Thx for ur help!
Simple c# code can do this for you. You can create a thumbnail from byte array.
First convert your memory stream object to byte array by following code
byte[] bytes = memoryStream.ToArray();
and then you can use below method
public byte[] MakeThumbnail(byte[] myImage, int thumbWidth, int thumbHeight)
{
using (MemoryStream ms = new MemoryStream())
using (Image thumbnail = Image.FromStream(new MemoryStream(myImage)).GetThumbnailImage(thumbWidth, thumbHeight, null, new IntPtr()))
{
thumbnail.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
return ms.ToArray();
}
}
I don't find library which can create thumbnail from memory stream only from
source file
Really? Because I do not need a library for that - I can do that with standard C#.
System.Drawing.Bitmap has a constructor accepting a stream.
But can't have file source,
Actually you can - it is called a temporary file and there is a whole mechanism for that in .NET (and windows). Really.
But it is not needed. Read the manual, create a bitmap (by packing your byte array into a MemoryStream) and it should work.
im using the SLsharpziplip to try to compress a byte[] before sending it on the network to a server. the byte[] contains jpeg data which is already compressed by the jpeg encoder.
you may ask , if jpeg already compress the image, why do i need to compress it more, well because i tried it and it worked.
here is what happened:
I wrote the bytes in the byte[] to a txt file , the size of the txt file is ~5k , i compressed it with winzip and the result file was ~2k , so thats about 50% reduction in the file size. however , when i try to do it with the byte[] and use the slsharziplip to compress the byte[] , the reduction in size is minimal.
here is the code i used:
MemoryStream msCompressed = new MemoryStream();
GZipOutputStream gzCompressed = new GZipOutputStream(msCompressed);
gzCompressed.SetLevel(9);
// allframes is a byte array.
gzCompressed.Write(allframes, 0, allframes.Length);
gzCompressed.Finish();
gzCompressed.IsStreamOwner = false;
gzCompressed.Close();
// i used byte[] compresseddata = msCompressed.ToArray() but i thought i'll try this too.
msCompressed.Seek(0, SeekOrigin.Begin);
byte[] compresseddata = new byte[msCompressed.Length];
msCompressed.Read(compresseddata, 0, compresseddata.Length);
==================================================================================
from debugging the code, i can see that the difference of size between allframes.Length and compresseddata.lenght is minimal. but if that same data is written to a text file and zipped with winzip its size is reduced by 50%.
this is how i write the same data to a txt file:
TextWriter tw = new StreamWriter(MainPage.fs); // fs is a filestream.
foreach (byte b in allframes )
{
tw.Write(b);
}
===============================================================================
am i doing something wrong?! am i misunderstanding something!!
thanks up front :)
You are not comparing like with like.
There is no point in compressing JPEG image data as it is compressed already. Writing it out to a text file won't give you the same file size as writing it to a binary file.
Probably not, I would imagine WinZip has a superior zip algorithm to SLSharpZipLib. You can try varying the compression ratio but other than that, I would try different Silverlight compatible zip libraries.
JPEG as you've correctly pointed out is already a highly compressed file type, so finding a compression algorithm that can find further redundancy is going to be difficult.
Best regards,
I have one WPF application in which I am uploading autocad drawing files (.dwg), convert it to byte array and save to database. When I read back that file from byte array, I am getting following error :
No imaging component suitable to complete this operation was found.
My code to convert in byte array is below :
FileStream fs = new FileStream(dlg.FileName, FileMode.Open, FileAccess.Read);
byte[] data = new byte[fs.Length];
fs.Read(data, 0, System.Convert.ToInt32(fs.Length));
fs.Close();
I am trying to get image from byte array using below code :
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.CreateOptions = BitmapCreateOptions.None;
bi.CacheOption = BitmapCacheOption.Default;
bi.StreamSource = new MemoryStream(data);
RenderOptions.SetBitmapScalingMode(bi, BitmapScalingMode.Linear);
bi.EndInit();
Above code works fine for other image files like jpg, png, bmp, gif. but not working for dwg file. Can anybody guide me what's wrong in my code ?
Thanks
Times ago I was searching for DWG library in C# and found this one:
http://www.woutware.com/cadlib.html, but after never used it.
You can not threat DWG files like ordinar image files, DWG is fairly complicated format for storing 2D and 3D data as well. And years ago also was a subject of frequent change and all licensing mess.
Hope this helps.
You have answered it yourself!
Above code works fine for other image files like jpg, png, bmp, gif.
but not working for dwg file.
For this to work correctly deserialise the byte array back to as "dwg file" itself and use some APIs to convert it to a bitmap and use that as the image source.
Try using a type converter
FileStream fs = new FileStream(dlg.FileName, FileMode.Open, FileAccess.Read);
byte[] data = new byte[fs.Length];
fs.Read(data, 0, System.Convert.ToInt32(fs.Length));
fs.Close();
TypeConverter tc = TypeDescriptor.GetConverter(typeof(BitmapImage));
BitmapImage bitmap1 = (BitmapImage)tc.ConvertFrom(data);
Try using strm.Seek(0, SeekOrigin.Begin); because it may be possible you must have gone past through the stream with read
One option is to use http://www.opendwg.org/
Although not free, it is non-profit.
But it will only parse the dwg file for you into collection of lines, circles, polygons etc.
You still need to piece together and render the image.
I have a functioning application in c#/.net that currently accepts raw image data in a bayer format from a set of embedded cameras and converts them to jpeg images. To save transmission time, I have modified the embedded devices to encode the images as jpegs prior to transmission. I'm an experienced embedded programmer but a total c#/.net noob. I have managed to modify the application to save the arrays to file with a jpeg name using this snippet: ( the offset of 5 is to skip header data in the transmission frame)
FileStream stream = File.Create(fileName);
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(multiBuff.msgData, 5, multiBuff.dataSize - 5);
writer.Close();
The files open up fine, but now I want to treat the data as a bitmap without having to save & load from file. I tried the following on the data array:
MemoryStream stream = new MemoryStream(data);
BinaryReader reader = new BinaryReader(stream);
byte[] headerData = reader.ReadBytes(5);
Bitmap bmpImage = new Bitmap(stream);
But this throws a parameter not valid exception. As a newbie, I'm a little overwhelmed with all the classes and methods for images and it seems like what I'm doing should be commonplace, but I can't find any examples in the usual places. Any ideas?
I think you are looking for Bitmap.FromStream() :
Bitmap bmpImage = (Bitmap)Bitmap.FromStream(stream);
Actually using new Bitmap(stream) should have worked as well - this means that the data in the stream does not constitute a valid image - are you sure the jpg is valid? Can you save it to disk and open it i.e. in Paint to test?
You use the Image class.
Image image;
using (MemoryStream stream = new MemoryStream(data))
{
image = Image.FromStream(stream);
}
FYI it didn't work because reader.ReadBytes(5) returns the 5 first bytes of stream not the bytes after position 5