]> Creatis software - gdcm.git/blobdiff - src/gdcmJpeg.cxx
Fix mistypings
[gdcm.git] / src / gdcmJpeg.cxx
index 5a2fb98418b7eb04edc04fd06822f494d013187c..f4e8862c31f16ac27785ec35bddd575664d0b73a 100644 (file)
@@ -3,8 +3,8 @@
   Program:   gdcm
   Module:    $RCSfile: gdcmJpeg.cxx,v $
   Language:  C++
-  Date:      $Date: 2005/02/04 23:30:21 $
-  Version:   $Revision: 1.41 $
+  Date:      $Date: 2007/08/30 17:37:16 $
+  Version:   $Revision: 1.59 $
                                                                                 
   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
   l'Image). All rights reserved. See Doc/License.txt or
 
 #include <setjmp.h>
 #include <fstream>
+
+#if defined(__BORLANDC__)
+   #include <mem.h> // for memset
+#endif
+
 #include "jdatasrc.cxx"
 #include "jdatadst.cxx"
 
-namespace gdcm 
+namespace GDCM_NAME_SPACE 
 {
 
  /**
- * \brief   routine for JPEG decompression 
- * @param fp pointer to an already open file descriptor 
+ * \brief   routine for JPEG decompression
+ * @param fp pointer to an already open file descriptor
  *                      8 significant bits per pixel
  * @param im_buf Points to array (of R,G,B-order) data to compress
  * @param quality compression quality
- * @param image_height Number of rows in image 
+ * @param image_height Number of rows in image
  * @param image_width Number of columns in image
  * @return 1 on success, 0 on error
  */
-bool gdcm_write_JPEG_file (std::ofstream *fp, void *im_buf, 
-                           int image_width, int image_height, int quality)
-{
 
-   JSAMPLE *image_buffer = (JSAMPLE*) im_buf;
+bool gdcm_write_JPEG_file (std::ostream *fp, char *inputdata, size_t inputlength,
+                           int image_width, int image_height, int numZ,
+                           int sample_pixel, int bitsallocated, int quality)
+{
+  (void)bitsallocated;
+  struct jpeg_compress_struct cinfo;
+  int row_stride;            /* physical row width in image buffer */
 
   /* This struct contains the JPEG compression parameters and pointers to
    * working space (which is allocated as needed by the JPEG library).
@@ -68,7 +75,7 @@ bool gdcm_write_JPEG_file (std::ofstream *fp, void *im_buf,
    * compression/decompression processes, in existence at once.  We refer
    * to any one struct (and its associated working data) as a "JPEG object".
    */
-  struct jpeg_compress_struct cinfo;
+  //struct jpeg_compress_struct cinfo;
   /* This struct represents a JPEG error handler.  It is declared separately
    * because applications often want to supply a specialized error handler
    * (see the second half of this file for an example).  But here we just
@@ -79,9 +86,6 @@ bool gdcm_write_JPEG_file (std::ofstream *fp, void *im_buf,
    */
   struct jpeg_error_mgr jerr;
   /* More stuff */
-  //FILE*  outfile;    /* target FILE* /
-  JSAMPROW row_pointer[1];   /* pointer to JSAMPLE row[s] */
-  int row_stride;            /* physical row width in image buffer */
 
   /* Step 1: allocate and initialize JPEG compression object */
 
@@ -97,17 +101,8 @@ bool gdcm_write_JPEG_file (std::ofstream *fp, void *im_buf,
   /* Step 2: specify data destination (eg, a file) */
   /* Note: steps 2 and 3 can be done in either order. */
 
-  /* Here we use the library-supplied code to send compressed data to a
-   * stdio stream.  You can also write your own code to do something else.
-   * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
-   * requires it in order to write binary files.
-   */
- // if ((outfile = fopen(filename, "wb")) == NULL) {
- //   fprintf(stderr, "can't open %s\n", filename);
- //   exit(1);
- //
- // }
-  jpeg_stdio_dest(&cinfo, fp);
+  int fragment_size = static_cast< int >( inputlength );
+  jpeg_stdio_dest(&cinfo, fp, fragment_size, 1);
 
   /* Step 3: set parameters for compression */
 
@@ -116,13 +111,36 @@ bool gdcm_write_JPEG_file (std::ofstream *fp, void *im_buf,
    */
   cinfo.image_width = image_width;/* image width and height, in pixels */
   cinfo.image_height = image_height;
-  cinfo.input_components = 3;     /* # of color components per pixel */
-  cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
+  if ( sample_pixel == 3 )
+    {
+    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 */
+    }
   /* Now use the library's routine to set default compression parameters.
    * (You must set at least cinfo.in_color_space before calling this,
    * since the defaults depend on the source color space.)
    */
   jpeg_set_defaults(&cinfo);
+  /*
+   * http://www.koders.com/c/fid80DBBF1D49D004EF71CE7C493C34610C4F17D3D3.aspx
+   * http://studio.imagemagick.org/pipermail/magick-users/2002-September/004685.html
+   * You need to set -quality 101 or greater.  If quality is 100 or less you
+   * get regular JPEG output.  This is not explained in the documentation, only
+   * in the comments in coder/jpeg.c.  When you have configured libjpeg with
+   * lossless support, then
+   * 
+   *    quality=predictor*100 + point_transform
+   * 
+   * If you don't know what these values should be, just use 101.
+   * They only affect the compression ratio, not the image appearance,
+   * which is lossless.
+   */
+  jpeg_simple_lossless (&cinfo, 1, 0);
   /* Now you can set any non-default parameters you wish to.
    * Here we just illustrate the use of quality (quantization table) scaling:
    */
@@ -143,25 +161,57 @@ bool gdcm_write_JPEG_file (std::ofstream *fp, void *im_buf,
    * To keep things simple, we pass one scanline per call; you can pass
    * more if you wish, though.
    */
-  row_stride = image_width * 3;/* JSAMPLEs per row in image_buffer */
+  if (sample_pixel == 3)
+    {
+    row_stride = image_width * 3;/* JSAMPLEs per row in image_buffer */
+    }
+  else
+    {
+    assert( sample_pixel == 1 );
+    row_stride = image_width * 1;/* JSAMPLEs per row in image_buffer */
+    }
+
+  (void)numZ;
+
+  uint8_t* input_buffer = (uint8_t*)inputdata;
+  //uint8_t *pbuffer = input_buffer;
+  //int i;
+  //for(i=0; i<numZ; ++i)
+//    {
+  JSAMPLE *image_buffer = (JSAMPLE*) input_buffer;
+  JSAMPROW row_pointer[1];   /* pointer to JSAMPLE row[s] */
+  row_pointer[0] = image_buffer;
 
   while (cinfo.next_scanline < cinfo.image_height) {
     /* jpeg_write_scanlines expects an array of pointers to scanlines.
      * Here the array is only one element long, but you could pass
      * more than one scanline at a time if that's more convenient.
      */
-    row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
+    //row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
 
-    (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
+    if( jpeg_write_scanlines(&cinfo, row_pointer, 1) != 1)
+      {
+      //entering suspension mode, basically we wrote the whole jpeg fragment
+      // technically we could enforce that by checkig the value of row_pointer to
+      // actually be at the end of the image...TODO
+      return false;
+      }
+    row_pointer[0] += row_stride;
   }
+//    pbuffer+=fragment_size; //shift to next image
+
+    //Upodate frag size
+//    size_t end = fp->tellp();
+//    std::cerr << "DIFF: " << end-beg << std::endl;
+
+//    JpegPair &jp = v[i];
+//    jp.second = end-beg;
+    //beg = end; //
+ //   }
 
   /* Step 6: Finish compression */
 
   jpeg_finish_compress(&cinfo);
-  
-  /* After finish_compress, we can close the output file. */
-  
- // fclose(fp); --> the caller will close (multiframe treatement)
 
   /* Step 7: release JPEG compression object */
 
@@ -170,11 +220,7 @@ bool gdcm_write_JPEG_file (std::ofstream *fp, void *im_buf,
 
   /* And we're done! */
 
-  return true; //???
-}
-
-extern "C" {
-  typedef void(*void_jpeg_common_struct)(jpeg_common_struct*);
+  return true;
 }
 
 //-----------------------------------------------------------------------------
@@ -188,6 +234,7 @@ typedef struct my_error_mgr* my_error_ptr;
 /*
  * Here's the routine that will replace the standard error_exit method:
  */
+extern "C" {
 METHODDEF(void) my_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;
@@ -200,9 +247,21 @@ METHODDEF(void) my_error_exit (j_common_ptr cinfo) {
    longjmp(myerr->setjmp_buffer, 1);
 }
 
+//METHODDEF(void) my_output_message (j_common_ptr cinfo)
+//{
+//   char buffer[JMSG_LENGTH_MAX];
+// 
+//   /* Create the message */
+//   (*cinfo->err->format_message) (cinfo, buffer);
+//
+//   // Custom display message, we could be more fancy and throw an exception:
+//   gdcmStaticErrorMacro( buffer );
+//}
+
+}
 //-----------------------------------------------------------------------------
  
- /**
+/**
  * \brief   routine for JPEG decompression 
  * @param fp pointer to an already open file descriptor 
  *                      8 significant bits per pixel
@@ -246,8 +305,11 @@ bool JPEGFragment::ReadJPEGFile (std::ifstream *fp, void *image_buffer, int &sta
   // We set up the normal JPEG error routines, then override error_exit.
   
   cinfo.err = jpeg_std_error(&jerr.pub);
-  jerr.pub.error_exit = reinterpret_cast<void_jpeg_common_struct>(my_error_exit);
-  
+  // for any jpeg error call my_error_exit
+  jerr.pub.error_exit = my_error_exit;
+  // for any output message call my_output_message
+  //jerr.pub.output_message = my_output_message;
+
   // Establish the setjmp return context for my_error_exit to use.
   if (setjmp(jerr.setjmp_buffer))
   {
@@ -259,7 +321,7 @@ bool JPEGFragment::ReadJPEGFile (std::ifstream *fp, void *image_buffer, int &sta
     return 0;
   }
   // Now we can initialize the JPEG decompression object.
-  if( statesuspension == 0 )
+  if ( statesuspension == 0 )
     {
     jpeg_create_decompress(&cinfo);
     jpeg_stdio_src(&cinfo, fp, this, 1);
@@ -270,17 +332,17 @@ bool JPEGFragment::ReadJPEGFile (std::ifstream *fp, void *image_buffer, int &sta
     }
    // Step 3: read file parameters with jpeg_read_header()
 
-   if( statesuspension < 2 )
+   if ( statesuspension < 2 )
    {
-      if( jpeg_read_header(&cinfo, TRUE) == JPEG_SUSPENDED )
+      if ( jpeg_read_header(&cinfo, TRUE) == JPEG_SUSPENDED )
       {
       // Suspension in jpeg_read_header
       statesuspension = 2; 
       }
-   
       // Step 4: set parameters for decompression
       // prevent the library from performing any color space conversion
-      if( cinfo.process == JPROC_LOSSLESS )
+      if ( cinfo.process == JPROC_LOSSLESS )
       {
          cinfo.jpeg_color_space = JCS_UNKNOWN;
          cinfo.out_color_space = JCS_UNKNOWN;
@@ -288,9 +350,9 @@ bool JPEGFragment::ReadJPEGFile (std::ifstream *fp, void *image_buffer, int &sta
    }
 
    // Step 5: Start decompressor
-   if(statesuspension < 3 )
+   if (statesuspension < 3 )
    {
-      if( jpeg_start_decompress(&cinfo) == FALSE )
+      if ( jpeg_start_decompress(&cinfo) == FALSE )
       {
          // Suspension: jpeg_start_decompress
          statesuspension = 3;
@@ -318,14 +380,14 @@ bool JPEGFragment::ReadJPEGFile (std::ifstream *fp, void *image_buffer, int &sta
 
    while (cinfo.output_scanline < cinfo.output_height)
    {
-      if( jpeg_read_scanlines(&cinfo, buffer, 1) == 0 )
+      if ( jpeg_read_scanlines(&cinfo, buffer, 1) == 0 )
         {
         // Suspension in jpeg_read_scanlines
         statesuspension = 3;
         return true;
         }
 // The ijg has no notion of big endian, therefore always swap the jpeg stream
-#if defined(GDCM_WORDS_BIGENDIAN) && (CMAKE_BITS_IN_JSAMPLE != 8)
+#if (defined(GDCM_WORDS_BIGENDIAN) || defined(GDCM_FORCE_BIGENDIAN_EMULATION)) && (CMAKE_BITS_IN_JSAMPLE != 8)
       uint16_t *buffer16 = (uint16_t*)*buffer;
       uint16_t *pimage16 = (uint16_t*)pImage;
       for(unsigned int i=0;i<rowsize/2;i++)
@@ -337,7 +399,7 @@ bool JPEGFragment::ReadJPEGFile (std::ifstream *fp, void *image_buffer, int &sta
    }
 
    // Step 7: Finish decompression
-   if( jpeg_finish_decompress(&cinfo) == FALSE )
+   if ( jpeg_finish_decompress(&cinfo) == FALSE )
      {
      // Suspension: jpeg_finish_decompress
      statesuspension = 4;