00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include "cxutils/images/jpeg/jpeg.h"
00042 #include "cxutils/packet.h"
00043 #include <stdio.h>
00044 #include <stdlib.h>
00045 #include <string.h>
00046 #include <assert.h>
00047
00048
00049
00050 extern "C"
00051 {
00052 #ifdef WIN32
00053 #include <jpeglib.h>
00054 #else
00055 #ifdef JPEG_TURBO_DIR
00056 #include JPEG_TURBO_DIR
00057 #else
00058 #include "linux/jpeglib.h"
00059 #endif
00060 #endif
00061 }
00062
00063 const unsigned int gJPEGHeaderSize = 20;
00064 unsigned char gJPEGHeader[gJPEGHeaderSize] =
00065 {
00066 0xff,0xd8,
00067 0xff,0xe0,
00068 0x00,0x10,
00069 0x4a,0x46,0x49,0x46,0x00,
00070 0x01,0x01,
00071 0x00,
00072 0x00, 0x00,
00073 0x00, 0x00,
00074 0x00,
00075 0x00
00076 };
00077
00078 const unsigned int gMJPGDHTSegSize = 420;
00079
00080 unsigned char gMJPGDHTSeg[gMJPGDHTSegSize] =
00081 {
00082
00083 0xFF,0xC4,0x01,0xA2,
00084 0x00,0x00,0x01,0x05,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
00085 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x01,0x00,0x03,0x01,0x01,0x01,0x01,
00086 0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
00087 0x08,0x09,0x0A,0x0B,0x10,0x00,0x02,0x01,0x03,0x03,0x02,0x04,0x03,0x05,0x05,0x04,0x04,0x00,
00088 0x00,0x01,0x7D,0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,
00089 0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xA1,0x08,0x23,0x42,0xB1,0xC1,0x15,0x52,0xD1,0xF0,0x24,
00090 0x33,0x62,0x72,0x82,0x09,0x0A,0x16,0x17,0x18,0x19,0x1A,0x25,0x26,0x27,0x28,0x29,0x2A,0x34,
00091 0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x53,0x54,0x55,0x56,
00092 0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x73,0x74,0x75,0x76,0x77,0x78,
00093 0x79,0x7A,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,
00094 0x9A,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,
00095 0xBA,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,
00096 0xDA,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,
00097 0xF8,0xF9,0xFA,0x11,0x00,0x02,0x01,0x02,0x04,0x04,0x03,0x04,0x07,0x05,0x04,0x04,0x00,0x01,
00098 0x02,0x77,0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,
00099 0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,0xA1,0xB1,0xC1,0x09,0x23,0x33,0x52,0xF0,0x15,0x62,
00100 0x72,0xD1,0x0A,0x16,0x24,0x34,0xE1,0x25,0xF1,0x17,0x18,0x19,0x1A,0x26,0x27,0x28,0x29,0x2A,
00101 0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x53,0x54,0x55,0x56,
00102 0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x73,0x74,0x75,0x76,0x77,0x78,
00103 0x79,0x7A,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,
00104 0x99,0x9A,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,
00105 0xB9,0xBA,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,
00106 0xD9,0xDA,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,
00107 0xF9,0xFA
00108 };
00109
00124 int CxUtils::JPEG::ConvertMJPEG2JPEG(const unsigned char* mjpeg,
00125 const unsigned int mjpegSize,
00126 unsigned char** jpeg,
00127 unsigned int* jpegSize)
00128 {
00129 if(mjpeg == NULL || mjpegSize == 0)
00130 {
00131 return 0;
00132 }
00133 int aviHeaderSize = *(mjpeg + 4);
00134 aviHeaderSize <<= 8;
00135 aviHeaderSize += *(mjpeg + 5) + 4;
00136 if(aviHeaderSize >= (int)mjpegSize)
00137 {
00138 return 0;
00139 }
00140 int outputSize = mjpegSize + gMJPGDHTSegSize + gJPEGHeaderSize - aviHeaderSize;
00141
00142 if(*jpeg != NULL)
00143 {
00144
00145 if(outputSize >= (int)*jpegSize)
00146 {
00147 delete[] *jpeg;
00148 *jpeg = new unsigned char[outputSize + 128];
00149 }
00150 }
00151 else
00152 {
00153 *jpeg = new unsigned char[outputSize + 128];
00154 }
00155
00156 memcpy(*jpeg, gJPEGHeader, gJPEGHeaderSize);
00157 memcpy(*jpeg + gJPEGHeaderSize, gMJPGDHTSeg, gMJPGDHTSegSize);
00158 memcpy(*jpeg + gMJPGDHTSegSize + gJPEGHeaderSize, mjpeg + aviHeaderSize, mjpegSize - aviHeaderSize);
00159 return 1;
00160 }
00161
00162 #include <setjmp.h>
00163
00164 #define JPEG_BUFFER_SIZE 4096
00165
00166 namespace CxUtils
00167 {
00168 namespace JPEG
00169 {
00176 struct InputSource
00177 {
00178 struct
00179 {
00180 struct jpeg_error_mgr mManager;
00181 jmp_buf mSetJumpBuffer;
00182 } mErrorManager;
00183
00184 unsigned char* mpImage;
00185 unsigned int mImageSize;
00186 unsigned int mNumBytesRead;
00187 unsigned char mpBuffer[JPEG_BUFFER_SIZE];
00188 };
00189
00190
00191 void InitSource(j_decompress_ptr cinfo)
00192 {
00193 #ifdef JCS_EXTENSIONS
00194 cinfo->out_color_space = JCS_EXT_BGR;
00195 #endif
00196 }
00197
00198
00199
00200
00201 boolean FillInputBuffer(j_decompress_ptr cinfo)
00202 {
00203 struct InputSource* input = (struct InputSource*)cinfo->client_data;
00204
00205 if(input->mImageSize <= 0)
00206 {
00207
00208 input->mpBuffer[0] = (JOCTET)0xFF;
00209 input->mpBuffer[1] = (JOCTET)JPEG_EOI;
00210 cinfo->src->bytes_in_buffer = 2;
00211 }
00212 if((unsigned int)(input->mImageSize - input->mNumBytesRead) < (unsigned int)JPEG_BUFFER_SIZE)
00213 {
00214 memcpy(input->mpBuffer, &input->mpImage[input->mNumBytesRead], input->mImageSize - input->mNumBytesRead);
00215 cinfo->src->bytes_in_buffer = input->mImageSize - input->mNumBytesRead;
00216 }
00217 else
00218 {
00219 memcpy(input->mpBuffer, &input->mpImage[input->mNumBytesRead], JPEG_BUFFER_SIZE);
00220 input->mNumBytesRead += JPEG_BUFFER_SIZE;
00221 cinfo->src->bytes_in_buffer = JPEG_BUFFER_SIZE;
00222 }
00223 cinfo->src->next_input_byte = input->mpBuffer;
00224 return TRUE;
00225 }
00226
00227
00228 void SkipInputData(j_decompress_ptr cinfo, long num_bytes)
00229 {
00230 if(num_bytes > 0)
00231 {
00232 while(num_bytes > (long)cinfo->src->bytes_in_buffer)
00233 {
00234 num_bytes -= (long)cinfo->src->bytes_in_buffer;
00235 FillInputBuffer(cinfo);
00236 }
00237 cinfo->src->next_input_byte += (size_t)num_bytes;
00238 cinfo->src->bytes_in_buffer -= (size_t)num_bytes;
00239 }
00240 }
00241
00242
00243 void TerminateSource(j_decompress_ptr cinfo)
00244 {
00245 }
00246
00247
00248
00249 void ErrorExit(j_common_ptr cinfo)
00250 {
00251 struct InputSource* inputSource = (struct InputSource*)(cinfo->client_data);
00252 longjmp(inputSource->mErrorManager.mSetJumpBuffer, 1);
00253 }
00254 }
00255 }
00256
00274 int CxUtils::JPEG::DecompressImage(const unsigned char* jpeg,
00275 const unsigned int jpegSize,
00276 unsigned char** image,
00277 unsigned short* width,
00278 unsigned short* height,
00279 unsigned char* channels)
00280 {
00281 int result = 0;
00282
00283 *width = *height = *channels = 0;
00284
00285
00286 struct InputSource inputSource;
00287 inputSource.mpImage = (unsigned char*)jpeg;
00288 inputSource.mImageSize = jpegSize;
00289 inputSource.mNumBytesRead = 0;
00290
00291
00292 jpeg_source_mgr mgr;
00293 mgr.bytes_in_buffer = 0;
00294 mgr.next_input_byte = NULL;
00295 mgr.init_source = InitSource;
00296 mgr.fill_input_buffer = FillInputBuffer;
00297 mgr.skip_input_data = SkipInputData;
00298 mgr.resync_to_restart = jpeg_resync_to_restart;
00299 mgr.term_source = TerminateSource;
00300
00301
00302 struct jpeg_decompress_struct cinfo;
00303
00304
00305 jpeg_create_decompress(&cinfo);
00306
00307
00308 cinfo.client_data = &inputSource;
00309
00310 cinfo.err = jpeg_std_error(&inputSource.mErrorManager.mManager);
00311 inputSource.mErrorManager.mManager.error_exit = ErrorExit;
00312
00313
00314 if(setjmp(inputSource.mErrorManager.mSetJumpBuffer))
00315 {
00316 jpeg_destroy_decompress(&cinfo);
00317 return result;
00318 }
00319
00320
00321 cinfo.src = &mgr;
00322
00323
00324 jpeg_read_header(&cinfo, TRUE);
00325
00326 #ifdef JCS_EXTENSIONS
00327 cinfo.out_color_space = JCS_EXT_BGR;
00328
00329 #endif
00330
00331
00332
00333 jpeg_start_decompress(&cinfo);
00334
00335
00336
00337 if(cinfo.output_components != 1 && cinfo.output_components != 3)
00338 {
00339 jpeg_finish_decompress(&cinfo);
00340 jpeg_destroy_decompress(&cinfo);
00341 return result;
00342 }
00343
00344
00345 #ifdef JCS_EXTENSIONS
00346 if (cinfo.out_color_space == JCS_RGB || cinfo.out_color_space == JCS_EXT_BGR)
00347 *channels = (unsigned char)3;
00348 #else
00349 if (cinfo.out_color_space == JCS_RGB)
00350 *channels = (unsigned char)3;
00351 #endif
00352 else if (cinfo.out_color_space == JCS_GRAYSCALE)
00353 *channels = (unsigned char)1;
00354 else
00355 {
00356 jpeg_finish_decompress(&cinfo);
00357 jpeg_destroy_decompress(&cinfo);
00358 return result;
00359 }
00360
00361
00362
00363 int row_stride = cinfo.output_width * cinfo.output_components;
00364 JSAMPARRAY buffer = NULL;
00365 buffer = (*cinfo.mem->alloc_sarray)
00366 ((j_common_ptr) &cinfo,
00367 JPOOL_IMAGE,
00368 row_stride,
00369 1);
00370
00371
00372 unsigned int outputSize;
00373 outputSize = cinfo.output_components*cinfo.output_width*cinfo.output_height;
00374
00375
00376 if(*image != NULL)
00377 {
00378
00379 if(outputSize >= (unsigned int)(*width)*(*height)*(*channels))
00380 {
00381 delete[] *image;
00382 *image = new unsigned char[outputSize + 100];
00383 }
00384 }
00385 else
00386 {
00387 *image = new unsigned char[outputSize + 100];
00388 }
00389
00390 *width = (unsigned short)cinfo.output_width;
00391 *height = (unsigned short)cinfo.output_height;
00392 *channels = (unsigned char)cinfo.output_components;
00393
00394 unsigned char* ptr = *image;
00395 int linesRead = 0;
00396
00397 while (cinfo.output_scanline < cinfo.output_height)
00398 {
00399 linesRead += (int)jpeg_read_scanlines(&cinfo, buffer, 1);
00400
00401 memcpy(ptr, buffer[0], row_stride);
00402 ptr += row_stride;
00403 }
00404
00405 if(linesRead != (int)cinfo.output_height)
00406 {
00407 return result;
00408 }
00409
00410 (void) jpeg_finish_decompress(&cinfo);
00411 jpeg_destroy_decompress(&cinfo);
00412
00413 result = 1;
00414
00415 return result;
00416 }
00417
00418 namespace CxUtils
00419 {
00420 namespace JPEG
00421 {
00422
00429 struct OutputSource
00430 {
00431 struct jpeg_destination_mgr mDestinationManager;
00432 unsigned char mOutputBuffer[JPEG_BUFFER_SIZE];
00433 unsigned char* mpCompressedJPEG;
00434 unsigned int mCompressionBufferSize;
00435 unsigned int mNumBytesCompressed;
00436 };
00437
00438
00439 void InitDestination (j_compress_ptr cinfo)
00440 {
00441 struct OutputSource *dest = (struct OutputSource *) cinfo->dest;
00442 dest->mDestinationManager.next_output_byte = dest->mOutputBuffer;
00443 dest->mDestinationManager.free_in_buffer = JPEG_BUFFER_SIZE;
00444 }
00445
00446
00447
00448 boolean EmptyOutputBuffer (j_compress_ptr cinfo)
00449 {
00450 struct OutputSource *dest = (struct OutputSource *) cinfo->dest;
00451
00452
00453 if(dest->mpCompressedJPEG == NULL || dest->mNumBytesCompressed + JPEG_BUFFER_SIZE >= dest->mCompressionBufferSize)
00454 {
00455 unsigned char *tempOutput = new unsigned char[dest->mCompressionBufferSize + JPEG_BUFFER_SIZE*2];
00456 if(dest->mpCompressedJPEG)
00457 {
00458 memcpy(tempOutput, dest->mpCompressedJPEG, dest->mCompressionBufferSize);
00459 delete[] dest->mpCompressedJPEG;
00460 }
00461 dest->mpCompressedJPEG = tempOutput;
00462 dest->mCompressionBufferSize += JPEG_BUFFER_SIZE*2;
00463 }
00464 memcpy(&dest->mpCompressedJPEG[dest->mNumBytesCompressed], dest->mOutputBuffer, JPEG_BUFFER_SIZE);
00465 dest->mNumBytesCompressed += JPEG_BUFFER_SIZE;
00466 dest->mDestinationManager.next_output_byte = dest->mOutputBuffer;
00467 dest->mDestinationManager.free_in_buffer = JPEG_BUFFER_SIZE;
00468
00469 return TRUE;
00470 }
00471
00472
00473
00474 void TerminateDestination(j_compress_ptr cinfo)
00475 {
00476 OutputSource *dest = (OutputSource *) cinfo->dest;
00477 unsigned int datacount = (unsigned int)(JPEG_BUFFER_SIZE - dest->mDestinationManager.free_in_buffer);
00478
00479
00480
00481 if(dest->mpCompressedJPEG == NULL || dest->mNumBytesCompressed + datacount >= dest->mCompressionBufferSize)
00482 {
00483 unsigned char *tempOutput = new unsigned char[dest->mCompressionBufferSize + datacount];
00484 if(dest->mpCompressedJPEG)
00485 {
00486 memcpy(tempOutput, dest->mpCompressedJPEG, dest->mCompressionBufferSize);
00487 delete[] dest->mpCompressedJPEG;
00488 }
00489 dest->mpCompressedJPEG = tempOutput;
00490 dest->mCompressionBufferSize += datacount;
00491 }
00492
00493 memcpy(&dest->mpCompressedJPEG[dest->mNumBytesCompressed], dest->mOutputBuffer, datacount);
00494 dest->mNumBytesCompressed += datacount;
00495 dest->mDestinationManager.next_output_byte = dest->mOutputBuffer;
00496 dest->mDestinationManager.free_in_buffer = JPEG_BUFFER_SIZE;
00497 }
00498 }
00499 }
00500
00501
00523 int CxUtils::JPEG::CompressImage(const unsigned short width,
00524 const unsigned short height,
00525 const unsigned char channels,
00526 const unsigned char* image,
00527 unsigned char** jpeg,
00528 unsigned int* jpegBufferSize,
00529 unsigned int* jpegSize,
00530 const int quality)
00531 {
00532 int result = 0;
00533
00534 if(width > 0 &&
00535 height > 0 &&
00536 (channels == 1 || channels == 3) &&
00537 image != 0 &&
00538 jpeg != 0)
00539 {
00540 unsigned int imageSize = width*height*channels*sizeof(unsigned char);
00541
00542 *jpegSize = 0;
00543
00544
00545
00546 if(*jpeg == NULL || jpegBufferSize == 0)
00547 {
00548 if(*jpeg)
00549 {
00550 delete[] *jpeg;
00551 *jpeg = 0;
00552 }
00553 *jpeg = new unsigned char[imageSize];
00554 assert( *jpeg );
00555 *jpegBufferSize = imageSize;
00556 }
00557
00558
00559 struct jpeg_compress_struct cinfo;
00560 struct jpeg_error_mgr jerr;
00561
00562
00563 jpeg_create_compress(&cinfo);
00564
00565 cinfo.err = jpeg_std_error(&jerr);
00566
00567 OutputSource dest;
00568
00569
00570 dest.mpCompressedJPEG = *jpeg;
00571 dest.mCompressionBufferSize = *jpegBufferSize;
00572 dest.mNumBytesCompressed = 0;
00573 dest.mDestinationManager.init_destination = InitDestination;
00574 dest.mDestinationManager.empty_output_buffer = EmptyOutputBuffer;
00575 dest.mDestinationManager.term_destination = TerminateDestination;
00576
00577 cinfo.dest = (struct jpeg_destination_mgr *)&dest;
00578
00579 cinfo.image_width = width;
00580 cinfo.image_height = height;
00581 cinfo.input_components = channels;
00582 #ifdef JCS_EXTENSIONS
00583 cinfo.in_color_space = channels > 1 ? JCS_EXT_BGR : JCS_GRAYSCALE;
00584 #else
00585 cinfo.in_color_space = channels > 1 ? JCS_RGB : JCS_GRAYSCALE;
00586 #endif
00587
00588
00589
00590 jpeg_set_defaults(&cinfo);
00591
00592
00593 if(quality >= 0)
00594 {
00595 jpeg_set_quality(&cinfo, quality, TRUE);
00596 }
00597
00598
00599 jpeg_start_compress(&cinfo, TRUE);
00600
00601 JSAMPROW row_pointer[1];
00602 int row_stride;
00603 row_stride = width*channels;
00604
00605 while (cinfo.next_scanline < cinfo.image_height)
00606 {
00607
00608
00609
00610 row_pointer[0] = & ((unsigned char *)(image)) [cinfo.next_scanline * row_stride];
00611 (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
00612
00613 }
00614
00615
00616 jpeg_finish_compress(&cinfo);
00617
00618
00619 *jpegSize = dest.mNumBytesCompressed;
00620 *jpegBufferSize = dest.mCompressionBufferSize;
00621 *jpeg = dest.mpCompressedJPEG;
00622
00623
00624 jpeg_destroy_compress(&cinfo);
00625
00626 result = 1;
00627 }
00628
00629 return result;
00630 }
00631
00632
00633 namespace CxUtils
00634 {
00635 namespace JPEG
00636 {
00637 Compressor::Compressor() : mpCompressionObject(0)
00638 {
00639 }
00640 Compressor::~Compressor()
00641 {
00642 if(mpCompressionObject)
00643 {
00644 jpeg_destroy_compress((j_compress_ptr)(mpCompressionObject));
00645 delete ((jpeg_compress_struct *)(mpCompressionObject));
00646 }
00647 mpCompressionObject = 0;
00648 }
00649
00670 int Compressor::CompressImage(const unsigned short width,
00671 const unsigned short height,
00672 const unsigned char channels,
00673 const unsigned char* image,
00674 unsigned char** jpeg,
00675 unsigned int* jpegBufferSize,
00676 unsigned int* jpegSize,
00677 const int quality)
00678 {
00679 int result = 0;
00680
00681 if(width > 0 &&
00682 height > 0 &&
00683 (channels == 1 || channels == 3) &&
00684 image != 0 &&
00685 jpeg != 0)
00686 {
00687 unsigned int imageSize = width*height*channels*sizeof(unsigned char);
00688
00689 *jpegSize = 0;
00690
00691
00692
00693 if(*jpeg == NULL || jpegBufferSize == 0)
00694 {
00695 if(*jpeg)
00696 {
00697 delete[] *jpeg;
00698 *jpeg = 0;
00699 }
00700 *jpeg = new unsigned char[imageSize];
00701 assert( *jpeg );
00702 *jpegBufferSize = imageSize;
00703 }
00704
00705
00706 if(mpCompressionObject == 0)
00707 {
00708 mpCompressionObject = (void *)(new jpeg_compress_struct);
00709
00710 jpeg_create_compress((j_compress_ptr)(mpCompressionObject));
00711 }
00712 j_compress_ptr cinfo = (j_compress_ptr)(mpCompressionObject);
00713 struct jpeg_error_mgr jerr;
00714
00715
00716 cinfo->err = jpeg_std_error(&jerr);
00717
00718 OutputSource dest;
00719
00720
00721 dest.mpCompressedJPEG = *jpeg;
00722 dest.mCompressionBufferSize = *jpegBufferSize;
00723 dest.mNumBytesCompressed = 0;
00724 dest.mDestinationManager.init_destination = InitDestination;
00725 dest.mDestinationManager.empty_output_buffer = EmptyOutputBuffer;
00726 dest.mDestinationManager.term_destination = TerminateDestination;
00727
00728 cinfo->dest = (struct jpeg_destination_mgr *)&dest;
00729
00730 cinfo->image_width = width;
00731 cinfo->image_height = height;
00732 cinfo->input_components = channels;
00733 #ifdef JCS_EXTENSIONS
00734 cinfo->in_color_space = channels > 1 ? JCS_EXT_BGR : JCS_GRAYSCALE;
00735 #else
00736 cinfo->in_color_space = channels > 1 ? JCS_RGB : JCS_GRAYSCALE;
00737 #endif
00738
00739
00740 jpeg_set_defaults(cinfo);
00741
00742
00743 if(quality >= 0)
00744 {
00745 jpeg_set_quality(cinfo, quality, TRUE);
00746 }
00747
00748
00749 jpeg_start_compress(cinfo, TRUE);
00750
00751 JSAMPROW row_pointer[1];
00752 int row_stride;
00753 row_stride = width*channels;
00754
00755 while (cinfo->next_scanline < cinfo->image_height)
00756 {
00757
00758
00759
00760 row_pointer[0] = & ((unsigned char *)(image)) [cinfo->next_scanline * row_stride];
00761 (void) jpeg_write_scanlines(cinfo, row_pointer, 1);
00762
00763 }
00764
00765
00766 jpeg_finish_compress(cinfo);
00767
00768
00769 *jpegSize = dest.mNumBytesCompressed;
00770 *jpegBufferSize = dest.mCompressionBufferSize;
00771 *jpeg = dest.mpCompressedJPEG;
00772
00773 result = 1;
00774 }
00775
00776 return result;
00777 }
00778
00799 int Compressor::CompressImageNoResize(const unsigned short width,
00800 const unsigned short height,
00801 const unsigned char channels,
00802 const unsigned char* image,
00803 unsigned char* jpeg,
00804 unsigned int jpegBufferSize,
00805 unsigned int* jpegSize,
00806 const int quality)
00807 {
00808 int result = 0;
00809
00810 if(width > 0 &&
00811 height > 0 &&
00812 (channels == 1 || channels == 3) &&
00813 image != 0 &&
00814 jpeg != 0)
00815 {
00816 unsigned int imageSize = width*height*channels*sizeof(unsigned char);
00817
00818 *jpegSize = 0;
00819
00820
00821
00822 if(jpeg == NULL || jpegBufferSize < imageSize)
00823 {
00824 return 0;
00825 }
00826
00827
00828 if(mpCompressionObject == 0)
00829 {
00830 mpCompressionObject = (void *)(new jpeg_compress_struct);
00831
00832 jpeg_create_compress((j_compress_ptr)(mpCompressionObject));
00833 }
00834 j_compress_ptr cinfo = (j_compress_ptr)(mpCompressionObject);
00835 struct jpeg_error_mgr jerr;
00836
00837
00838 cinfo->err = jpeg_std_error(&jerr);
00839
00840 OutputSource dest;
00841
00842
00843 dest.mpCompressedJPEG = jpeg;
00844 dest.mCompressionBufferSize = jpegBufferSize;
00845 dest.mNumBytesCompressed = 0;
00846 dest.mDestinationManager.init_destination = InitDestination;
00847 dest.mDestinationManager.empty_output_buffer = EmptyOutputBuffer;
00848 dest.mDestinationManager.term_destination = TerminateDestination;
00849
00850 cinfo->dest = (struct jpeg_destination_mgr *)&dest;
00851
00852 cinfo->image_width = width;
00853 cinfo->image_height = height;
00854 cinfo->input_components = channels;
00855 #ifdef JCS_EXTENSIONS
00856 cinfo->in_color_space = channels > 1 ? JCS_EXT_BGR : JCS_GRAYSCALE;
00857 #else
00858 cinfo->in_color_space = channels > 1 ? JCS_RGB : JCS_GRAYSCALE;
00859 #endif
00860
00861
00862 jpeg_set_defaults(cinfo);
00863
00864
00865 if(quality >= 0)
00866 {
00867 jpeg_set_quality(cinfo, quality, TRUE);
00868 }
00869
00870
00871 jpeg_start_compress(cinfo, TRUE);
00872
00873 JSAMPROW row_pointer[1];
00874 int row_stride;
00875 row_stride = width*channels;
00876
00877 while (cinfo->next_scanline < cinfo->image_height)
00878 {
00879
00880
00881
00882 row_pointer[0] = & ((unsigned char *)(image)) [cinfo->next_scanline * row_stride];
00883 (void) jpeg_write_scanlines(cinfo, row_pointer, 1);
00884
00885 }
00886
00887
00888 jpeg_finish_compress(cinfo);
00889
00890
00891 *jpegSize = dest.mNumBytesCompressed;
00892
00893 result = 1;
00894 }
00895
00896 return result;
00897 }
00898 }
00899 }
00900
00901
00902