Hello everyone, i'm fresh new here, and i already have a question regarding...well, C#.
I've made a Forms Application in which the user submits an image (bmp,png,jpg or gif), and the image suffers some byte-level modifications (obviously, i'm using the LockBits() method).
Now, after the modifications are done, the user should be able to save the image in its original format (only the least important bits of the image get modified, so the image looks pretty much like the original).
I've developed a static class called ImageTextEncoder which has a public static member ImageTextEncoder.Image, which holds the submitted bitmap.
When i call ImageTextEncoder.Image.Save(Filename,Format) (if initially the image was a Jpeg, i will save it as a jpeg, same for png, gif, etc. ), and i upload the image back, visibly it suffered nothing, but its size gets modified (example: a 700 kb JPG got down to 140 kb), AND at byte level things are altered.
IS there a way i can save the image WITHOUT losing ANYTHING ( size, byte information) . (as a note, i need a solution asap, it's been bugging my application for some days now)
Thank you very much !
4
Contributors
26
Replies
2 Days
Discussion Span
3 Years Ago
Last Updated
31
Views
Question Answered
Related Article:C# Saving information as file
is a solved C# discussion thread by wingers1290 that has 1 reply, was last updated 3 years ago and has been tagged with the keywords: association, c#, file, saving, view.
if the image is a different size, its probably the compression level. when you save your bitmap, if you save it as a jpeg file, you can alter its compression methods, changing its filesize, if you just call save, it uses the default. which might be different from the source image.
I ment size as in file size not dimensions. sorry.
// We will store the correct image codec in this object
ImageCodecInfo iciJpegCodec = null;
// This will specify the image quality to the encoder
EncoderParameter epQuality = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, (int)80);//set quality here
// Get all image codecs that are available
ImageCodecInfo[] iciCodecs = ImageCodecInfo.GetImageEncoders();
// Store the quality parameter in the list of encoder parameters
EncoderParameters epParameters = new EncoderParameters(1);
epParameters.Param[0] = epQuality;
// Loop through all the image codecs
for (int i = 0; i < iciCodecs.Length; i++)
{
// Until the one that we are interested in is found, which is image/jpeg
if (iciCodecs[i].MimeType == "image/jpeg")
{
iciJpegCodec = iciCodecs[i];
break;
}
}
//now save
yourImage.Save(filepath, iciJpegCodec, epParameters);
I borrowed this code from somewhere a long time ago, i don't remember where. there are other ways. but this one always worked for me.
Ok, never mind GIF,PNG,BMP, i'm using the suggestion which you, and also microsoft http://support.microsoft.com/kb/324790 apparently gives, but my problem ain't solved - when i call the new parametrized save method, with 100 quality quoefficient, my image still gets shrinked :(.
The problem with image shrinkage is data loss - i used the least significative bits of each byte to encode some data, and that data is LOST when i save the image :(
please help !
the idea behind JPEG image compression is that it removes color differences that are not apparent by the human eye. If you really want a full quality picture you might want to always save to bmp or png24 regardless of source type.
jpeg compression looks good, and makes for a good file size, but if your goal is just to preserve bytes written into your image, you probably will loose it during the compression. Sorry. its still not clear to me what your goal is.
im not sure if this will suit u , especially i didn't understand completely
what u intend to do ..
but : what about submitting array of bytes representing the image..
and then reading them through memory stream then converting them to an image with the type u want
this is a part of code i used before for saving submitted images..
//this is a kind of encoding i used
byte[] img = Convert.FromBase64String(s);
MemoryStream ms = new MemoryStream(img);
Bitmap bmp = new Bitmap(ms);
System.Drawing.Image.FromStream(ms);
imga.Save(file path);
@dima shawahneh:
Already tried that, the Save method will cause my image to lose bytes.
@Diamonddrake:
I am encoding text into an image - changing the least significant bit of each of the image's bytes to "encode" the ASCII representation of a character. (example: The letter "A" is 65 in ASCII -> 01000001 in binary, so i will modify 8 of the image's bytes in order to "encode" that specific letter).
I need to save any jpeg,bmp,gif,png file and not lose ANY of the image's bytes.
(I already tried saving Jpeg as a Bitmap, while still retaining the .jpg extension , but it increases the image's byte size too much. - it saved a 700 KB jpeg to a 3 MB one)
What i need is to save the image and not loose ANY of its bytes, while also retaining its original size in bytes ( 700 KB to 3 MB = NOT GOOD)
Then don't convert the input stream in to an image. Save the raw input stream directly to a file and you will have the exact image they uploaded.
//this is a kind of encoding i used
byte[] img = Convert.FromBase64String(s);
System.IO.File.WriteAllBytes(@"C:\image.bmp", img);
You will obviously have to tweak the save location and file extension but that information needs to be gathered from the uploaded filename and whatever logic you use to determine save file names...
ImageConverter img_converter = new ImageConverter();
byte[] bytes = (byte[])img_converter.ConvertTo(image, typeof(byte[]));
File.WriteAllBytes(savefil.FileName, bytes);
//savefil is a Save File Dialog
It works ! But my original Jpeg file has 700 KB, while the new one has 2 MB ...could i further enhance this?
You ran the bytes through your converter.... In my last post I said to save the input stream directly to disk. Its hard to say whats going on here since we don't have the full code for your encoding/converting mechanisms. Are you writing the base-encoded bytes to disk and not the raw image to disk, and using your app to view the image?
>>So after using that method i flush down its bytes through the converter and save them to a file.
So what you are saying is "after I take an original image, run the image through a converter, and save the modified image it is different than my original image". Right? If you do anything to an image other than save it you're probably going to cause some change in it.
Wherever you are getting the source image -- before you convert it, encode it, or even load it in to an Image or Bitmap class in C# you should save the raw image bytes.
I dont need the original image saved back to the hard disk, i need the modified image saved to the disk. I modify only the least significant bits of the image, so the change isn't that big to increase its size threefold.
That's where my problem is.
Ah, gotcha. Upload the source image and your project to this thread. You can do this by zipping them up and clicking on "Go Advanced" then "Manage attachments".
Yes, everyone can download it. Just pull out the parts of your code relevant to what you're trying to accomplish and a single image. There is all kinds of commercial code posted on the internet.....
I used your application and made that ~700kb jpeg to a ~2.xMB jpeg just like you said. However after inspecting the 2MB file I noticed it is actually a PNG file with a JPEG extension. You can change the file extension to another image type and it will still open in photo viewers properly. I'm sure you know that PNG is a lossless format so that makes sense why the file is so big.
Something you are doing is changing the image format.
I noticed here:
case "JPEG":
case "JPG":
{
File.WriteAllBytes(savefil.FileName, ImageTextEncoder.ToByteArray());
//Works only for JPG files, though it increases their size considerably.
}
break;
case "BMP":
{
bm.Save(savefil.FileName, ImageFormat.MemoryBmp);
//Shrinks bmp's, but works.
}