用IJG的jpeglib压缩文件,目标都设成个FILE * outfile; 压缩完了就写到文件里去了,而且只有个压缩质量的参数,不知道根据那个参数压出来的文件尺寸会多大; 我弄个办法解决鸭的,不过比较傻; 这是个基本用法,用这个函数把RGB buffer压缩成个jpeg文件存起来,而我只需要他压缩到一个buffer里给我就行了,我不想要文件存储IO开销; BOOL RGBToJpegFile(const char * fileName, BYTE *dataBuf, UINT widthPix, UINT height, BOOL color, int quality) { if (dataBuf==NULL) return FALSE; if (widthPix==0) return FALSE; if (height==0) return FALSE; LPBYTE tmp; if (!color) {//处理黑白图像 tmp = (BYTE*)new BYTE[widthPix*height]; if (tmp==NULL) { return FALSE; } UINT row,col; for (row=0;row for (col=0;col LPBYTE pRed, pGrn, pBlu; pRed = dataBuf + row * widthPix * 3 + col * 3; pGrn = dataBuf + row * widthPix * 3 + col * 3 + 1; pBlu = dataBuf + row * widthPix * 3 + col * 3 + 2; // luminance int lum = (int)(.299 * (double)(*pRed) + .587 * (double)(*pGrn) + .114 * (double)(*pBlu)); LPBYTE pGray; pGray = tmp + row * widthPix + col; *pGray = (BYTE)lum; } } } struct jpeg_compress_struct cinfo; FILE * outfile=NULL; /* 目标文件 */ int row_stride; /* 行宽*/ struct my_error_mgr jerr; /* Step 1: 分配对象*/ cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = my_error_exit; if (setjmp(jerr.setjmp_buffer)) { /* 出错了 */ jpeg_destroy_compress(&cinfo); if (outfile!=NULL) fclose(outfile); if (!color) { delete [] tmp; } return FALSE; } /* 初始化. */ jpeg_create_compress(&cinfo); /* Step 2: 指定目标 */ if ((outfile = fopen(fileName, "wb")) == NULL) { return FALSE; } jpeg_stdio_dest(&cinfo, outfile); /* Step 3: 设参数*/ cinfo.image_width = widthPix; /* 宽度*/ cinfo.image_height = height;/* 高度*/ if (color) { cinfo.input_components = 3; /* # of color components per pixel */ cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ } else { cinfo.input_components = 1; /* # of color components per pixel */ cinfo.in_color_space = JCS_GRAYSCALE; /* colorspace of input image */ } jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, quality, TRUE ); /*设参数*/ /* Step 4: 开始压缩*/ jpeg_start_compress(&cinfo, TRUE); /* Step 5: 逐行写入 */ row_stride = widthPix * 3; /* 行宽*/ while (cinfo.next_scanline < cinfo.image_height) { /* 逐行写入 */ LPBYTE outRow; if (color) { outRow = dataBuf + (cinfo.next_scanline * widthPix * 3); } else { outRow = tmp + (cinfo.next_scanline * widthPix); } (void) jpeg_write_scanlines(&cinfo, &outRow, 1); } /* Step 6: 完成压缩*/ jpeg_finish_compress(&cinfo); /* 关闭文件. */ fclose(outfile); /* Step 7: 释放对象*/ jpeg_destroy_compress(&cinfo); if (!color) delete [] tmp; /* 完成*/ return TRUE; } =========================================================================== 解决起来挺傻的,不知道有没有人有更好的办法,反正我是一直没再花心思琢磨它,有个用就好了; 定义了一个这样的结构 typedef struct { unsigned char * buff; long buffsize; long next_byte_to_write; }XXX_JPEG_FILE_BUFFER; XXX_JPEG_FILE_BUFFER filebuffer; jpeg_stdio_destf(&cinfo, &filebuffer); //把结构替代输出文件作为目标设进去就行了;这样压缩完成的图片就在buffer里了 不过jpeg_stdio_destf这个函数是不一样的,我自己对jpeglib做了修改,增加了这么一个函数;具体内容下面详述; #define JPEG_BUFFERSIZE 0x100000 long RGBToJpegBuffer( char ** filebuffer, BYTE *dataBuf, UINT widthPix, UINT height, BOOL color, int quality) { if (dataBuf==NULL) return -1; if (widthPix==0) return -1; if (height==0) return -1; LPBYTE tmp; if (!color) {//处理黑白图像 tmp = (BYTE*)new BYTE[widthPix*height]; if (tmp==NULL) { return -1; } UINT row,col; for (row=0;row for (col=0;col LPBYTE pRed, pGrn, pBlu; pRed = dataBuf + row * widthPix * 3 + col * 3; pGrn = dataBuf + row * widthPix * 3 + col * 3 + 1; pBlu = dataBuf + row * widthPix * 3 + col * 3 + 2; // luminance int lum = (int)(.299 * (double)(*pRed) + .587 * (double)(*pGrn) + .114 * (double)(*pBlu)); LPBYTE pGray; pGray = tmp + row * widthPix + col; *pGray = (BYTE)lum; } } } struct jpeg_compress_struct cinfo;
int row_stride; /* 行宽*/ struct my_error_mgr jerr; /* Step 1: 分配对象*/ cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = my_error_exit; if (setjmp(jerr.setjmp_buffer)) { /* 出错了 */ jpeg_destroy_compress(&cinfo); if (!color) { delete [] tmp; } return -1; } /* 初始化. */ jpeg_create_compress(&cinfo); /* Step 2: 指定目标 */ XXX_JPEG_FILE_BUFFER filebuffer; filebuffer.buff = (unsigned char *)malloc(JPEG_BUFFERSIZE ); filebuffer.next_byte_to_write = 0; if (filebuffer.buff == NULL) { return 0; } jpeg_stdio_destf(&cinfo, &filebuffer); /* Step 3: 设参数*/ cinfo.image_width = widthPix; /* 宽度*/ cinfo.image_height = height;/* 高度*/ if (color) { cinfo.input_components = 3; /* # of color components per pixel */ cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ } else { cinfo.input_components = 1; /* # of color components per pixel */ cinfo.in_color_space = JCS_GRAYSCALE; /* colorspace of input image */ } jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, quality, TRUE ); /*设参数*/ /* Step 4: 开始压缩*/ jpeg_start_compress(&cinfo, TRUE); /* Step 5: 逐行写入 */ row_stride = widthPix * 3; /* 行宽*/ while (cinfo.next_scanline < cinfo.image_height) { /* 逐行写入 */ LPBYTE outRow; if (color) { outRow = dataBuf + (cinfo.next_scanline * widthPix * 3); } else { outRow = tmp + (cinfo.next_scanline * widthPix); } (void) jpeg_write_scanlines(&cinfo, &outRow, 1); } /* Step 6: 完成压缩*/ jpeg_finish_compress(&cinfo); /* Step 7: 释放对象*/ jpeg_destroy_compress(&cinfo); if (!color) delete [] tmp; /* 完成*/ * filebuffer = filebuffer.buff return filebuffer.next_byte_to_write; } //============================================================================== 下面说如何扩展jpeglib的流管理器,jpeglib有文档专门说如何做自己的流管理器,我就是看完了那个然后拿原来的库改的; 在jdatadstf.c这个文件里做文章,这个文件是我把jdatadst.c做了一份拷贝改了个名字加到jpeglib工程里的; 定义自己的管理器结构 typedef struct { struct jpeg_destination_mgr pub; /* public fields */ XXX_JPEG_FILE_BUFFER * outfile; /* target stream */ JOCTET * buffer; /* start of buffer */ } my_destination_mgrf; typedef my_destination_mgrf * my_dest_ptrf; #define OUTPUT_BUF_SIZE 4096 /* 缓冲区块大小*/ //------------------------------------------自己的初始化函数--------------------------- METHODDEF(void) init_destination (j_compress_ptr cinfo) // { my_dest_ptrf dest = (my_dest_ptrf) cinfo->dest; dest->buffer = (JOCTET *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, OUTPUT_BUF_SIZE * SIZEOF(JOCTET)); dest->pub.next_output_byte = dest->buffer; dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; } //-----------------------------------清空函数------------------------------------------------------ METHODDEF(boolean) empty_output_buffer (j_compress_ptr cinfo) { my_dest_ptrf dest = (my_dest_ptrf) cinfo->dest; unsigned char * destbuff = dest->outfile->buff + dest->outfile->next_byte_to_write; memcpy(destbuff, dest->buffer, OUTPUT_BUF_SIZE); dest->outfile->next_byte_to_write += OUTPUT_BUF_SIZE; // ERREXIT(cinfo, JERR_FILE_WRITE); dest->pub.next_output_byte = dest->buffer; dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; return TRUE; } //-------------------------------------这个函数干啥的忘了-------------------------------------------------- METHODDEF(void) term_destination (j_compress_ptr cinfo) { my_dest_ptrf dest = (my_dest_ptrf) cinfo->dest; size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; unsigned char * destbuff = dest->outfile->buff + dest->outfile->next_byte_to_write; /* Write any data remaining in the buffer */ if (datacount > 0) { memcpy(destbuff, dest->buffer, datacount); dest->outfile->next_byte_to_write += datacount; } //fflush(dest->outfile); /* Make sure we wrote the output file OK */ //if (ferror(dest->outfile)) // ERREXIT(cinfo, JERR_FILE_WRITE); }
//--------------------------------------------这个就是最关键的,公开的那个------------------------------- GLOBAL(void) jpeg_stdio_destf (j_compress_ptr cinfo, XXX_JPEG_FILE_BUFFER * outbuffer) { my_dest_ptrf dest; if (cinfo->dest == NULL) { /* first time for this JPEG object? */ cinfo->dest = (struct jpeg_destination_mgr *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(my_destination_mgrf)); } dest = (my_dest_ptrf) cinfo->dest; dest->pub.init_destination = init_destination; dest->pub.empty_output_buffer = empty_output_buffer; dest->pub.term_destination = term_destination; dest->outfile = outbuffer; } 后面还有工作要做 在jpeglib.h文件中加入这一行#define jpeg_stdio_destf jStdDestf 还有这一行 EXTERN(void) jpeg_stdio_destf JPP((j_compress_ptr cinfo, XXX_JPEG_FILE_BUFFER * outbuffer)); 重新编译jpeglib以后自己用就可以了; |