PTdecode/CImg-1.3.0/plugins/jpeg_buffer.h

Wed, 05 Aug 2009 17:32:05 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Wed, 05 Aug 2009 17:32:05 +0100
changeset 18
fd1c6f6066da
parent 5
1204ebf9340d
permissions
-rwxr-xr-x

updated README

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