Qimage image format Summary
20:35:32
Well, this qimage problem has been studied for a long time. It was useless for some time. I forgot that I had been asked twice. I suddenly had a hard time explaining it, I think it is necessary to repeat it. Otherwise, I am not ashamed of myself.
The data of the image is saved in bytes. The number of bytes in each row must be an integer multiple of 4.
(Because we use a 32-bit operating system, the data is 32-bit aligned, therefore, the number of bytes in each row must be an integer multiple of 4, that is, the data bit in each row must be an integer multiple of 32 bits .) This is what I understand. It seems wrong. I fixed it. Recently I was reading data alignment. In this section, I ignored it and didn't delete it because I wanted to leave a footprint, wait until I find a suitable answer and paste it back. However, the image data is indeed 32-bit aligned.
If it is not an integer multiple, the formula is as follows: W = (w * bitcount + 31)/32*4;
Note: W indicates the width of the image, and bitcount indicates the depth of the image, that is, 32 or 24. The calculated W indicates the number of bytes per line of the image in the program.
The 32, 24, and 8 bitmap of qimage are described here.
Image Format: qimage: format_rgb32, qimage: format_rgb888, qimage: format_indexed8.
Construct an image:
(1) qimage myimage1 = qimage (filename); open the Image Based on the file name. If the image itself is 32-bit or 24-bit, the program image is 32-bit, if the image itself is 8-bit and 1-bit, the program corresponds to 8-bit and 1-bit.
(2) qimage myimage2 = qimage (width, height, qimage: Format _...); To construct an image based on the image width and height, the program will automatically align the image data according to the image format.
Operating image: Construct the image in the way of (2). Under debug, if the initial value of myimage2 is not given, the image is not black, but under release, the constructed image is black by default.
Now we need to operate on the image data. A 32-bit image is undoubtedly the simplest, because its data is aligned. Width indicates the image width, and height indicates the Image Height.
First, familiarize yourself with several functions:
A. uchar * bits (); obtains the first address of the image.
B. Int bytecount (); Total number of bytes of the image
C, int bytesperline (); number of bytes per line of the image
1. qimage: format_rgb32. The storage format is B, G, R, A, corresponding to 0, 1, 2, 3.
Qimage: format_rgb888. The storage format is R, G, and B, corresponding to 0, 1, 2.
Qimage: format_indexed8. You need to set the color table and qvector <qrgb>
Grayscale image color table settings:
Qvector <qrgb> colortable;
For (intk = 0; k <256; ++ K)
{
Colortable. push_back (qrgb (K, K, k ));
}
2. qimage image32 = qimage (width, height, qimage: format_32 );
Qimage image24 = qimage (width, height, qimage: format_24 );
Qimage image8 = qimage (width, height, qimage: format_8 );
Image8.setcolortable (colortable );
3. Each pixel needs to be processed. The pointer value is used and the row scan method is as follows:
Int linenum_32 = 0; // number of rows
Int pixelsub_32 = 0; // pixel subscript
Uchar * imagebits_32 = image32.bits (); // obtain the first image address, 32 bitmap
Uchar * imagebits24 = image24.bits ();
Uchar * imagebits8 = image8.bits ();
For (INT I = 0; I
{
// According to the general understanding, we will process the following and take each line
Linenum_32 = I * width * 4; // This sentence is correct for any image.
// Linenum_24 = I * width * 3 ;//?? When width is not an integer multiple of 4, this sentence cannot start with each line.
// Linenum_8 = I * width ;//?? When width is not an integer multiple of 4, this sentence cannot start with each line.
For (Int J = 0; j <width; ++ J)
{
Int r_32 = imagebits_32 [linenum_32 + J * 4 + 2];
Int g_32 = imagebits_32 [linenum_32 + J * 4 + 1];
Int B _32 = imagebits_32 [linenum _ 32 + J * 4];
// Int r_24 = imagebits_24 [linenum_24 + J * 3]; // a 32-bit Graph
// Int g_24 = imagebits_24 [linenum_24 + J * 3 + 1];
// Int B _24 = imagebits_24 [linenum_24 + J * 3 + 2];
// Int gray_8 = imagebits_8 [linenum_8 + J];
......
// Your own operations
}
}
//?? There is a problem, because the actual image data is not based on the actual width. There are two solutions:
Method 1: calculate the actual width by yourself
To:
// Obtain the number of bytes in each row
Int w_32 = (width * 32 + 31)/32*4; // note that there is no rounding here, so do not convert it at will
Int w_24 = (width * 24 + 31)/32*4;
Int w_8 = (width * 8 + 31)/32*4;
// You can also use the QT function to obtain the function. The function is the same as the above.
{
Int w_32 = image32.bytesperline ();
Int w_24 = image24.bytesperline ();
Int w_8 = image8.bytesperline ();
}
For (INT I = 0; I
{
// Now we can take each line according to the general understanding
Linenum_32 = I * w_32; // note that multiplication is no longer required here (4, 3, etc)
// Linenum_24 = I * w_24;
// Linenum_8 = I * w_8;
For (Int J = 0; j <width; ++ J)
{
// The operation here is the same as above
}
}
Method 2: Use scanline (INT) to obtain the first address of each line,
For (INT I = 0; I
{
Imagebits_32 = image32.scanline (I );
Imagebits_24 = image24.scanline (I );
Imagebits_8 = image8.scanline (I );
For (Int J = 0; j <width; ++ J)
{
Int r_32 = imagebits_32 [J * 4 + 2];
Int g_32 = imagebits_32 [J * 4 + 1];
Int B _32 = imagebits_32 [J * 4];
// Int r_24 = imagebits_24 [J * 3];
// Int g_24 = imagebits_24 [J * 3 + 1];
// Int B _24 = imagebits_24 [J * 3 + 2];
// Int gray_8 = imagebits_8 [J];
......
// Your own operations
}
}
OK. The index of the above two methods will not cause the image data offset problem.
4. You have noticed this constructor of qimage. qimage: qimage (uchar *Data, IntWidth, IntHeight, FormatFormat)
Well, this function is used to construct an image from the data of uchar *. Generally, we may first store the image data in uchar,
Uchar * data32 = new uchar [width * height * 4];
Uchar * data24 = new uchar [width * height * 3];
Uchar * data8 = new uchar [width * Height];
There is no problem in constructing an image from data32, but when the width is not an integer multiple of 4, you cannot construct the desired data from data24 and data8, and the program will be suspended, because the data size of these two arrays is not enough for a graph (remember whether the data can be filled in ).
Solution:
You need to calculate the actual data size (in bytes) of your image according to qimage. bytecount () function to obtain the number of bytes of the image. Of course, you can also calculate the formula bytecount = height * W. Here, W is the number of bytes in each row, the calculation method has been discussed above.
Then, you can use qbytearray to obtain the converted pointer data:
For example, put your image data in the array uchar * srcdata;
Qbytearray imagebytearray = qbytearray (const char *) srcdata, bytecount );
Uchar * transdata = (unsignedchar *) imagebytearray. Data ();
Qimage desimage = qimage (transdata, width, height, qimage: Format _...);
Well, after the above conversion, transdata will be an array of completed data, and the resulting image will not have any problems.
Well, I have finally concluded that there are many small problems. I don't want to write them anymore. It should be enough. If there are other problems, let's think about them and we will certainly be able to solve them. Haha