PTdecode/CImg-1.3.0/plugins/jpeg_buffer.h

Wed, 05 Aug 2009 15:00:54 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Wed, 05 Aug 2009 15:00:54 +0100
changeset 12
96e1df9bd27c
parent 5
1204ebf9340d
permissions
-rwxr-xr-x

small changes to hexdump code to stop a gcc warning on platforms where sizeof(int) != sizeof(int*) e.g. x86_64

     1 /*
     2  #
     3  #  File        : deprecated.h
     4  #                ( C++ header file - CImg plug-in )
     5  #
     6  #  Description : This CImg plug-in provide functions to load and save jpeg images
     7  #                directly from/to memory buffers of JOCTET buffers, using the
     8  #                JPEG library (required to compile !)
     9  #                This file is a part of the CImg Library project.
    10  #                ( http://cimg.sourceforge.net )
    11  #
    12  #  Copyright   : Paolo Prete
    13  #                ( p4olo_prete@yahoo.it )
    14  #
    15  #  License     : CeCILL v2.0
    16  #                ( http://www.cecill.info/licences/Licence_CeCILL_V2-en.html )
    17  #
    18  #  This software is governed by the CeCILL  license under French law and
    19  #  abiding by the rules of distribution of free software.  You can  use,
    20  #  modify and/ or redistribute the software under the terms of the CeCILL
    21  #  license as circulated by CEA, CNRS and INRIA at the following URL
    22  #  "http://www.cecill.info".
    23  #
    24  #  As a counterpart to the access to the source code and  rights to copy,
    25  #  modify and redistribute granted by the license, users are provided only
    26  #  with a limited warranty  and the software's author,  the holder of the
    27  #  economic rights,  and the successive licensors  have only  limited
    28  #  liability.
    29  #
    30  #  In this respect, the user's attention is drawn to the risks associated
    31  #  with loading,  using,  modifying and/or developing or reproducing the
    32  #  software by the user in light of its specific status of free software,
    33  #  that may mean  that it is complicated to manipulate,  and  that  also
    34  #  therefore means  that it is reserved for developers  and  experienced
    35  #  professionals having in-depth computer knowledge. Users are therefore
    36  #  encouraged to load and test the software's suitability as regards their
    37  #  requirements in conditions enabling the security of their systems and/or
    38  #  data to be ensured and,  more generally, to use and operate it in the
    39  #  same conditions as regards security.
    40  #
    41  #  The fact that you are presently reading this means that you have had
    42  #  knowledge of the CeCILL license and that you accept its terms.
    43  #
    44 */
    46 /*-----------------------------------------------------------------------------------
    48  IMPORTANT NOTE :
    50  You *need* to include the following two lines in your own code to use this plugin :
    52  #include <cstdio>
    53  #include <jpeglib.h>
    54  #include <jerror.h>
    56  (see example file provided in examples/jpeg_buffer.cpp).
    58 ------------------------------------------------------------------------------------*/
    60 ///////////////////////////////////////////////////////////////////////////////////////
    61 //
    62 //    extension of libjpeg (helper functions for loading images from JOCTET arrays)
    63 //                                      hacked from
    64 //      http://www.koders.com/cpp/fidB5A4549ABB5CB01824058F57A43D095D3F95AB40.aspx
    65 //
    66 ///////////////////////////////////////////////////////////////////////////////////////
    68 #define INPUT_BUF_SIZE 4096
    70 struct my_source_mem {
    71   struct jpeg_source_mgr pub; // Public fields
    72   int    indexinmem;
    73   JOCTET * inmem;             // Source stream
    74   JOCTET * buffer;            // Start of buffer
    75   int lenght;                 // Size of buffer in memory
    76   boolean start_of_file;      // Have we gotten any data yet?
    77 };
    79 struct my_source_mgr {
    80   struct jpeg_source_mgr pub; // public fields
    81   FILE * infile;              // source stream
    82   JOCTET * buffer;            // start of buffer
    83   boolean start_of_file;      // have we gotten any data yet?
    84 };
    86 typedef my_source_mem *my_src_mptr;
    87 typedef my_source_mgr *my_src_ptr;
    89 static boolean fill_minput_buffer(j_decompress_ptr cinfo) {
    90   my_src_mptr src = (my_src_mptr) cinfo->src;
    91   size_t nbytes;
    92   if (src->indexinmem+INPUT_BUF_SIZE>src->lenght) nbytes=src->lenght-src->indexinmem;
    93   else nbytes = INPUT_BUF_SIZE;
    94   std::memcpy(src->buffer,src->inmem,nbytes);
    95   src->inmem += nbytes;
    96   src->indexinmem += (int)nbytes;
    97   src->pub.next_input_byte = src->buffer;
    98   src->pub.bytes_in_buffer = INPUT_BUF_SIZE;
    99   src->start_of_file = FALSE;
   100   return TRUE;
   101 }
   103 static void skip_minput_data(j_decompress_ptr cinfo, long num_bytes) {
   104   my_src_ptr src = (my_src_ptr)cinfo->src;
   105   if (num_bytes > 0) {
   106     while (num_bytes > (long) src->pub.bytes_in_buffer) {
   107       num_bytes -= (long) src->pub.bytes_in_buffer;
   108       fill_minput_buffer(cinfo);
   109       // note we assume that fill_input_buffer will never return FALSE,
   110       // so suspension need not be handled.
   111       //
   112     }
   113     src->pub.next_input_byte += (size_t) num_bytes;
   114     src->pub.bytes_in_buffer -= (size_t) num_bytes;
   115   }
   116 }
   118 static void init_msource(j_decompress_ptr cinfo) {
   119   my_src_mptr src = (my_src_mptr)cinfo->src;
   120   src->start_of_file = TRUE;
   121 }
   123 static void term_source(j_decompress_ptr) {
   124   // no work necessary here
   125 }
   127 static void jpeg_mem_src(j_decompress_ptr cinfo, JOCTET * memptr,int lenght) {
   128   my_src_mptr src;
   130   // The source object and input buffer are made permanent so that a series
   131   //of JPEG images can be read from the same file by calling jpeg_stdio_src
   132   // only before the first one.  (If we discarded the buffer at the end of
   133   // one image, we'd likely lose the start of the next one.)
   134   // This makes it unsafe to use this manager and a different source
   135   // manager serially with the same JPEG object.  Caveat programmer.
   136   //
   138   // first time for this JPEG object?
   139   if (cinfo->src == NULL) {
   140     cinfo->src = (struct jpeg_source_mgr*)(*cinfo->mem->alloc_small)((j_common_ptr) cinfo, JPOOL_PERMANENT,sizeof(my_source_mem));
   141     src = (my_src_mptr) cinfo->src;
   142     src->buffer = (JOCTET *)(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,INPUT_BUF_SIZE * sizeof(JOCTET));
   143   }
   145   src = (my_src_mptr) cinfo->src;
   146   src->pub.init_source = init_msource;
   147   src->pub.fill_input_buffer = fill_minput_buffer;
   148   src->pub.skip_input_data = skip_minput_data;
   149   //src->pub.resync_to_restart = jpeg_resync_to_restart; // use default method
   150   src->pub.term_source = term_source;
   151   src->inmem = memptr;
   152   src->indexinmem = 0;
   153   src->lenght = lenght;
   154   src->pub.bytes_in_buffer = 0; // forces fill_input_buffer on first read
   155   src->pub.next_input_byte = NULL; // until buffer loaded
   156 }
   158 // The following declarations and 5 functions are jpeg related
   159 // functions used by put_jpeg_grey_memory and put_jpeg_yuv420p_memory
   160 //
   161 struct mem_destination_mgr {
   162   struct jpeg_destination_mgr pub;
   163   JOCTET *buf;
   164   size_t bufsize;
   165   size_t jpegsize;
   166 };
   168 typedef mem_destination_mgr *mem_dest_ptr;
   170 static void init_destination(j_compress_ptr cinfo) {
   171   mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest;
   172   dest->pub.next_output_byte = dest->buf;
   173   dest->pub.free_in_buffer = dest->bufsize;
   174   dest->jpegsize = 0;
   175 }
   177 static boolean empty_output_buffer(j_compress_ptr cinfo) {
   178   mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest;
   179   dest->pub.next_output_byte = dest->buf;
   180   dest->pub.free_in_buffer = dest->bufsize;
   181   return FALSE;
   182   ERREXIT(cinfo, JERR_BUFFER_SIZE);
   183 }
   185 static void term_destination(j_compress_ptr cinfo) {
   186   mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest;
   187   dest->jpegsize = dest->bufsize - dest->pub.free_in_buffer;
   188 }
   190 static void jpeg_mem_dest(j_compress_ptr cinfo, JOCTET* buf, size_t bufsize) {
   191   mem_dest_ptr dest;
   192   if (cinfo->dest == NULL) {
   193     cinfo->dest = (struct jpeg_destination_mgr *)
   194       (*cinfo->mem->alloc_small)((j_common_ptr)cinfo, JPOOL_PERMANENT,sizeof(mem_destination_mgr));
   195   }
   196   dest = (mem_dest_ptr) cinfo->dest;
   197   dest->pub.init_destination    = init_destination;
   198   dest->pub.empty_output_buffer = empty_output_buffer;
   199   dest->pub.term_destination    = term_destination;
   200   dest->buf      = buf;
   201   dest->bufsize  = bufsize;
   202   dest->jpegsize = 0;
   203 }
   205 static unsigned jpeg_mem_size(j_compress_ptr cinfo) {
   206   mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest;
   207   return dest->jpegsize;
   208 }
   210 /////////////////////////////////////////////////////////////////
   211 //
   212 //    Define main CImg plugin functions.
   213 //    (you should use these functions only in your own code)
   214 //
   215 /////////////////////////////////////////////////////////////////
   217 //! Load image from a jpeg-coded memory buffer.
   218 /**
   219    \param buffer Memory buffer containing the jpeg-coded image data.
   220    \param buffer_size Size of the memory buffer, in bytes.
   221 **/
   222 static CImg get_load_jpeg_buffer(const JOCTET *const buffer, const unsigned buffer_size) {
   223   struct jpeg_decompress_struct cinfo;
   224   struct jpeg_error_mgr jerr;
   225   cinfo.err = jpeg_std_error(&jerr);
   226   jpeg_create_decompress(&cinfo);
   227   jpeg_mem_src(&cinfo, const_cast<JOCTET*>(buffer), buffer_size);
   228   jpeg_read_header(&cinfo,TRUE);
   229   jpeg_start_decompress(&cinfo);
   231   const unsigned int row_stride = cinfo.output_width * cinfo.output_components;
   232   JOCTET *buf = new JOCTET[cinfo.output_width*cinfo.output_height*cinfo.output_components];
   233   const JOCTET *buf2 = buf;
   234   JSAMPROW row_pointer[1];
   235   while (cinfo.output_scanline < cinfo.output_height) {
   236     row_pointer[0] = buf + cinfo.output_scanline*row_stride;
   237     jpeg_read_scanlines(&cinfo,row_pointer,1);
   238   }
   239   jpeg_finish_decompress(&cinfo);
   240   jpeg_destroy_decompress(&cinfo);
   242   CImg<T> dest(cinfo.output_width,cinfo.output_height,1,cinfo.output_components);
   243   switch (dest.dim) {
   244   case 1: {
   245     T *ptr_g = dest.ptr(0,0,0,0);
   246     cimg_foroff(dest,off) *(ptr_g++) = (T)*(buf2++);
   247   } break;
   248   case 3: {
   249     T
   250       *ptr_r = dest.ptr(0,0,0,0),
   251       *ptr_g = dest.ptr(0,0,0,1),
   252       *ptr_b = dest.ptr(0,0,0,2);
   253     cimg_forXY(dest,x,y) {
   254       *(ptr_r++) = (T)*(buf2++);
   255       *(ptr_g++) = (T)*(buf2++);
   256       *(ptr_b++) = (T)*(buf2++);
   257     }
   258   } break;
   259   case 4: {
   260     T
   261       *ptr_r = dest.ptr(0,0,0,0),
   262       *ptr_g = dest.ptr(0,0,0,1),
   263       *ptr_b = dest.ptr(0,0,0,2),
   264       *ptr_a = dest.ptr(0,0,0,3);
   265     cimg_forXY(dest,x,y) {
   266       *(ptr_r++) = (T)*(buf2++);
   267       *(ptr_g++) = (T)*(buf2++);
   268       *(ptr_b++) = (T)*(buf2++);
   269       *(ptr_a++) = (T)*(buf2++);
   270     }
   271   } break;
   272   }
   273   delete[] buf;
   275   return dest;
   276 }
   278 //! Load image from a jpeg-coded memory buffer (in-place version)
   279 /**
   280    \param buffer Memory buffer containing the jpeg-coded image data.
   281    \param buffer_size Size of the memory buffer, in bytes.
   282 **/
   283 CImg& load_jpeg_buffer(const JOCTET *const buffer, const unsigned buffer_size) {
   284   return get_load_jpeg_buffer(buffer,buffer_size).transfer_to(*this);
   285 }
   287 //! Save image in a memory buffer, directly as a jpeg-coded file
   288 /**
   289    \param buffer Memory buffer that will be written with the jpeg-coded image data.
   290    \param buffer_size Initial size of the memory buffer. When the function returns, the variable
   291    contains the effective length needed to fill the buffer.
   292    \param quality Quality of the jpeg compression.
   293 **/
   294 const CImg& save_jpeg_buffer(JOCTET *const buffer, unsigned int &buffer_size, const int quality=100) const {
   296   // Fill pixel buffer
   297   JOCTET *buf;
   298   unsigned int dimbuf=0;
   299   J_COLOR_SPACE colortype=JCS_RGB;
   300   switch (dim) {
   301   case 1: {
   302     // Greyscale images
   303     JOCTET *buf2 = buf = new JOCTET[width*height*(dimbuf=1)];
   304     const T
   305       *ptr_g = ptr();
   306     colortype = JCS_GRAYSCALE;
   307     cimg_foroff(*this,off) *(buf2++) = (JOCTET)*(ptr_g++);
   308   } break;
   309   case 2:
   310   case 3: {
   311     // RGB images
   312     JOCTET *buf2 = buf = new JOCTET[width*height*(dimbuf=3)];
   313     const T
   314       *ptr_r = ptr(0,0,0,0),
   315       *ptr_g = ptr(0,0,0,1),
   316       *ptr_b = ptr(0,0,0,dim>2?2:0);
   317     colortype = JCS_RGB;
   318     cimg_forXY(*this,x,y) {
   319       *(buf2++) = (JOCTET)*(ptr_r++);
   320       *(buf2++) = (JOCTET)*(ptr_g++);
   321       *(buf2++) = (JOCTET)*(ptr_b++);
   322     }
   323   } break;
   324   default: {
   325     // YCMYK images
   326     JOCTET *buf2 = buf = new JOCTET[width*height*(dimbuf=4)];
   327     const T
   328       *ptr_r = ptr(0,0,0,0),
   329       *ptr_g = ptr(0,0,0,1),
   330       *ptr_b = ptr(0,0,0,2),
   331       *ptr_a = ptr(0,0,0,3);
   332     colortype = JCS_CMYK;
   333     cimg_forXY(*this,x,y) {
   334       *(buf2++) = (JOCTET)*(ptr_r++);
   335       *(buf2++) = (JOCTET)*(ptr_g++);
   336       *(buf2++) = (JOCTET)*(ptr_b++);
   337       *(buf2++) = (JOCTET)*(ptr_a++);
   338     }
   339   } break;
   340   }
   342   // Call libjpeg functions
   343   struct jpeg_compress_struct cinfo;
   344   struct jpeg_error_mgr jerr;
   345   cinfo.err = jpeg_std_error(&jerr);
   346   jpeg_create_compress(&cinfo);
   347   jpeg_mem_dest(&cinfo, buffer, buffer_size);
   348   cinfo.image_width = width;
   349   cinfo.image_height = height;
   350   cinfo.input_components = dimbuf;
   351   cinfo.in_color_space = colortype;
   352   jpeg_set_defaults(&cinfo);
   353   jpeg_set_quality(&cinfo,quality<100?quality:100,TRUE);
   354   jpeg_start_compress(&cinfo,TRUE);
   356   const unsigned int row_stride = width*dimbuf;
   357   JSAMPROW row_pointer[1];
   358   while (cinfo.next_scanline < cinfo.image_height) {
   359     row_pointer[0] = &buf[cinfo.next_scanline*row_stride];
   360     jpeg_write_scanlines(&cinfo,row_pointer,1);
   361   }
   362   jpeg_finish_compress(&cinfo);
   363   delete[] buf;
   364   jpeg_destroy_compress(&cinfo);
   365   buffer_size = jpeg_mem_size(&cinfo);
   366   return *this;
   367 }