IMAJPG.CPP
上传用户:wep9318
上传日期:2007-01-07
资源大小:893k
文件大小:11k
源码类别:

图片显示

开发平台:

Visual C++

  1. /*
  2.  * File: imajpg.cc
  3.  * Purpose: Platform Independent JPEG Image Class
  4.  * Author: Alejandro Aguilar Sierra
  5.  * Created: 1995
  6.  * Copyright: (c) 1995, Alejandro Aguilar Sierra <asierra@servidor.unam.mx>
  7.  *
  8.  * This software is based in part on the work of the Independent JPEG Group.
  9.  *
  10.  */
  11.  
  12. // #include "stdafx.h"
  13. #include "imajpg.h"
  14. #if CIMAGE_SUPPORT_JPEG
  15. #include <stdio.h>
  16. extern "C" {
  17. #include "jpeglib.h"
  18. }
  19. #include "imaiter.h"
  20.          
  21. #include <setjmp.h>
  22. #ifdef _DEBUG
  23. #define new DEBUG_NEW
  24. #undef THIS_FILE
  25. static char THIS_FILE[] = __FILE__;
  26. #endif
  27. struct ima_error_mgr {
  28.   struct jpeg_error_mgr pub; /* "public" fields */
  29.   jmp_buf setjmp_buffer; /* for return to caller */
  30. };
  31. typedef ima_error_mgr *ima_error_ptr;
  32. /*
  33.  * Here's the routine that will replace the standard error_exit method:
  34.  */
  35. METHODDEF void
  36. ima_jpeg_error_exit (j_common_ptr cinfo)
  37. {
  38.   /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
  39.   ima_error_ptr myerr = (ima_error_ptr) cinfo->err;
  40.   char buffer[JMSG_LENGTH_MAX];
  41.   /* Create the message */
  42.   myerr->pub.format_message (cinfo, buffer);
  43.   /* Send it to stderr, adding a newline */
  44. //        AfxMessageBox(buffer);
  45.   /* Return control to the setjmp point */
  46.   longjmp(myerr->setjmp_buffer, 1);
  47. }
  48. BOOL
  49. CImageJPG::ReadFile(const CString& imageFileName)
  50. {
  51.   if (imageFileName != "")
  52.     filename = imageFileName;
  53.     
  54.   CImageIterator iter(this);
  55.   /* This struct contains the JPEG decompression parameters and pointers to
  56. * working space (which is allocated as needed by the JPEG library).
  57. */
  58.   struct jpeg_decompress_struct cinfo;
  59.   /* We use our private extension JPEG error handler. */
  60.   struct ima_error_mgr jerr;
  61. //  struct jpeg_error_mgr jerr;
  62.   /* More stuff */
  63.   FILE * infile; /* source file */
  64.   JSAMPARRAY buffer; /* Output row buffer */
  65.   int row_stride; /* physical row width in output buffer */
  66.   /* In this example we want to open the input file before doing anything else,
  67. * so that the setjmp() error recovery below can assume the file is open.
  68. * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
  69. * requires it in order to read binary files.
  70. */
  71.   if ((infile = fopen((const char *)filename, "rb")) == NULL) {
  72.  //fprintf(stderr, "can't open %sn", filename);
  73.  return 0;
  74.   }
  75.   /* Step 1: allocate and initialize JPEG decompression object */
  76.   /* We set up the normal JPEG error routines, then override error_exit. */
  77.   cinfo.err = jpeg_std_error(&jerr.pub);
  78.   jerr.pub.error_exit = ima_jpeg_error_exit;
  79.   /* Establish the setjmp return context for my_error_exit to use. */
  80.   if (setjmp(jerr.setjmp_buffer)) {
  81.  /* If we get here, the JPEG code has signaled an error.
  82.   * We need to clean up the JPEG object, close the input file, and return.
  83.   */
  84.  jpeg_destroy_decompress(&cinfo);
  85.  fclose(infile);
  86.  return 0;
  87.   }
  88.   /* Now we can initialize the JPEG decompression object. */
  89.   jpeg_create_decompress(&cinfo);
  90.   /* Step 2: specify data source (eg, a file) */
  91.   jpeg_stdio_src(&cinfo, infile);
  92.   /* Step 3: read file parameters with jpeg_read_header() */
  93.   (void) jpeg_read_header(&cinfo, TRUE);
  94.   /* Step 4: set parameters for decompression */
  95. //  printf("info %d %d %d CS %d ", cinfo.image_width, cinfo.image_height, cinfo.output_components, cinfo.jpeg_color_space);
  96.   if (cinfo.jpeg_color_space!=JCS_GRAYSCALE) {
  97. cinfo.quantize_colors = TRUE;
  98. cinfo.desired_number_of_colors = 128;
  99.   }
  100.   /* Step 5: Start decompressor */
  101.   jpeg_start_decompress(&cinfo);
  102.   /* We may need to do some setup of our own at this point before reading
  103. * the data.  After jpeg_start_decompress() we have the correct scaled
  104. * output image dimensions available, as well as the output colormap
  105. * if we asked for color quantization.
  106. */
  107.   Create(cinfo.image_width, cinfo.image_height, 8*cinfo.output_components);
  108.   if (cinfo.jpeg_color_space==JCS_GRAYSCALE)
  109.  CreateGrayColourMap(256);
  110.   else
  111.  SetPalette(cinfo.actual_number_of_colors, cinfo.colormap[0], cinfo.colormap[1], cinfo.colormap[2]);
  112.   /* JSAMPLEs per row in output buffer */
  113.   row_stride = cinfo.output_width * cinfo.output_components;
  114. //  byte* buf2 = new byte[row_stride];
  115. //  printf("NCMPS cmp [%d %d %d]", cinfo.output_components, cinfo.actual_number_of_colors,row_stride);
  116.   /* Make a one-row-high sample array that will go away when done with image */
  117.   buffer = (*cinfo.mem->alloc_sarray)
  118. ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
  119.   /* Step 6: while (scan lines remain to be read) */
  120.   /*           jpeg_read_scanlines(...); */
  121.   /* Here we use the library's state variable cinfo.output_scanline as the
  122. * loop counter, so that we don't have to keep track ourselves.
  123. */
  124.   iter.Upset();
  125.   while (cinfo.output_scanline < cinfo.output_height) {
  126.  (void) jpeg_read_scanlines(&cinfo, buffer, 1);
  127.  /* Assume put_scanline_someplace wants a pointer and sample count. */
  128. /*  for (int i=0; i<row_stride; i+=3) {
  129. buf2[i+2] = buffer[0][i];
  130. buf2[i+1] = buffer[0][i+1];
  131. buf2[i] = buffer[0][i+2];
  132.  }*/
  133. //  iter.SetRow(row_stride, buf2);
  134.  iter.SetRow(buffer[0], row_stride);
  135.  iter.PrevRow();
  136. //  put_scanline_someplace(buffer[0], row_stride);
  137.   }
  138.   /* Step 7: Finish decompression */
  139.   (void) jpeg_finish_decompress(&cinfo);
  140.   /* We can ignore the return value since suspension is not possible
  141. * with the stdio data source.
  142. */
  143.   /* Step 8: Release JPEG decompression object */
  144.   /* This is an important step since it will release a good deal of memory. */
  145.   jpeg_destroy_decompress(&cinfo);
  146.   /* After finish_decompress, we can close the input file.
  147. * Here we postpone it until after no more JPEG errors are possible,
  148. * so as to simplify the setjmp error logic above.  (Actually, I don't
  149. * think that jpeg_destroy can do an error exit, but why assume anything...)
  150. */
  151.   fclose(infile);
  152.   /* At this point you may want to check to see whether any corrupt-data
  153. * warnings occurred (test whether jerr.pub.num_warnings is nonzero).
  154. */
  155.   /* And we're done! */
  156.   return 1;
  157. }
  158. BOOL CImageJPG::SaveFile(const CString& imageFileName)
  159. {
  160.   if (imageFileName != "")
  161.  filename = imageFileName;
  162.   CImageIterator iter(this);
  163. byte *buf2=0;
  164. //  puts("saving");
  165.   /* This struct contains the JPEG compression parameters and pointers to
  166. * working space (which is allocated as needed by the JPEG library).
  167. * It is possible to have several such structures, representing multiple
  168. * compression/decompression processes, in existence at once.  We refer
  169. * to any one struct (and its associated working data) as a "JPEG object".
  170. */
  171.   struct jpeg_compress_struct cinfo;
  172.   /* This struct represents a JPEG error handler.  It is declared separately
  173. * because applications often want to supply a specialized error handler
  174. * (see the second half of this file for an example).  But here we just
  175. * take the easy way out and use the standard error handler, which will
  176. * print a message on stderr and call exit() if compression fails.
  177. * Note that this struct must live as long as the main JPEG parameter
  178. * struct, to avoid dangling-pointer problems.
  179. */
  180.   struct jpeg_error_mgr jerr;
  181.   /* More stuff */
  182.   FILE * outfile; /* target file */
  183.   int row_stride; /* physical row width in image buffer */
  184.   JSAMPARRAY buffer; /* Output row buffer */
  185.   /* Step 1: allocate and initialize JPEG compression object */
  186.   /* We have to set up the error handler first, in case the initialization
  187. * step fails.  (Unlikely, but it could happen if you are out of memory.)
  188. * This routine fills in the contents of struct jerr, and returns jerr's
  189. * address which we place into the link field in cinfo.
  190. */
  191.   cinfo.err = jpeg_std_error(&jerr);
  192.   /* Now we can initialize the JPEG compression object. */
  193.   jpeg_create_compress(&cinfo);
  194.   /* Step 2: specify data destination (eg, a file) */
  195.   /* Note: steps 2 and 3 can be done in either order. */
  196.   /* Here we use the library-supplied code to send compressed data to a
  197. * stdio stream.  You can also write your own code to do something else.
  198. * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
  199. * requires it in order to write binary files.
  200. */
  201.   if ((outfile = fopen((const char *)filename, "wb")) == NULL) {
  202. //  fprintf(stderr, "can't open %sn", filename);
  203.  return FALSE;
  204.   }
  205.   jpeg_stdio_dest(&cinfo, outfile);
  206.   /* Step 3: set parameters for compression */
  207.   /* First we supply a description of the input image.
  208. * Four fields of the cinfo struct must be filled in:
  209. */
  210.   cinfo.image_width = GetWidth();  // image width and height, in pixels
  211.   cinfo.image_height = GetHeight();
  212.   cinfo.input_components = 3;  // # of color components per pixel
  213.   cinfo.in_color_space = JCS_RGB;  /* colorspace of input image */
  214. //  printf("info %d %d %d %d ", cinfo.image_width, cinfo.image_height, cinfo.input_components, cinfo.in_color_space);
  215.   /* Now use the library's routine to set default compression parameters.
  216. * (You must set at least cinfo.in_color_space before calling this,
  217. * since the defaults depend on the source color space.)
  218. */
  219.   jpeg_set_defaults(&cinfo);
  220.   /* Now you can set any non-default parameters you wish to.
  221. * Here we just illustrate the use of quality (quantization table) scaling:
  222. */
  223.   jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
  224.   /* Step 4: Start compressor */
  225.   /* TRUE ensures that we will write a complete interchange-JPEG file.
  226. * Pass TRUE unless you are very sure of what you're doing.
  227. */
  228. //  puts("begining");
  229.   jpeg_start_compress(&cinfo, TRUE);
  230.   /* Step 5: while (scan lines remain to be written) */
  231.   /*           jpeg_write_scanlines(...); */
  232.   /* Here we use the library's state variable cinfo.next_scanline as the
  233. * loop counter, so that we don't have to keep track ourselves.
  234. * To keep things simple, we pass one scanline per call; you can pass
  235. * more if you wish, though.
  236. */
  237.   row_stride = GetWidth()*cinfo.input_components; /* JSAMPLEs per row in image_buffer */
  238.   buffer = (*cinfo.mem->alloc_sarray)
  239. ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
  240. //  puts("now itera");
  241.   iter.Upset();
  242.   while (cinfo.next_scanline < cinfo.image_height) {
  243.  if (GetPalette())
  244.  {
  245. buf2 = new byte[GetWidth()];
  246. iter.GetRow(buf2, GetWidth());
  247. int k=0;
  248. for (int i=0; i<GetWidth(); i++, k+=3)
  249.   GetPalette()->GetRGB(buf2[i], &buffer[0][k], &buffer[0][k+1], &buffer[0][k+2]);
  250.  } else
  251. iter.GetRow(buffer[0], row_stride);
  252.   
  253.  iter.PrevRow();
  254.  (void) jpeg_write_scanlines(&cinfo, buffer, 1);
  255.   }
  256.   delete buf2;
  257. //  puts("iterado");
  258.   /* Step 6: Finish compression */
  259.   jpeg_finish_compress(&cinfo);
  260.   /* After finish_compress, we can close the output file. */
  261.   fclose(outfile);
  262.   /* Step 7: release JPEG compression object */
  263. //  puts("destroy");
  264.   /* This is an important step since it will release a good deal of memory. */
  265.   jpeg_destroy_compress(&cinfo);
  266.   /* And we're done! */
  267.   return TRUE;
  268. }
  269. void CImageJPG::CreateGrayColourMap(int n)
  270. {
  271.   byte g[256];
  272.   for (int i=0; i<n; i++) g[i] = (byte)(256*i/n);
  273.   SetPalette(n, g);
  274. }
  275. #endif // CIMAGE_SUPPORT_JPEG