Image Compression Rate in OpenCV - python-3.x

I am trying to save a bulk of image files after cropping them with cv2.IMWRITE_PNG_COMPRESSION, 9, but this is extremely slow. It takes about one hour for 5000 images.
cv2.imwrite(fn, img, [int(cv2.IMWRITE_PNG_COMPRESSION),9)
This is the command along with the path(fn), the image(img) and the compression mode, 9. If I use the default mode 3, that is by not giving the third argument the png's size gets doubled.
My qusetion is, Is there a way to optimize the process of compression, or any other library that can do this given that img has been opened using img = cv2.imread(src).

Related

AVAssetWriter getting raw bytes makes corrupt videos on device (works on sim)

So my goal is to add CVPixelBuffers into my AVAssetWriter / AVAssetWriterInputPixelBufferAdaptor with super high speed. My previous solution used CGContextDrawImage but it is very slow (0.1s) to draw. The reason seems to be with color matching and converting, but that's another question I think.
My current solution is trying to read the bytes of the image directly to skip the draw call. I do this:
CGImageRef cgImageRef = [image CGImage];
CGImageRetain(cgImageRef);
CVPixelBufferRef pixelBuffer = NULL;
CGDataProviderRef dataProvider = CGImageGetDataProvider(cgImageRef);
CGDataProviderRetain(dataProvider);
CFDataRef da = CGDataProviderCopyData(dataProvider);
CVPixelBufferCreateWithBytes(NULL,
CGImageGetWidth(cgImageRef),
CGImageGetHeight(cgImageRef),
kCVPixelFormatType_32BGRA,
(void*)CFDataGetBytePtr(da),
CGImageGetBytesPerRow(cgImageRef),
NULL,
0,
NULL,
&pixelBuffer);
[writerAdaptor appendPixelBuffer:pixelBuffer withPresentationTime:presentTime];
-- releases here --
This works fine on my simulator and inside an app. But when I run the code inside the SpringBoard process, it comes out as the images below. Running it outside the sandbox is a requirement, it is meant for jailbroken devices.
I have tried to play around with e.g. pixel format styles but it mostly comes out with differently corrupted images.
The proper image/video file looks fine:
But this is what I get in the broken state:
Answering my own question as I think I got the answer(s). The resolution difference was a simple code error, not using the device bounds on the latter ones.
The color issues. In short, the CGImages I got when running outside of the sandbox was using more bytes per pixel, 8 bytes. The images I get when running inside the sandbox was 4 bytes. So basically I was simply writing the wrong data into the buffer.
So, instead of simply slapping all of the bytes from the larger image into the smaller buffer. I loop through the pixel buffer row-by-row, byte-by-byte and I pick the RGBA values for each pixel. I essentially had to skip every other byte from the source image to get the right data into the right place within the buffer.

Node.js: How do I extract an embedded thumbnail from a jpg without loading the full jpg first?

I'm creating a Raspberry Pi Zero W security camera and am attempting to integrate motion detection using Node.js. Images are being taken with Pi camera module at 8 Megapixels (3280x2464 pixels, roughly 5MB per image).
On a Pi Zero, resources are limited, so loading an entire image from file to Node.js may limit how fast I can capture then evaluate large photographs. Surprisingly, I capture about two 8MB images per second in a background time lapse process and hope to continue to capture the largest sized images roughly once per second at least. One resource that could help with this is extracting the embedded thumbnail from the large image (thumbnail size customizable in raspistill application).
Do you have thoughts on how I could quickly extract the thumbnail from a large image without loading the full image in Node.js? So far I've found a partial answer here. I'm guessing I would manage this through a buffer somehow?

How to check png file if it's a decompression bomb

I am playing with image uploads to a website and I found out about these decompression bomb attacks that can take place when it's allowed to upload png files (and some other). Since I am going to change the uploaded images, I want to make sure I don't become a victim of this attack. So when it comes to checking if a png file is a bomb, can I just read the file's headers and make sure that width and height are not more than the set limit, like 4000x4000 or whatever? Is it a valid method? Or what is the better way to go?
Besides large width and height, decompression bombs can also have excessively large iCCP chunks, zTXt, chunks, and iTXt chunks. By default, libpng defends against those to some degree.
Your "imagemagick" tag indicates that you are you asking how to do it with ImageMagick. ImageMagick's default width and height limits are very large: "convert -list resource" says
Resource limits: Width: 214.7MP Height: 214.7MP Area: 8.135GP
Image width and height limits in ImageMagick come from the commandline "-limit" option, which I suppose can also be conveyed via some equivalent directive in the various ImageMagick APIs. ImageMagick inherits the limits on iCCP chunks, etc., from libpng.
Forged smaller width and height values in the IHDR chunk don't fool either libpng or ImageMagick. They just issue an "Extra compressed data" warning and skip the remainder of the IDAT data without decompressing it.

Using mogrify to decrease image size

I'm trying to use mogrify to decrease the quality of the image to ultimately decrease the image size but rather than decreasing it, the image size is increasing. I'm using the following command:
mogrify -quality 20% 1.png
The image size is going from 2.5 mb to 4 mb, any idea?
PNG is a lossless format, so changing "quality" settings should do nothing at all with respect to the "image".
The mogrify documentation confirms this - "quality", when applied to a PNG, indicates which row filters to apply: a value ranging from 0 to 6.
Since the input 20 is invalid for a PNG file, it must have been silently replaced with a default value; presumably 0, which indicates no row filtering at all. (If you really want to know if this is the case, you could use a tool such as pngcheck on your before and after images.)
As to your target: it is unclear whether you want to decrease the physical image size in pixels, or the file size on disk, or (possibly) both. For the first, you can use -resize. For the second, try a PNG-recompressing tool such as pngcrush. For both, use the first method and then the second.
Another option may be to lower the number of color components, for example, from 24-bit RGB to indexed color. Finally, you can always convert the image type from PNG to JPEG, after which you can experiment with the "quality" parameter.

How to estimate size of a Jpeg file before saving it with a certain quality factor?

I'v got a bitmap 24bits, I am writing application in c++, MFC,
I am using libjpeg for encoding the bitmap into jpeg file 24bits.
When this bitmap's width is M, and height is N.
How to estimate jpeg file size before saving it with certain quality factor N (0-100).
Is it possible to do this?
For example.
I want to implement a slide bar, which represent save a current bitmap with certain quality factor N.
A label is beside it. shows the approximate file size when decode the bitmap with this quality factor.
When user move the slide bar. He can have a approximate preview of the filesize of the tobe saved jpeg file.
In libjpeg, you can write a custom destination manager that doesn't actually call fwrite, but just counts the number of bytes written.
Start with the stdio destination manager in jdatadst.c, and have a look at the documentation in libjpeg.doc.
Your init_destination and term_destination methods will be very minimal (just alloc/dealloc), and your empty_output_buffer method will do the actual counting. Once you have completed the JPEG writing, you'll have to read the count value out of your custom structure. Make sure you do this before term_destination is called.
It also depends on the compression you are using and to be more specific how many bits per color pixel are you using.
The quality factor wont help you here as a quality factor of 100 can range (in most cases) from 6 bits per color pixel to ~10 bits per color pixel, maybe even more (Not sure).
so once you know that its really straight forward from there..
If you know the Sub Sampling Factor this can be estimated. That information comes from the start of frame marker.
In the same marker right before the width and height so is the bit depth.
If you let
int subSampleFactorH = 2, subSampleFactorV = 1;
Then
int totalImageBytes = (Image.Width / subSampleFactorH) * (Image.Height / subSampleFactorV);
Then you can also optionally add more bytes to account for container data also.
int totalBytes = totalImageBytes + someConstantOverhead;

Resources