views:

892

answers:

2

Hello

I have a cannon digital camera and I set it to take pictures with superfine quality and it outputs a .jpg file 3 mega in size. If I load it like this in ASP.NET(this is useful to change it's dpi resolution or crop it or whaterver)

imgPicture = Image.FromFile(Config.WorkDirectory + this.TempPhotoName);
bmpPicture = new Bitmap(imgPicture);

and then I save it again like this:

bmpModified.Save(Config.WorkDirectory + this.TempPhotoName,System.Drawing.Imaging.ImageFormat.Jpeg);

it outputs a jpg that is only 700KB or so in size. There is a loss of quality.

I also tried saving it like this:

bmpPicture.Save(Config.WorkDirectory + this.TempPhotoName, codecJpeg, encparams);

where codecJpeg is

ImageCodecInfo codecJpeg = this.getEncoderInfo("image/jpeg");


    private ImageCodecInfo getEncoderInfo(string mimeType)
    {
        // Get image codecs for all image formats
        ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();

        // Find the correct image codec
        for (int i = 0; i < codecs.Length; i++)
            if (codecs[i].MimeType == mimeType)
                return codecs[i];
        return null;
    }

and encparams:

EncoderParameters encparams = new EncoderParameters(1);
encparams.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 97L);

This way the size(and I suspect also the quality) is maintained but I am inputing the quality by hand.

I want to ask:

Is there a way to save the image with the same quality as it was loaded without hardcoding the quality value?

Thank you in advance

+1  A: 

So it sounds like you know how to set the quality, you really just need to know how to fetch the quality from the original image?

I suspect that Image.PropertyItems is your friend, if the quality is in the metadata to start with. (I don't know if there's even a standard scale for quality within JPEG encoders.)

EDIT: I've just checked, and a jpeg I downloaded didn't have any tags for quality.

One option might be to work out how big the file should end up to have roughly the same quality, and then save it several times, doing a binary search to work out the most appropriate quality. Icky, but it might just work.

I have a sneaking suspicion that there isn't a way to just preserve the original quality setting, although I don't have very good grounds for that suspicion...

Jon Skeet
Setting PropertyItems and resave will lead to quality loss, because image will be re-encoded. Read more here: http://stackoverflow.com/questions/1038206/net-c-library-for-lossless-exif-rewriting
arbiter
Yes, I appreciate that it will be re-encoded - but I think it does make sense to re-encode at roughly the same "lossiness" as the original, should you wish to. You're still going to lose data, but probably not a huge amount. Also note that I wasn't talking about *setting* PropertyItems - I was talking about *fetching* it to find out the original quality, although that doesn't seem to have the relevant data.
Jon Skeet
Well there is exist propertyitem element for fetching jpeg quality - PropertyTagJPEGQuality, but it stated as private tag for adobe photoshop, so I do not know it is filled by camera or not. Anyway there is a little sense of storing jpeg with the same jpeg quality value, because quality loss will be there.
arbiter
My point is that it wasn't filled in on the jpeg I was using :) I still disagree with your fundamental point though: I suspect that you typically *do* want to store a jpeg with the same quality value as the original, even though you'll lose quality. The original quality value shows how much you care about quality, as does the new quality value.
Jon Skeet
Wouldn't you have to save it at 100% quality? For example, say I save an image at 70% quality, then re-open it and save it again. If I now save it at 70% its actually 70% of 70% not 70% of the original. So really to maintain the quality you should always save the opened JPEG as 100%?
Mauro
No, you wouldn't get 70% of 70% - that's not how it works. Don't forget that when you reload it, you'll reload data that is naturally easier to compress than the perfect original - so you can compress it with a "medium" quality again without losing as much data as if you'd start with the perfect original.
Jon Skeet
A: 

Read here how to save image without re-encoding image: How-to: Re-encode a JPEG Image with Metadata.

However, if you do cropping or another image manipulation it impossible to do it without quality loss (well technically it is possible to do loss-less crop, if you work with boundaries that multiply of 16, but AFAIK it is cannot be done with libraries available in .net).

arbiter