AVFoundation or VideoToolbox JPEG compression - ios

I'm trying to capture an image using AVFoundation and save it as JPEG with maximum quality. I'm aware of AVVideoCodecJPEG and AVVideoQualityKey for AVFoundation capture, but it doesn't produce the output I'm looking for. Namely, I need the final JPEG to use the 4:4:4 chroma subsampling. Instead AVFoundation even at quality set to 1.0 (max) produces the image with 4:2:0 chroma subsampling. I tried to capture an image in BGRA32 format and later compress with VideoToolbox - same result. The only way I can get the desired output is by using CGImageDestinationCreateWithData method, but it's too slow - 0.4 sec for 12 MPx image (if I set quality to less than 1.0, the image can be compressed in 0.1 sec for the same size, but than I get again 4:2:0 chroma subsampling).
Did anyone ever succeeded to produce a JPEG with chroma subsampling 4:4:4 using AVFoundation or VideoToolbox? Or maybe there is there any way to accelerate CGImageDestinationCreateWithData method? Thanks in advance

Ok, there seems to be no support for 4:4:4 chroma sub-sampling using hardware accelerated JPG compression.

Related

Does Opencv support lossless compression for jpeg

Opencv imwrite lossy compress image into jpeg by set IMWRITE_JPEG_QUALITY to 0-100 to adjust the rate-distortion. It seems that image is still lossy compressed even if IMWRITE_JPEG_QUALITY is set to 100. Does Opencv support lossless compression for jpeg?

Codec for lossless 8-bit grayscale

I have a camera that outputs 160 fps of 1024x1280 pixels in 8-bit grayscale (256 colors).
I need to encode this live without any loss.
What's the best codec for this?
I can code this in either python or c++, and have lots of cores, so parallelization is an option.
Thank you
Motion JPEG-2000 supports lossless and gray scale.
ffv1 https://github.com/FFmpeg/FFV1/blob/master/ffv1.md is another common option for lossless.
Your uncompressed data rate is 160 fps * 1024 * 1280 = 210 Mbytes/s.
I am guessing 50% compressing so you end up with about 100 MBytes/s compressed video.
This should be a doable I/O rate for a SSD.
Concerning the CPU - I suggest a naïve parallelization where you run one video compressor per core. So you have to do some sort of scheduling, pipelining and resorting of the output frames.
So if you have a 16 (32) core CPU each core needs to do 10 (5) fps which sounds pretty reasonable.

Is webp format more efficient than JPEG?

I am trying to compress and resize DSLR camera photos. But my observation so far is that webp has noticeable degraded quality when webp file size is about 30% smaller than JPEG.
Command used to generate webp using imagemagick:
convert 1.JPG -strip -quality 80 -resize 800 -define
webp:method=6 1.webp
My goal is to get webp format that is at least 20% samller file size than JPEG while having virtually no difference in quality between JPEG and webp.
Is this achievable or again there is no such thing as free lunch?
Update Since the time of the original posting, I've discovered that using Google's cwebp compressor shows dramatically improved compression over ImageMagik 6.7.8, which is what powered my initial tests. This is especially true for images with transparency when compared to PNGs. Files using the mac version of the webp command (which uses cwebp under the hood) are about 1/4 of the size of the same file compressed with ImageMagik, and do provide a significant performance boost.
According to Google, "WebP typically acheives an average of 30% more compression than JPG" (source) with similar visual quality to a JPG. However, as you suggest, there in never such a thing as a free lunch.
Quality
Quality is largely a subjective measure, but keep in mind that you're comparing a file compressed at quality 80 with a file that doesn't have that level of compression (at least, this is what I understand from your question). Just running the default conversion without specifying a lower quality may give you slightly smaller files without loss of visible quality. 20% smaller might be a bit much of an ask, though, but it may be achievable for certain images.
convert 1.JPG 1.webp # do not specify quality
Size
In practice, it depends a lot on your settings and your source images. For example, I recently ran this command on all jpg images in a folder on a website "in the wild":
convert filename.jpg -quality 80 -strip -define webp:lossless=false -define webp:method=6 filename.webp
The convert command on this particular server is powered by ImageMagick 6.7.8. Some files were dramatically smaller compared to the original JPGs, while others were actually larger. Overall, after running that command, the total file sizes of all JPG images was 49MB, while the total file size of all WebP images was 29MB. That's a pretty good savings, however, when I ran ImageMagick's JPG compression, it was even better:
convert filename.jpg -sampling-factor 4:2:0 -strip -quality 80 -interlace JPEG filename-new.jpg;
The size of all new jpgs in the directory was 21MB. Both are set to compress at quality 80, but the jpg compression appears to be better. This may have to do with some compression already on my set of test images and how that interacts with the WebP conversion process.
As I found, file sizes can even grow, usually if you are converting between lossy and lossless images. On the FAQ page linked above, Google claims: "this is mainly due to the colorspace difference (YUV420 vs ARGB) and the conversion between these."
tl;dr: In the wild, it may or may not improve file size depending on the type of images, if/how the source file was compressed, and what quality you set for the WebP. Visible degradation is harder thing to measure, but try setting a higher quality, or without specifying a quality at all.
Just to add a side-comment to #Pwpwpw's excellent answer, webp is a good PNG replacement, but not great as a JPG replacement.
It beats PNG because it has better lossless compression algorithm than libpng, and it has the great feature of allowing different compression settings for different channels. You can do lossless on the alpha but lossy on the RGB, for example, which is fantastic for overlays.
Against JPG it does less well. It uses the VP8 codec for lossy, which is only somewhat better than JPG.
I would take a look at HEIC. It uses the much more modern h.265 for lossy compression and typically beats JPG by a factor of two at the same quality. It's the format Apple are using by default on iOS now.
libheif have a nice demo here:
https://strukturag.github.io/libheif/
That's libheif, compiled to javascript and running in your browser. You can upload .heic to it and download as jpg. libheif have some basic command-line tools to encode and decode images.
It does sadly have some patent issues, you might need to be a little cautious.
update Looking further out, the current hope is AVIF: it's the same container format as HEIC (called HEIF, confusingly), but swaps the problematic h.265 compressor for AV1. AV1 is roughly equivalent to h.265, but is patent-free.
update for 2022 AVIF seems to be too slow to be practical, so now hope rests on JXL. It's fast, patent free, supports HDR, transparency, etc., and compression is as good as HEIC. Chrome has support, though it's behind a flag for now.
You are re-encoding lossy compressed jpeg; if you have access to the original raw files you should use them as master. Currently you are compressing noise (and other artefacts) introduced by the jpeg encoder so the WebP codec does not have access to the same information that was already lost at the jpeg encoding. Of course it will look worse.
In other words; you should encode the original image data, if possible. I'm aware that some cameras and equipment only outputs HEIC / JPEG and not RAW so you might be out of options - the best thing to do is to keep the JPEGs as JPEGs.
Just did a quick test with a high-res JPG from my DSLR camera converting to a 410x800 background picture for mobile using Photoshop CC 2020 (and the WebPShop plugin).
Lossless:
PNG 100%: 680 KB
JPG 12 (max): 428 KB
WEBP 100%: 537 KB
50% quality:
JPG 6 (50%): 119KB
WEBP 50%: 45KB
At 50% JPG has more detail, but quite comparable quality.
0 quality:
JPG 0 (min): 51KB
WEBP 0%: 6KB
At 0% WEBP is horrible. But imagine the lowest quality JPG, and that's bad image quality and WEBP definitely beats it at 50%, while still being smaller in file size. So for me.. that's free lunch.

Converting png to jpeg increases image size

When I convert png to jpeg , size of image is increasing for 2 percent cases. I am using convert command of imagemagick for this. Also able to handle alpha transparency factor by maintaing white background . But , I am not getting increase in size of image . It is very well known that pngs are lossless and jpegs are lossy , then what is the specific reason and what can be work around for it.
Please refer above mentioned example pic
Try decreasing JPEG quality setting. Jpeg uses Discreet Cosine Transform (DCT) to decrease the size of spatial data, but on high quality setting with high-detailed input images
you will get some size increase due to the fact, that data is not quantized enough and DCT-ed data needs some storage too.

What is the best pixel format to choose when creating a AVAssetReaderTrackOutput?

I am writing code to convert a frame in a MP4 file to a OpenGLES texture, and am using the class AVAssetReaderTrackOutput to be able to access the pixel buffer. What is the best pixel buffer format to output as? Right now I am using my old code that converts YUV420P to RGB in a OpenGLES shader as I previously used libav to feed it. Now I am trying to use AVFoundation and wondering whether my OpenGLES shader is faster than setting the pixel buffer format to RGBA, or whether I should use a YUV format and keep with my shader.
Thanks
I guess this depends on what the destination of your data is. If all you are after is passing through the data, native YUV should be faster than BGRA. If you need to read back the data to RGBA or BGRA, I'd stick to BGRA and use a OpenGL Texture Cache rather than glReadPixels().
I recommend reading the answer for this SO question on the YUV method. Quote:
"Video frames need to go to the GPU in any case: using YCbCr saves you 25% bus bandwidth if your video has 4:2:0 sampled chrominance."

Resources