在做算法的过程中经常终端传来的是jpeg图片,需要将jpeg解码为yuv再进行处理。这里使用jpeg-6b交叉编译,然后进行解码,下面是解码的过程:
#include <ctype.h>
#include <errno.h>
#include <unistd.h>
#include <setjmp.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include "jpeglib.h"
#include <setjmp.h>
#include "decode.h"
struct my_error_mgr {
struct jpeg_error_mgr pub; /* "public" fields */
jmp_buf setjmp_buffer; /* for return to caller */
};
typedef struct my_error_mgr * my_error_ptr;
void my_decompress_error_exit (j_common_ptr cinfo)
{
/* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
my_error_ptr myerr = (my_error_ptr) cinfo->err;
/* Always display the message. */
/* We could postpone this until after returning, if we chose. */
(*cinfo->err->output_message) (cinfo);
/* Return control to the setjmp point */
longjmp(myerr->setjmp_buffer, 1);
}
int decode_jpeg_file (char *frame,int frame_size,char *decoded_frame,int *decoded_frame_size,int *decoded_width,int *decoded_height,int color_space)
{
struct jpeg_decompress_struct cinfo;
struct my_error_mgr jerr;
FILE *infile, *outfile;
JSAMPARRAY buffer; /* Output row buffer */
int row_stride; /* physical row width in output buffer */
int finished = 1;
int chromaWidth, chromaHeight;
int yMask,xMask;
int x,y;
int width,height;
unsigned char *pixels=NULL,*rgbPixels=NULL, *src=NULL;
unsigned char *yPixels=NULL, *uPixels=NULL, *vPixels=NULL;
unsigned char *yPtr=NULL, *uPtr=NULL, *vPtr=NULL;
cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = my_decompress_error_exit;
if (setjmp(jerr.setjmp_buffer))
{
jpeg_destroy_decompress(&cinfo);
//fclose(infile);
return -1;
}
jpeg_create_decompress(&cinfo);
//jpeg_stdio_src(&cinfo, infile);
jpeg_stdio_buffer_src(&cinfo,(unsigned char *)(frame),frame_size);
(void) jpeg_read_header(&cinfo, TRUE);
/*set parameters for decompression */
cinfo.out_color_space = JCS_YCbCr;
(void) jpeg_start_decompress(&cinfo);
width = cinfo.output_width;
height = cinfo.output_height;
*decoded_width = width;
*decoded_height = height;
pixels = (unsigned char *)malloc(width*height*3);
if(pixels==NULL)
printf("Malloc pixels failed!!!!\n");
memset(pixels, 0, width * height * 3);
src = rgbPixels = pixels;
/* JSAMPLEs per row in output buffer */
row_stride = cinfo.output_width * cinfo.output_components;
/* Make a one-row-high sample array that will go away when done with image */
buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
printf("cinfo.output_width:%d\n",cinfo.output_width);
printf("cinfo.output_height:%d\n",cinfo.output_height);
printf("cinfo.output_components:%d\n",cinfo.output_components);
while (cinfo.output_scanline < cinfo.output_height)
{
int num_rows = jpeg_read_scanlines(&cinfo, buffer, 1);
// printf("cinfo.output_scanline:%d\n",cinfo.output_scanline);
// printf("num_rows:%d\n",num_rows);
// printf("\t\tcinfo.output_components:%d\n",cinfo.output_components);
// getchar();
if (num_rows == 0)
{
finished = 0;
break;
}
if (cinfo.output_components == 1)
{
// greyscale
unsigned int i;
unsigned char *in = (unsigned char *)(*buffer);
for (i = 0; i < width * num_rows; ++i)
{
*pixels++ = *in; // red b
*pixels++ = *in; // green g
*pixels++ = *in; // blue r
++in;
}
}
else if (cinfo.output_components == 3)
{
// RGB
memcpy(rgbPixels, (*buffer), num_rows * width * 3);
rgbPixels += num_rows * width * 3;
//memcpy(pixels, (*buffer), num_rows * width * 3);
//pixels += num_rows * width * 3;
}
}
rgbPixels = pixels;
if(finished)
{
printf("jpeg_finish_decompress!\n");
(void) jpeg_finish_decompress(&cinfo);
}
printf("\n");
jpeg_destroy_decompress(&cinfo);
printf("jpeg_destroy_decompress finished! \n");
// fwrite(yPixels, 1, width * height, outfile);
// fwrite(uPixels, 1, chromaWidth*chromaHeight, outfile);
// fwrite(vPixels, 1, chromaWidth*chromaHeight, outfile);
// fwrite(rgbPixels, 1, width * height*3, outfile);
//if( NULL !=infile)
//{
// fclose(infile);
//}
//if(NULL != outfile)
//{
// fclose(outfile);
//}
/*
if(width!=352||height!=288)
{
printf("Decoded img:wid=%d,hgt=%d\tError!!!!!!!not 352*288!!!!\n",width,height);
return -1;
}
else
*/
if (color_space == DECODE_COLOR_Y||color_space == DECODE_COLOR_GRAY)
{
yPixels = (unsigned char*)malloc(height * width);
if(yPixels==NULL)printf("Malloc yPixels fail!!!\n");
yPtr = yPixels;
for(y = 0; y < height; y++)
{
for(x = 0; x < width; x++)
{
*yPtr++ = *rgbPixels++;
rgbPixels += 2;
}
}
memcpy(decoded_frame, yPixels, height * width );
*decoded_frame_size = height * width;
}
else if (color_space == DECODE_COLOR_YUV420)
{
chromaWidth = width/2;
chromaHeight = height/2;
printf("color_space DECODE_COLOR_YUV420! \n");
yMask = xMask = 1;
yPixels = (unsigned char*)malloc(width * height);
if(yPixels==NULL)printf("Malloc yPixels fail!!!\n");
uPixels = (unsigned char*)malloc(chromaWidth*chromaHeight);
if(uPixels==NULL)printf("Malloc uPixels fail!!!\n");
vPixels = (unsigned char*)malloc(chromaWidth*chromaHeight);
if(vPixels==NULL)printf("Malloc vPixels fail!!!\n");
yPtr = yPixels;
uPtr = uPixels;
vPtr = vPixels;
for(y = 0; y < height; y++)
{
for(x = 0; x < width; x++)
{
*yPtr++ = *rgbPixels++;
if((y & yMask) == 0 && (x & xMask) == 0)
{
*uPtr++ = *rgbPixels++;
*vPtr++ = *rgbPixels++;
}
else
{
rgbPixels += 2;
}
}
}
memcpy(decoded_frame, yPixels, height * width );
memcpy(decoded_frame+height * width, uPixels, chromaHeight * chromaWidth );
memcpy(decoded_frame+height * width+chromaHeight * chromaWidth, vPixels, chromaHeight * chromaWidth );
*decoded_frame_size = height * width/2*3;
printf("decoded_frame:%d\n", *decoded_frame_size);
rgbPixels=NULL;
}
else if (color_space == DECODE_COLORYUV444)
{
chromaWidth = width;
chromaHeight = height;
yPixels = (unsigned char*)malloc(height * width);
if(yPixels==NULL)printf("Malloc yPixels fail!!!\n");
uPixels = (unsigned char*)malloc(chromaWidth*chromaHeight);
if(uPixels==NULL)printf("Malloc uPixels fail!!!\n");
vPixels = (unsigned char*)malloc(chromaWidth*chromaHeight);
if(vPixels==NULL)printf("Malloc vPixels fail!!!\n");
yPtr = yPixels;
uPtr = uPixels;
vPtr = vPixels;
for(y = 0; y < height; y++)
{
for(x = 0; x < width; x++)
{
*yPtr++ = *rgbPixels++;
*uPtr++ = *rgbPixels++;
*vPtr++ = *rgbPixels++;
}
}
memcpy(decoded_frame, yPixels, height * width );
memcpy(decoded_frame+height * width, uPixels, height * width );
memcpy(decoded_frame+2*height * width, vPixels, height * width );
*decoded_frame_size = height * width*3;
}
if( NULL !=pixels)
{
free(pixels);
pixels = NULL;
}
if( NULL !=yPixels)
{
free(yPixels);
yPixels = NULL;
}
if( NULL !=uPixels)
{
free(uPixels);
uPixels = NULL;
}
if( NULL !=vPixels)
{
free(vPixels);
vPixels = NULL;
}
if( NULL !=rgbPixels)
{
rgbPixels = NULL;
}
return 0;
}
需要注意的是,jpeg-6b解码好像只能用gcc编译,用g++会出错,我通常是将其封装成库,用gcc编译,然后在c++中调用。