Recently, libpng and libjpeg have been used in our work to parse images. We need to parse RGB data, provide 8-bit and 24-bit 2 excuses, and scale images, I have written my own code based on my articles from various friends on the Internet, and I am posting it for your reference.
1. read from a file:
Bool pngimage: loadfromfile (const char * path, image_type type)
{
// Re-Initialize to prevent loading multiple images.
M_good = false;
M_width = 0;
M_height = 0;
If (m_bgra)
{
Delete m_bgra; m_bgra = 0; // class member variable, which stores 24-bit RGB data.
}
If (m_8bit)
{
Delete m_8bit; m_8bit = 0; // class member variable, which stores 8-bit data.
}
If (type = image_png)
{
// Parse PNG files
// Try to open file
File * file = fopen (path, "rb ");
// Unable to open
If (file = 0) return false;
// Create read struct
Png_structp png_ptr = png_create_read_struct (png_libpng_ver_string, 0, 0, 0 );
// Check pointer
If (png_ptr = 0)
{
Fclose (File );
Return false;
}
// Create info struct
Png_infop info_ptr = png_create_info_struct (png_ptr );
// Check pointer
If (info_ptr = 0)
{
Png_destroy_read_struct (& png_ptr, 0, 0 );
Fclose (File );
Return false;
}
// Set error handling
If (setjmp (png_jmpbuf (png_ptr )))
{
Png_destroy_read_struct (& png_ptr, & info_ptr, 0 );
Fclose (File );
Return false;
}
// I/O initialization using standard C streams
Png_init_io (png_ptr, file );
// Read entire image, ignore alpha channel. If you want to use alpha channel, remove png_transform_strip_alpha.
Png_read_png (png_ptr, info_ptr, png_transform_expand | png_transform_strip_alpha, 0 );
/*
Png_transform_expand has the following processing:
1. Expand paletted colors into true RGB triplets
2. Expand grayscale images to full 8 bits from 1, 2, or 4 bits/Pixel
3. Expand paletted or RGB Images with transparency to Full Alpha channels so the data will be available
As rgba quartets.
Png_transform_strip_alpha: Strip Alpha bytes from the input data without combining withthe background
*/
Int width = m_width = info_ptr-> width;
Int Height = m_height = info_ptr-> height;
Int color_type = info_ptr-> color_type;
Int bit_depth = info_ptr-> pixel_depth;
Png_bytep * row_pointers = png_get_rows (png_ptr, info_ptr );
Int Pos = 0;
If (color_type = png_color_type_gray)
{// Grayscale image processing
M_8bit = new unsigned char [width * Height];
Memset (m_8bit, 0, width * Height );
For (INT I = 0; I {
For (Int J = 0; j <width; j + = 1)
{
M_8bit [POS ++] = row_pointers [I] [J];
}
}
}
Else
{// Process non-Grayscale Images
M_bgra = new unsigned char [width * height * 3];
Memset (m_bgra, 0, width * height * 3 );
For (INT I = 0; I {
For (Int J = 0; j <3 * width; j + = 3)
{
M_bgra [POS ++] = row_pointers [I] [J + 2]; // blue
M_bgra [POS ++] = row_pointers [I] [J + 1]; // green
M_bgra [POS ++] = row_pointers [I] [J]; // red
}
}
}
// Free memory
Png_destroy_read_struct (& png_ptr, & info_ptr, 0 );
// Close file
Fclose (File );
}
Else if (type = image_jpeg)
{// Parse JPEG images
Struct performance_decompress_struct Cinfo;
Struct performance_error_mgr Jerr;
Cinfo. Err = maid (& Jerr );
Pai_create_decompress (& Cinfo );
File * infile;
If (infile = fopen (path, "rb") = NULL)
{
Printf ("Open File error! /N ");
Return false;
}
Performance_stdio_src (& Cinfo, infile );
Pai_read_header (& Cinfo, true );
M_height = Cinfo. image_height;
M_width = Cinfo. image_width;
M_bgra = new unsigned char [Cinfo. image_width * Cinfo. image_height * Cinfo. num_components];
Pai_start_decompress (& Cinfo );
Jsamprow row_pointer [1];
While (Cinfo. output_scanline <Cinfo. output_height)
{
/* Row_pointer [0] = & m_bgr [(Cinfo. output_height-cinfo.output_scanline-1)
* Cinfo. image_width * Cinfo. num_components]; */
Row_pointer [0] = & m_bgra [Cinfo. output_scanline * Cinfo. image_width * Cinfo. num_components];
Pai_read_scanlines (& Cinfo, row_pointer, 1 );
}
Pai_finish_decompress (& Cinfo );
Pai_destroy_decompress (& Cinfo );
Fclose (infile );
}
Return true;
}
2. Read from memory:
For PNG format, you need to reset the read callback function for reading from memory, and then use the png_set_read_fn () function to specify the READ function.
For JPEG format, you only need to use the pai_mem_src () function to replace the original jpeg_stdio_src (& Cinfo, infile) read from the file.
Typedef struct
{
Unsigned char * data;
Int size;
Int offset;
} Imagesource;
// Callback function for reading PNG images from memory
Static void pngreadcallback (png_structp png_ptr, png_bytep data, png_size_t length)
{
Imagesource * isource = (imagesource *) png_get_io_ptr (png_ptr );
If (isource-> Offset + Length <= isource-> size)
{
Memcpy (data, isource-> Data + isource-> offset, length );
Isource-> Offset + = length;
}
Else
Png_error (png_ptr, "pngreadercallback failed ");
}
// Read from memory
Bool pngimage: loadfromstream (unsigned char * data, const unsigned int datasize, image_type type)
{
M_good = false;
M_width = 0;
M_height = 0;
If (m_bgra)
{
Delete m_bgra; m_bgra = 0;
}
If (m_8bit)
{
Delete m_8bit; m_8bit = 0;
}
If (type = image_png)
{
Png_structp png_ptr = png_create_read_struct (png_libpng_ver_string, 0, 0, 0 );
If (png_ptr = 0)
Return false;
Png_infop info_ptr = png_create_info_struct (png_ptr );
If (info_ptr = 0)
{
Png_destroy_read_struct (& png_ptr, 0, 0 );
Return false;
}
If (setjmp (png_jmpbuf (png_ptr )))
{
Png_destroy_read_struct (& png_ptr, & info_ptr, 0 );
}
Imagesource imgsource;
Imgsource. Data = data;
Imgsource. size = datasize;
Imgsource. offset = 0;
Png_set_read_fn (png_ptr, & imgsource, pngreadcallback );
Png_read_png (png_ptr, info_ptr, png_transform_expand | png_transform_strip_alpha, 0 );
Int width = m_width = info_ptr-> width;
Int Height = m_height = info_ptr-> height;
Int color_type = info_ptr-> color_type;
Int bit_depth = info_ptr-> pixel_depth;
Png_bytep * row_pointers = png_get_rows (png_ptr, info_ptr );
Int Pos = 0;
If (color_type = png_color_type_gray)
{
M_8bit = new unsigned char [width * Height];
Memset (m_8bit, 0, width * Height );
For (INT I = 0; I {
For (Int J = 0; j <width; j + = 1)
{
M_8bit [POS ++] = row_pointers [I] [J];
}
}
}
Else
{
M_bgra = new unsigned char [width * height * 3];
Memset (m_bgra, 0, width * height * 3 );
For (INT I = 0; I {
For (Int J = 0; j <3 * width; j + = 3)
{
M_bgra [POS ++] = row_pointers [I] [J + 2]; // blue
M_bgra [POS ++] = row_pointers [I] [J + 1]; // green
M_bgra [POS ++] = row_pointers [I] [J]; // red
}
}
}
// Free memory
Png_destroy_read_struct (& png_ptr, & info_ptr, 0 );
}
Else if (type = image_jpeg)
{
Struct performance_decompress_struct Cinfo;
Struct performance_error_mgr Jerr;
Cinfo. Err = maid (& Jerr );
Pai_create_decompress (& Cinfo );
// Read from memory
Performance_mem_src (& Cinfo, Data, datasize );
Pai_read_header (& Cinfo, true );
M_height = Cinfo. image_height;
M_width = Cinfo. image_width;
M_bgra = new unsigned char [Cinfo. image_width * Cinfo. image_height * Cinfo. num_components];
Pai_start_decompress (& Cinfo );
Jsamprow row_pointer [1];
While (Cinfo. output_scanline <Cinfo. output_height)
{
/* Row_pointer [0] = & m_bgr [(Cinfo. output_height-cinfo.output_scanline-1)
* Cinfo. image_width * Cinfo. num_components]; */
Row_pointer [0] = & m_bgra [Cinfo. output_scanline * Cinfo. image_width * Cinfo. num_components];
Pai_read_scanlines (& Cinfo, row_pointer, 1 );
}
Pai_finish_decompress (& Cinfo );
Pai_destroy_decompress (& Cinfo );
}
Return/* (m_good = true) */true;
}
3. Scaling images is a widely spread interpolation algorithm on the Internet.
The input parameter is: return the image width (w_dest), return the Image Height (h_dest), return the image depth (bit_depth), and the source image RGB data (SRC ), the source image width (w_src) and the source Image Height (h_src ).
Unsigned char * pngimage: do_stretch_linear (INT w_dest, int h_dest, int bit_depth, unsigned char * SRC, int w_src, int h_src)
{
Int Sw = w_Src-1, SH = h_Src-1, DW = w_Dest-1, DH = h_Dest-1;
Int B, n, x, y;
Int npixelsize = bit_depth/8;
Unsigned char * plineprev, * plinenext;
Unsigned char * pdest = new unsigned char [w_dest * h_dest * bit_depth/8];
Unsigned char * TMP;
Unsigned char * pA, * pb, * PC, * PD;
For (INT I = 0; I <= DH; ++ I)
{
TMP = pdest + I * w_dest * npixelsize;
Y = I * sh/DH;
N = DH-I * sh % DH;
Plineprev = SRC + (Y ++) * w_src * npixelsize;
// Plineprev = (unsigned char *) asrc-> m_bitbuf + (Y ++) * asrc-> m_width * npixelsize );
Plinenext = (n = DH )? Plineprev: SRC + y * w_src * npixelsize;
// Plinenext = (n = DH )? Plineprev: (unsigned char *) asrc-> m_bitbuf + (y * asrc-> m_width * npixelsize );
For (Int J = 0; j <= dw; ++ J)
{
X = J * Sw/DW * npixelsize;
B = DW-J * SW % dw;
Pa = plineprev + X;
PB = pa + npixelsize;
PC = plinenext + X;
Pd = PC + npixelsize;
If (B = DW)
{
PB = PA;
Pd = pc;
}
For (int K = 0; k <npixelsize; ++ K)
{
* TMP ++ = (unsigned char) (INT )(
(B * n * (* pA ++-* pb-* PC + * PD) + DW * n ** Pb ++
+ DH * B ** PC ++ (DW * DH-DH * B-DW * n) ** PD ++
+ DW * DH/2)/(DW * DH ));
}
}
}
Return pdest;
}
If you find any imperfections, you are welcome to discuss them.