How to specify a bitrate for JPEG compression?

Is there a way to encode a JPEG with a specific bit rate?

I am currently using imagemagick convert :

 convert Lenna-gray-100.jpeg -quality 1.1111 test.jpeg 

Bitrate increases with quality, but it is non-linear. I want to explicitly control the bitrate. It does not have to be accurate, but I want it to be close enough (inside, say, 0.1 bit / s from the specified setting).

Is there some kind of encoder that allows you to encode images with a specific transmission speed? It should not be imagemagick, I will take everything that works (preferably on Linux).

A dumb way to do this is to play with fractional values ​​in the -quality parameter until something close to the target bitrate appears, but I hope for a more elegant solution.

EDIT:

I got bored and decided to do something quickly (but stupid).

Firstly, here is the imagemagick- -quality vs bitrate graph:

alt text

By the way, here is the image I used:

alt text

Thus, the change in bit rate is pretty good for lower quality values, but it becomes rough after about 80.

Here is an example code for encoding an image with some target bitrate. I used OpenCV because it allows you to encode JPEG in memory (no I / O required). Although I originally intended to mock this with Python, unfortunately, Python OpenCV shells do not reveal in-memory coding functionality. So I wrote it in C ++.

Finally, I thought about using linear quality interpolation to get closer to the target bitrate, but since cv::imencode only accepts integer parameters, it is not possible to set non-integer JPEG quality. The quality scale between OpenCV and imagemagick seems to be somewhat different, so using the interpolated quality parameter from OpenCV and using imagemagick convert did not work.

This means that the output bitrate is not equal to the target bitrate, especially at higher bitrates (> 1). But it is close.

Can anyone suggest something better?

the code:

 #include <stdio.h> #include <cv.h> #include <highgui.h> #include <assert.h> #include <vector> using cv::Mat; using std::vector; #define IMENCODE_FMT ".jpeg" #define QUALITY_UBOUND 101 #define BITS_PER_BYTE 8 int main(int argc, char **argv) { if (argc != 4) { fprintf(stderr, "usage: %s in.png out.jpeg bpp\n", argv[0]); return 1; } char *fname_in = argv[1]; char *fname_out = argv[2]; float target; sscanf(argv[3], "%f", &target); Mat orig = cv::imread(fname_in); int pixels = orig.size().width * orig.size().height * orig.channels(); vector<unsigned char> buf; vector<int> params = vector<int>(2); params[0] = CV_IMWRITE_JPEG_QUALITY; int q; double bpp = 0.0; for (q = 1; q < QUALITY_UBOUND; ++q) { params[1] = q; cv::imencode(IMENCODE_FMT, orig, buf, params); bpp = (double)buf.size() * BITS_PER_BYTE / pixels; if (bpp > target) break; } cv::imwrite(fname_out, orig, params); printf("wrote %s at %d%% quality, %.2fbpp\n", fname_out, q, bpp); return 0; } 

Compile and run with:

 g++ -c -Wall -ggdb -I../c -I../blur `pkg-config --cflags opencv` -Wno-write-strings jpeg-bitrate.cpp -o jpeg-bitrate.o g++ -I../c `pkg-config --cflags opencv` `pkg-config --libs opencv` -lboost_filesystem jpeg-bitrate.o -o jpeg-bitrate.out rm jpeg-bitrate.o misha@misha-desktop:~/co/cpp$ ./jpeg-bitrate.out Lenna-gray.png test.jpeg 0.53 wrote test.jpeg at 88% quality, 0.55bpp 
+8
image-processing opencv imagemagick compression jpeg
source share
2 answers

I know that there is a lot of work to control the output bitrate of a JPEG encoder (for example, 1st document ; 2nd document ), and that such controls exist in JPEG2000. Unfortunately, I'm not sure if any bitrate control is standardized for JPEG or implemented in shared libraries. You may need to program your own method using, for example, binary search ...

But then again, I could be wrong - and if so, I would like to hear about such a library.

Just out of curiosity, what language do you use?

+4
source share

The ratio of bitrate quality in JPG depends on the content. If you want to encode with a specific bitrate, I suggest you make two passes: 1. Encode with a fixed quality factor (closer to the target bitrate, it may be better based on your schedule) 2. Based on your size, reinstall the original with higher or lower quality . Again, this may be based on your schedule or something similar.

You can also endlessly repeat the last step to get the desired EXACT bitrate.

I would check this with various extreme cases, for example, a very noisy / busy image, a black rectangle or a smooth gradient.

+2
source share

Source: https://habr.com/ru/post/651016/


All Articles