更改jpeglib中的特定像素

时间:2011-11-16 08:06:14

标签: c libjpeg

我们在变量char * raw_image中提取了jpeg图像。 在编写新图片之前,我们如何更改原始数据中的特定像素? 我们正在编写c。

这是我们写入和读取图像的功能:

#include <stdio.h>
#include "jpeglib.h"
#include <stdlib.h>

/* we will be using this uninitialized pointer later to store raw, uncompressd image */
unsigned char *raw_image = NULL;
unsigned char *raw_image_tmp = NULL;

/* dimensions of the image we want to write */
int width = 0;
int height = 0;
int bytes_per_pixel = 3;   /* or 1 for GRACYSCALE images */
int color_space = JCS_RGB; /* or JCS_GRAYSCALE for grayscale images */ 

/**
 * read_jpeg_file Reads from a jpeg file on disk specified by filename and saves into the 
 * raw_image buffer in an uncompressed format.
* 
* \returns positive integer if successful, -1 otherwise
* \param *filename char string specifying the file name to read from
*
*/

int read_jpeg_file( char *filename )
{
/* these are standard libjpeg structures for reading(decompression) */
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
/* libjpeg data structure for storing one row, that is, scanline of an image */
JSAMPROW row_pointer[1];

FILE *infile = fopen( filename, "rb" );
unsigned long location = 0;
int i = 0;

if ( !infile )
{
    printf("Error opening jpeg file %s\n!", filename );
    return -1;
}
/* here we set up the standard libjpeg error handler */
cinfo.err = jpeg_std_error( &jerr );
/* setup decompression process and source, then read JPEG header */
jpeg_create_decompress( &cinfo );
/* this makes the library read from infile */
jpeg_stdio_src( &cinfo, infile );
/* reading the image header which contains image information */
jpeg_read_header( &cinfo, TRUE );
/* Uncomment the following to output image information, if needed. */
/*--
printf( "JPEG File Information: \n" );
printf( "Image width and height: %d pixels and %d pixels.\n", cinfo.image_width, cinfo.image_height );
printf( "Color components per pixel: %d.\n", cinfo.num_components );
printf( "Color space: %d.\n", cinfo.jpeg_color_space );
--*/
width = cinfo.image_width;
height = cinfo.image_height; 

/* Start decompression jpeg here */
jpeg_start_decompress( &cinfo );

/* allocate memory to hold the uncompressed image */
raw_image = (unsigned char*)malloc( cinfo.output_width*cinfo.output_height*cinfo.num_components );
/* now actually read the jpeg into the raw buffer */
row_pointer[0] = (unsigned char *)malloc( cinfo.output_width*cinfo.num_components );
/* read one scan line at a time */
while( cinfo.output_scanline < cinfo.image_height )
{
    jpeg_read_scanlines( &cinfo, row_pointer, 1 );
    for( i=0; i<cinfo.image_width*cinfo.num_components;i++) 
        raw_image[location++] = row_pointer[0][i];
}
/* wrap up decompression, destroy objects, free pointers and close open files */
jpeg_finish_decompress( &cinfo );
jpeg_destroy_decompress( &cinfo );
free( row_pointer[0] );
fclose( infile );
/* yup, we succeeded! */
return 1;
}

/**
 * write_jpeg_file Writes the raw image data stored in the raw_image buffer
 * to a jpeg image with default compression and smoothing options in the file
 * specified by *filename.
 *
 * \returns positive integer if successful, -1 otherwise
 * \param *filename char string specifying the file name to save to
 *
 */
int write_jpeg_file( char *filename )
{
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;

/* this is a pointer to one row of image data */
JSAMPROW row_pointer[1];
FILE *outfile = fopen( filename, "wb" );

if ( !outfile )
{
    printf("Error opening output jpeg file %s\n!", filename );
    return -1;
}
cinfo.err = jpeg_std_error( &jerr );
jpeg_create_compress(&cinfo);
jpeg_stdio_dest(&cinfo, outfile);

/* Setting the parameters of the output file here */
cinfo.image_width = width;  
cinfo.image_height = height;
cinfo.input_components = bytes_per_pixel;
cinfo.in_color_space = color_space;
/* default compression parameters, we shouldn't be worried about these */
jpeg_set_defaults( &cinfo );
/* Now do the compression .. */
jpeg_start_compress( &cinfo, TRUE );
/* like reading a file, this time write one row at a time */

while( cinfo.next_scanline < cinfo.image_height)
{
    cinfo.image_width = width;
    row_pointer[0] = &raw_image[ cinfo.next_scanline * cinfo.image_width *  cinfo.input_components];
    jpeg_write_scanlines( &cinfo, row_pointer, 1 );

}
/* similar to read file, clean up after we're done compressing */
jpeg_finish_compress( &cinfo );
jpeg_destroy_compress( &cinfo );
fclose( outfile );
/* success code is 1! */
return 1;
}

我希望有人可以帮助我

基督教

1 个答案:

答案 0 :(得分:1)

raw_image是指向大小为imagewidth * imageheight * 3的字符数组的指针。 '3'代表RGB三联体中的三个组件。

查看代码,我理解的是,jpeg图像被读取并读入缓冲区,缓冲区被发送到解压缩图像的处理器。此外,解压缩的像素数据被写入raw_image缓冲区。下面的代码通过逐行编写来完成这项工作。因此条件“cinfo.output_scanline&lt; cinfo.image_height”和for for循环“i

while( cinfo.output_scanline < cinfo.image_height )
{
    jpeg_read_scanlines( &cinfo, row_pointer, 1 );
    for( i=0; i<cinfo.image_width*cinfo.num_components;i++) 
        raw_image[location++] = row_pointer[0][i];
}

在将此raw_image缓冲区写入文件之前,我想您要进行一些后期处理。是对的吗?如果是这样的话......您可以通过这种方式访问​​像素。

for (i=0; i < cinfo.image_height; i++){
 for (j=0; j < cinfo.image_width; j++){
   // Pixel (i,j)
   raw_image[(i*cinfo.image_width*3)+(j*3)+0]; // Red Pixel
   raw_image[(i*cinfo.image_width*3)+(j*3)+1]; // Green Pixel
   raw_image[(i*cinfo.image_width*3)+(j*3)+2]; // Blue Pixel
   // Now you have pixel (i,j). You can do any thing with this.
 }
}