PTdecode/CImg-1.3.0/plugins/jpeg_buffer.h

changeset 5
1204ebf9340d
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/PTdecode/CImg-1.3.0/plugins/jpeg_buffer.h	Mon Aug 03 14:09:20 2009 +0100
     1.3 @@ -0,0 +1,367 @@
     1.4 +/*
     1.5 + #
     1.6 + #  File        : deprecated.h
     1.7 + #                ( C++ header file - CImg plug-in )
     1.8 + #
     1.9 + #  Description : This CImg plug-in provide functions to load and save jpeg images
    1.10 + #                directly from/to memory buffers of JOCTET buffers, using the
    1.11 + #                JPEG library (required to compile !)
    1.12 + #                This file is a part of the CImg Library project.
    1.13 + #                ( http://cimg.sourceforge.net )
    1.14 + #
    1.15 + #  Copyright   : Paolo Prete
    1.16 + #                ( p4olo_prete@yahoo.it )
    1.17 + #
    1.18 + #  License     : CeCILL v2.0
    1.19 + #                ( http://www.cecill.info/licences/Licence_CeCILL_V2-en.html )
    1.20 + #
    1.21 + #  This software is governed by the CeCILL  license under French law and
    1.22 + #  abiding by the rules of distribution of free software.  You can  use,
    1.23 + #  modify and/ or redistribute the software under the terms of the CeCILL
    1.24 + #  license as circulated by CEA, CNRS and INRIA at the following URL
    1.25 + #  "http://www.cecill.info".
    1.26 + #
    1.27 + #  As a counterpart to the access to the source code and  rights to copy,
    1.28 + #  modify and redistribute granted by the license, users are provided only
    1.29 + #  with a limited warranty  and the software's author,  the holder of the
    1.30 + #  economic rights,  and the successive licensors  have only  limited
    1.31 + #  liability.
    1.32 + #
    1.33 + #  In this respect, the user's attention is drawn to the risks associated
    1.34 + #  with loading,  using,  modifying and/or developing or reproducing the
    1.35 + #  software by the user in light of its specific status of free software,
    1.36 + #  that may mean  that it is complicated to manipulate,  and  that  also
    1.37 + #  therefore means  that it is reserved for developers  and  experienced
    1.38 + #  professionals having in-depth computer knowledge. Users are therefore
    1.39 + #  encouraged to load and test the software's suitability as regards their
    1.40 + #  requirements in conditions enabling the security of their systems and/or
    1.41 + #  data to be ensured and,  more generally, to use and operate it in the
    1.42 + #  same conditions as regards security.
    1.43 + #
    1.44 + #  The fact that you are presently reading this means that you have had
    1.45 + #  knowledge of the CeCILL license and that you accept its terms.
    1.46 + #
    1.47 +*/
    1.48 +
    1.49 +/*-----------------------------------------------------------------------------------
    1.50 +
    1.51 + IMPORTANT NOTE :
    1.52 +
    1.53 + You *need* to include the following two lines in your own code to use this plugin :
    1.54 +
    1.55 + #include <cstdio>
    1.56 + #include <jpeglib.h>
    1.57 + #include <jerror.h>
    1.58 +
    1.59 + (see example file provided in examples/jpeg_buffer.cpp).
    1.60 +
    1.61 +------------------------------------------------------------------------------------*/
    1.62 +
    1.63 +///////////////////////////////////////////////////////////////////////////////////////
    1.64 +//
    1.65 +//    extension of libjpeg (helper functions for loading images from JOCTET arrays)
    1.66 +//                                      hacked from
    1.67 +//      http://www.koders.com/cpp/fidB5A4549ABB5CB01824058F57A43D095D3F95AB40.aspx
    1.68 +//
    1.69 +///////////////////////////////////////////////////////////////////////////////////////
    1.70 +
    1.71 +#define INPUT_BUF_SIZE 4096
    1.72 +
    1.73 +struct my_source_mem {
    1.74 +  struct jpeg_source_mgr pub; // Public fields
    1.75 +  int    indexinmem;
    1.76 +  JOCTET * inmem;             // Source stream
    1.77 +  JOCTET * buffer;            // Start of buffer
    1.78 +  int lenght;                 // Size of buffer in memory
    1.79 +  boolean start_of_file;      // Have we gotten any data yet?
    1.80 +};
    1.81 +
    1.82 +struct my_source_mgr {
    1.83 +  struct jpeg_source_mgr pub; // public fields
    1.84 +  FILE * infile;              // source stream
    1.85 +  JOCTET * buffer;            // start of buffer
    1.86 +  boolean start_of_file;      // have we gotten any data yet?
    1.87 +};
    1.88 +
    1.89 +typedef my_source_mem *my_src_mptr;
    1.90 +typedef my_source_mgr *my_src_ptr;
    1.91 +
    1.92 +static boolean fill_minput_buffer(j_decompress_ptr cinfo) {
    1.93 +  my_src_mptr src = (my_src_mptr) cinfo->src;
    1.94 +  size_t nbytes;
    1.95 +  if (src->indexinmem+INPUT_BUF_SIZE>src->lenght) nbytes=src->lenght-src->indexinmem;
    1.96 +  else nbytes = INPUT_BUF_SIZE;
    1.97 +  std::memcpy(src->buffer,src->inmem,nbytes);
    1.98 +  src->inmem += nbytes;
    1.99 +  src->indexinmem += (int)nbytes;
   1.100 +  src->pub.next_input_byte = src->buffer;
   1.101 +  src->pub.bytes_in_buffer = INPUT_BUF_SIZE;
   1.102 +  src->start_of_file = FALSE;
   1.103 +  return TRUE;
   1.104 +}
   1.105 +
   1.106 +static void skip_minput_data(j_decompress_ptr cinfo, long num_bytes) {
   1.107 +  my_src_ptr src = (my_src_ptr)cinfo->src;
   1.108 +  if (num_bytes > 0) {
   1.109 +    while (num_bytes > (long) src->pub.bytes_in_buffer) {
   1.110 +      num_bytes -= (long) src->pub.bytes_in_buffer;
   1.111 +      fill_minput_buffer(cinfo);
   1.112 +      // note we assume that fill_input_buffer will never return FALSE,
   1.113 +      // so suspension need not be handled.
   1.114 +      //
   1.115 +    }
   1.116 +    src->pub.next_input_byte += (size_t) num_bytes;
   1.117 +    src->pub.bytes_in_buffer -= (size_t) num_bytes;
   1.118 +  }
   1.119 +}
   1.120 +
   1.121 +static void init_msource(j_decompress_ptr cinfo) {
   1.122 +  my_src_mptr src = (my_src_mptr)cinfo->src;
   1.123 +  src->start_of_file = TRUE;
   1.124 +}
   1.125 +
   1.126 +static void term_source(j_decompress_ptr) {
   1.127 +  // no work necessary here
   1.128 +}
   1.129 +
   1.130 +static void jpeg_mem_src(j_decompress_ptr cinfo, JOCTET * memptr,int lenght) {
   1.131 +  my_src_mptr src;
   1.132 +
   1.133 +  // The source object and input buffer are made permanent so that a series
   1.134 +  //of JPEG images can be read from the same file by calling jpeg_stdio_src
   1.135 +  // only before the first one.  (If we discarded the buffer at the end of
   1.136 +  // one image, we'd likely lose the start of the next one.)
   1.137 +  // This makes it unsafe to use this manager and a different source
   1.138 +  // manager serially with the same JPEG object.  Caveat programmer.
   1.139 +  //
   1.140 +
   1.141 +  // first time for this JPEG object?
   1.142 +  if (cinfo->src == NULL) {
   1.143 +    cinfo->src = (struct jpeg_source_mgr*)(*cinfo->mem->alloc_small)((j_common_ptr) cinfo, JPOOL_PERMANENT,sizeof(my_source_mem));
   1.144 +    src = (my_src_mptr) cinfo->src;
   1.145 +    src->buffer = (JOCTET *)(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,INPUT_BUF_SIZE * sizeof(JOCTET));
   1.146 +  }
   1.147 +
   1.148 +  src = (my_src_mptr) cinfo->src;
   1.149 +  src->pub.init_source = init_msource;
   1.150 +  src->pub.fill_input_buffer = fill_minput_buffer;
   1.151 +  src->pub.skip_input_data = skip_minput_data;
   1.152 +  //src->pub.resync_to_restart = jpeg_resync_to_restart; // use default method
   1.153 +  src->pub.term_source = term_source;
   1.154 +  src->inmem = memptr;
   1.155 +  src->indexinmem = 0;
   1.156 +  src->lenght = lenght;
   1.157 +  src->pub.bytes_in_buffer = 0; // forces fill_input_buffer on first read
   1.158 +  src->pub.next_input_byte = NULL; // until buffer loaded
   1.159 +}
   1.160 +
   1.161 +// The following declarations and 5 functions are jpeg related
   1.162 +// functions used by put_jpeg_grey_memory and put_jpeg_yuv420p_memory
   1.163 +//
   1.164 +struct mem_destination_mgr {
   1.165 +  struct jpeg_destination_mgr pub;
   1.166 +  JOCTET *buf;
   1.167 +  size_t bufsize;
   1.168 +  size_t jpegsize;
   1.169 +};
   1.170 +
   1.171 +typedef mem_destination_mgr *mem_dest_ptr;
   1.172 +
   1.173 +static void init_destination(j_compress_ptr cinfo) {
   1.174 +  mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest;
   1.175 +  dest->pub.next_output_byte = dest->buf;
   1.176 +  dest->pub.free_in_buffer = dest->bufsize;
   1.177 +  dest->jpegsize = 0;
   1.178 +}
   1.179 +
   1.180 +static boolean empty_output_buffer(j_compress_ptr cinfo) {
   1.181 +  mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest;
   1.182 +  dest->pub.next_output_byte = dest->buf;
   1.183 +  dest->pub.free_in_buffer = dest->bufsize;
   1.184 +  return FALSE;
   1.185 +  ERREXIT(cinfo, JERR_BUFFER_SIZE);
   1.186 +}
   1.187 +
   1.188 +static void term_destination(j_compress_ptr cinfo) {
   1.189 +  mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest;
   1.190 +  dest->jpegsize = dest->bufsize - dest->pub.free_in_buffer;
   1.191 +}
   1.192 +
   1.193 +static void jpeg_mem_dest(j_compress_ptr cinfo, JOCTET* buf, size_t bufsize) {
   1.194 +  mem_dest_ptr dest;
   1.195 +  if (cinfo->dest == NULL) {
   1.196 +    cinfo->dest = (struct jpeg_destination_mgr *)
   1.197 +      (*cinfo->mem->alloc_small)((j_common_ptr)cinfo, JPOOL_PERMANENT,sizeof(mem_destination_mgr));
   1.198 +  }
   1.199 +  dest = (mem_dest_ptr) cinfo->dest;
   1.200 +  dest->pub.init_destination    = init_destination;
   1.201 +  dest->pub.empty_output_buffer = empty_output_buffer;
   1.202 +  dest->pub.term_destination    = term_destination;
   1.203 +  dest->buf      = buf;
   1.204 +  dest->bufsize  = bufsize;
   1.205 +  dest->jpegsize = 0;
   1.206 +}
   1.207 +
   1.208 +static unsigned jpeg_mem_size(j_compress_ptr cinfo) {
   1.209 +  mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest;
   1.210 +  return dest->jpegsize;
   1.211 +}
   1.212 +
   1.213 +/////////////////////////////////////////////////////////////////
   1.214 +//
   1.215 +//    Define main CImg plugin functions.
   1.216 +//    (you should use these functions only in your own code)
   1.217 +//
   1.218 +/////////////////////////////////////////////////////////////////
   1.219 +
   1.220 +//! Load image from a jpeg-coded memory buffer.
   1.221 +/**
   1.222 +   \param buffer Memory buffer containing the jpeg-coded image data.
   1.223 +   \param buffer_size Size of the memory buffer, in bytes.
   1.224 +**/
   1.225 +static CImg get_load_jpeg_buffer(const JOCTET *const buffer, const unsigned buffer_size) {
   1.226 +  struct jpeg_decompress_struct cinfo;
   1.227 +  struct jpeg_error_mgr jerr;
   1.228 +  cinfo.err = jpeg_std_error(&jerr);
   1.229 +  jpeg_create_decompress(&cinfo);
   1.230 +  jpeg_mem_src(&cinfo, const_cast<JOCTET*>(buffer), buffer_size);
   1.231 +  jpeg_read_header(&cinfo,TRUE);
   1.232 +  jpeg_start_decompress(&cinfo);
   1.233 +
   1.234 +  const unsigned int row_stride = cinfo.output_width * cinfo.output_components;
   1.235 +  JOCTET *buf = new JOCTET[cinfo.output_width*cinfo.output_height*cinfo.output_components];
   1.236 +  const JOCTET *buf2 = buf;
   1.237 +  JSAMPROW row_pointer[1];
   1.238 +  while (cinfo.output_scanline < cinfo.output_height) {
   1.239 +    row_pointer[0] = buf + cinfo.output_scanline*row_stride;
   1.240 +    jpeg_read_scanlines(&cinfo,row_pointer,1);
   1.241 +  }
   1.242 +  jpeg_finish_decompress(&cinfo);
   1.243 +  jpeg_destroy_decompress(&cinfo);
   1.244 +
   1.245 +  CImg<T> dest(cinfo.output_width,cinfo.output_height,1,cinfo.output_components);
   1.246 +  switch (dest.dim) {
   1.247 +  case 1: {
   1.248 +    T *ptr_g = dest.ptr(0,0,0,0);
   1.249 +    cimg_foroff(dest,off) *(ptr_g++) = (T)*(buf2++);
   1.250 +  } break;
   1.251 +  case 3: {
   1.252 +    T
   1.253 +      *ptr_r = dest.ptr(0,0,0,0),
   1.254 +      *ptr_g = dest.ptr(0,0,0,1),
   1.255 +      *ptr_b = dest.ptr(0,0,0,2);
   1.256 +    cimg_forXY(dest,x,y) {
   1.257 +      *(ptr_r++) = (T)*(buf2++);
   1.258 +      *(ptr_g++) = (T)*(buf2++);
   1.259 +      *(ptr_b++) = (T)*(buf2++);
   1.260 +    }
   1.261 +  } break;
   1.262 +  case 4: {
   1.263 +    T
   1.264 +      *ptr_r = dest.ptr(0,0,0,0),
   1.265 +      *ptr_g = dest.ptr(0,0,0,1),
   1.266 +      *ptr_b = dest.ptr(0,0,0,2),
   1.267 +      *ptr_a = dest.ptr(0,0,0,3);
   1.268 +    cimg_forXY(dest,x,y) {
   1.269 +      *(ptr_r++) = (T)*(buf2++);
   1.270 +      *(ptr_g++) = (T)*(buf2++);
   1.271 +      *(ptr_b++) = (T)*(buf2++);
   1.272 +      *(ptr_a++) = (T)*(buf2++);
   1.273 +    }
   1.274 +  } break;
   1.275 +  }
   1.276 +  delete[] buf;
   1.277 +
   1.278 +  return dest;
   1.279 +}
   1.280 +
   1.281 +//! Load image from a jpeg-coded memory buffer (in-place version)
   1.282 +/**
   1.283 +   \param buffer Memory buffer containing the jpeg-coded image data.
   1.284 +   \param buffer_size Size of the memory buffer, in bytes.
   1.285 +**/
   1.286 +CImg& load_jpeg_buffer(const JOCTET *const buffer, const unsigned buffer_size) {
   1.287 +  return get_load_jpeg_buffer(buffer,buffer_size).transfer_to(*this);
   1.288 +}
   1.289 +
   1.290 +//! Save image in a memory buffer, directly as a jpeg-coded file
   1.291 +/**
   1.292 +   \param buffer Memory buffer that will be written with the jpeg-coded image data.
   1.293 +   \param buffer_size Initial size of the memory buffer. When the function returns, the variable
   1.294 +   contains the effective length needed to fill the buffer.
   1.295 +   \param quality Quality of the jpeg compression.
   1.296 +**/
   1.297 +const CImg& save_jpeg_buffer(JOCTET *const buffer, unsigned int &buffer_size, const int quality=100) const {
   1.298 +
   1.299 +  // Fill pixel buffer
   1.300 +  JOCTET *buf;
   1.301 +  unsigned int dimbuf=0;
   1.302 +  J_COLOR_SPACE colortype=JCS_RGB;
   1.303 +  switch (dim) {
   1.304 +  case 1: {
   1.305 +    // Greyscale images
   1.306 +    JOCTET *buf2 = buf = new JOCTET[width*height*(dimbuf=1)];
   1.307 +    const T
   1.308 +      *ptr_g = ptr();
   1.309 +    colortype = JCS_GRAYSCALE;
   1.310 +    cimg_foroff(*this,off) *(buf2++) = (JOCTET)*(ptr_g++);
   1.311 +  } break;
   1.312 +  case 2:
   1.313 +  case 3: {
   1.314 +    // RGB images
   1.315 +    JOCTET *buf2 = buf = new JOCTET[width*height*(dimbuf=3)];
   1.316 +    const T
   1.317 +      *ptr_r = ptr(0,0,0,0),
   1.318 +      *ptr_g = ptr(0,0,0,1),
   1.319 +      *ptr_b = ptr(0,0,0,dim>2?2:0);
   1.320 +    colortype = JCS_RGB;
   1.321 +    cimg_forXY(*this,x,y) {
   1.322 +      *(buf2++) = (JOCTET)*(ptr_r++);
   1.323 +      *(buf2++) = (JOCTET)*(ptr_g++);
   1.324 +      *(buf2++) = (JOCTET)*(ptr_b++);
   1.325 +    }
   1.326 +  } break;
   1.327 +  default: {
   1.328 +    // YCMYK images
   1.329 +    JOCTET *buf2 = buf = new JOCTET[width*height*(dimbuf=4)];
   1.330 +    const T
   1.331 +      *ptr_r = ptr(0,0,0,0),
   1.332 +      *ptr_g = ptr(0,0,0,1),
   1.333 +      *ptr_b = ptr(0,0,0,2),
   1.334 +      *ptr_a = ptr(0,0,0,3);
   1.335 +    colortype = JCS_CMYK;
   1.336 +    cimg_forXY(*this,x,y) {
   1.337 +      *(buf2++) = (JOCTET)*(ptr_r++);
   1.338 +      *(buf2++) = (JOCTET)*(ptr_g++);
   1.339 +      *(buf2++) = (JOCTET)*(ptr_b++);
   1.340 +      *(buf2++) = (JOCTET)*(ptr_a++);
   1.341 +    }
   1.342 +  } break;
   1.343 +  }
   1.344 +
   1.345 +  // Call libjpeg functions
   1.346 +  struct jpeg_compress_struct cinfo;
   1.347 +  struct jpeg_error_mgr jerr;
   1.348 +  cinfo.err = jpeg_std_error(&jerr);
   1.349 +  jpeg_create_compress(&cinfo);
   1.350 +  jpeg_mem_dest(&cinfo, buffer, buffer_size);
   1.351 +  cinfo.image_width = width;
   1.352 +  cinfo.image_height = height;
   1.353 +  cinfo.input_components = dimbuf;
   1.354 +  cinfo.in_color_space = colortype;
   1.355 +  jpeg_set_defaults(&cinfo);
   1.356 +  jpeg_set_quality(&cinfo,quality<100?quality:100,TRUE);
   1.357 +  jpeg_start_compress(&cinfo,TRUE);
   1.358 +
   1.359 +  const unsigned int row_stride = width*dimbuf;
   1.360 +  JSAMPROW row_pointer[1];
   1.361 +  while (cinfo.next_scanline < cinfo.image_height) {
   1.362 +    row_pointer[0] = &buf[cinfo.next_scanline*row_stride];
   1.363 +    jpeg_write_scanlines(&cinfo,row_pointer,1);
   1.364 +  }
   1.365 +  jpeg_finish_compress(&cinfo);
   1.366 +  delete[] buf;
   1.367 +  jpeg_destroy_compress(&cinfo);
   1.368 +  buffer_size = jpeg_mem_size(&cinfo);
   1.369 +  return *this;
   1.370 +}