I’m using the CGImage APIs (CGImageDestination,
CGBitmapContext,
, CGImage
etc.) on Mac OS X as well as iOS to compress images to JPEG. Using the kCGImageDestinationLossyCompressionQuality
property you can control the compression quality: 0.0
being maximum compression and 1.0
being maximum quality (lossless if possible according to Apple).
I’ve found that there’s a huge jump in both disk size & image quality when you go from 0.99
to 1.0.
For example, I’ve got a 2048x1368 image that compresses to 430 KB when the quality is set to 0.99
but balloons to 2.3 MB when the quality is set to 1.0. There’s a big jump in visual quality as well and the 0.99
setting isn’t acceptable for this particular image. Trying to set the quality to anything between 0.99
to 1.0
doesn’t work as the size remains at 430 KB up until 0.995
where it jumps up to 2.3 MB. Also, there really isn’t much difference between qualities of 0.90
to 0.99
which ranges in file size from ~353 KB to 430 KB, but not much improvement in visual quality.
Does anyone know if there’s any way to increase the JPEG quality? I really need something better than what 0.99
is giving me but less than what 1.0
provides. Maybe there’s some other API I could use?
I may try using libjpeg directly but I hope it doesn’t come to that.
After some investigation it turns out that for all kCGImageDestinationLossyCompressionQuality
settings up to 1.0
Apple uses 4:2:0 chroma subsampling (or chroma decimation). This means that for the YCrCb image they only sample one chroma pixel (CrCb) for every 4 luminance (Y) pixels. In other words they’re only using 1/4 of the chroma data from the original image. For a quality of 1.0
Apple uses 4:4:4 chroma subsampling, which is no chroma subsampling or one chroma pixel for every luminance pixel. This is why the file size explodes as the image contains 4x the color data vs. qualities <= 0.99
.
So, does anyone know if there’s a way to turn off chroma subsampling using CGImage (or any other API) for qualities less than 1.0
?
After extensive research and following the suggestions in the comments above it appears that there is no way to disable chroma subsampling/decimation with any of Apple’s built-in APIs short of setting kCGImageDestinationLossyCompressionQuality
to 1.0
which results in very large images.
If you need to be able to control chroma subsampling/decimation yourself when saving to JPEG then you’ll need to use a 3rd party library such as libjpeg.
Maybe there’s some other API I could use?
WebP is a new image format from Google that gives you better compression than jpg and png, both lossless and lossy. There is a project on github that is pretty easy to use: https://github.com/seanooi/iOS-WebP
You just add a category and the WebP framework to your project to use it.
//Converting To WebP
// quality value is [0, 100]
NSData *webpData = [UIImage imageToWebP:[UIImage imageNamed:@"image.jpg"] quality:75];
//Converting From WebP
UIImage *webPImage = [UIImage imageFromWebP:@"/path/to/file"];
//Setting image transparency
//alpha value is [0, 1]
UIImage *transparencyImage = [[UIImage imageNamed:image.jpg] imageByApplyingAlpha:0.5];
The alpha isn't working right, but since you are using jpg, I'm assuming you don't need it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With