中国IT动力,最新最全的IT技术教程
最新100篇 | 推荐100篇 | 专题100篇 | 排行榜 | 搜索 | 在线API文档
首 页 | 程序开发 | 操作系统 | 软件应用 | 图形图象 | 网络应用 | 精文荟萃 | 教育认证 | 硬件维护 | 未整理篇 | 站长教程
ASP JS PHP工程 ASP.NET 网站建设 UML J2EESUN .NET VC VB VFP 网络维护 数据库 DB2 SQL2000 Oracle Mysql
服务器 Win2000 Office C DreamWeaver FireWorks Flash PhotoShop 上网宝典 CorelDraw 协议大全 网络安全 微软认证
硬件维护  CPU  主板  硬盘  内存  显卡  显示器  键盘鼠标  声卡音箱  打印机  机箱电源  BIOS  网卡  C#  Java  Delphi  vs.net2005
  当前位置:> 程序开发 > 编程语言 > C/C++
JPEG压缩图像尺寸
作者:未知 时间:2005-09-13 23:28 出处:Blog.ChinaUnix.net 责编:chinaitpower
              摘要:JPEG压缩图像尺寸

用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以后自己用就可以了;

关闭本页
 
首页 | 投资与合作 | 服务条款 | 隐私政策 | 收藏本站 | 设为首页 | 新用户注册 | 免责声明 | 使用帮助
Copyright ©2005-2008 chinaitpower.com All rights reserved. www.chinaitpower.com 版权所有