/indra/llimage/llimagejpeg.cpp

https://bitbucket.org/lindenlab/viewer-beta/ · C++ · 648 lines · 306 code · 115 blank · 227 comment · 29 complexity · 15d5052df5ad3ec22e0b982500e96681 MD5 · raw file

  1. /**
  2. * @file llimagejpeg.cpp
  3. *
  4. * $LicenseInfo:firstyear=2002&license=viewerlgpl$
  5. * Second Life Viewer Source Code
  6. * Copyright (C) 2010, Linden Research, Inc.
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License as published by the Free Software Foundation;
  11. * version 2.1 of the License only.
  12. *
  13. * This library is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with this library; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21. *
  22. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  23. * $/LicenseInfo$
  24. */
  25. #include "linden_common.h"
  26. #include "stdtypes.h"
  27. #include "llimagejpeg.h"
  28. #include "llerror.h"
  29. jmp_buf LLImageJPEG::sSetjmpBuffer ;
  30. LLImageJPEG::LLImageJPEG(S32 quality)
  31. :
  32. LLImageFormatted(IMG_CODEC_JPEG),
  33. mOutputBuffer( NULL ),
  34. mOutputBufferSize( 0 ),
  35. mEncodeQuality( quality ) // on a scale from 1 to 100
  36. {
  37. }
  38. LLImageJPEG::~LLImageJPEG()
  39. {
  40. llassert( !mOutputBuffer ); // Should already be deleted at end of encode.
  41. delete[] mOutputBuffer;
  42. }
  43. BOOL LLImageJPEG::updateData()
  44. {
  45. resetLastError();
  46. // Check to make sure that this instance has been initialized with data
  47. if (!getData() || (0 == getDataSize()))
  48. {
  49. setLastError("Uninitialized instance of LLImageJPEG");
  50. return FALSE;
  51. }
  52. ////////////////////////////////////////
  53. // Step 1: allocate and initialize JPEG decompression object
  54. // This struct contains the JPEG decompression parameters and pointers to
  55. // working space (which is allocated as needed by the JPEG library).
  56. struct jpeg_decompress_struct cinfo;
  57. cinfo.client_data = this;
  58. struct jpeg_error_mgr jerr;
  59. cinfo.err = jpeg_std_error(&jerr);
  60. // Customize with our own callbacks
  61. jerr.error_exit = &LLImageJPEG::errorExit; // Error exit handler: does not return to caller
  62. jerr.emit_message = &LLImageJPEG::errorEmitMessage; // Conditionally emit a trace or warning message
  63. jerr.output_message = &LLImageJPEG::errorOutputMessage; // Routine that actually outputs a trace or error message
  64. //
  65. //try/catch will crash on Mac and Linux if LLImageJPEG::errorExit throws an error
  66. //so as instead, we use setjmp/longjmp to avoid this crash, which is the best we can get. --bao
  67. //
  68. if(setjmp(sSetjmpBuffer))
  69. {
  70. jpeg_destroy_decompress(&cinfo);
  71. return FALSE;
  72. }
  73. try
  74. {
  75. // Now we can initialize the JPEG decompression object.
  76. jpeg_create_decompress(&cinfo);
  77. ////////////////////////////////////////
  78. // Step 2: specify data source
  79. // (Code is modified version of jpeg_stdio_src();
  80. if (cinfo.src == NULL)
  81. {
  82. cinfo.src = (struct jpeg_source_mgr *)
  83. (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT,
  84. sizeof(struct jpeg_source_mgr));
  85. }
  86. cinfo.src->init_source = &LLImageJPEG::decodeInitSource;
  87. cinfo.src->fill_input_buffer = &LLImageJPEG::decodeFillInputBuffer;
  88. cinfo.src->skip_input_data = &LLImageJPEG::decodeSkipInputData;
  89. cinfo.src->resync_to_restart = jpeg_resync_to_restart; // For now, use default method, but we should be able to do better.
  90. cinfo.src->term_source = &LLImageJPEG::decodeTermSource;
  91. cinfo.src->bytes_in_buffer = getDataSize();
  92. cinfo.src->next_input_byte = getData();
  93. ////////////////////////////////////////
  94. // Step 3: read file parameters with jpeg_read_header()
  95. jpeg_read_header( &cinfo, TRUE );
  96. // Data set by jpeg_read_header
  97. setSize(cinfo.image_width, cinfo.image_height, 3); // Force to 3 components (RGB)
  98. /*
  99. // More data set by jpeg_read_header
  100. cinfo.num_components;
  101. cinfo.jpeg_color_space; // Colorspace of image
  102. cinfo.saw_JFIF_marker; // TRUE if a JFIF APP0 marker was seen
  103. cinfo.JFIF_major_version; // Version information from JFIF marker
  104. cinfo.JFIF_minor_version; //
  105. cinfo.density_unit; // Resolution data from JFIF marker
  106. cinfo.X_density;
  107. cinfo.Y_density;
  108. cinfo.saw_Adobe_marker; // TRUE if an Adobe APP14 marker was seen
  109. cinfo.Adobe_transform; // Color transform code from Adobe marker
  110. */
  111. }
  112. catch (int)
  113. {
  114. jpeg_destroy_decompress(&cinfo);
  115. return FALSE;
  116. }
  117. ////////////////////////////////////////
  118. // Step 4: Release JPEG decompression object
  119. jpeg_destroy_decompress(&cinfo);
  120. return TRUE;
  121. }
  122. // Initialize source --- called by jpeg_read_header
  123. // before any data is actually read.
  124. void LLImageJPEG::decodeInitSource( j_decompress_ptr cinfo )
  125. {
  126. // no work necessary here
  127. }
  128. // Fill the input buffer --- called whenever buffer is emptied.
  129. boolean LLImageJPEG::decodeFillInputBuffer( j_decompress_ptr cinfo )
  130. {
  131. // jpeg_source_mgr* src = cinfo->src;
  132. // LLImageJPEG* self = (LLImageJPEG*) cinfo->client_data;
  133. // Should never get here, since we provide the entire buffer up front.
  134. ERREXIT(cinfo, JERR_INPUT_EMPTY);
  135. return TRUE;
  136. }
  137. // Skip data --- used to skip over a potentially large amount of
  138. // uninteresting data (such as an APPn marker).
  139. //
  140. // Writers of suspendable-input applications must note that skip_input_data
  141. // is not granted the right to give a suspension return. If the skip extends
  142. // beyond the data currently in the buffer, the buffer can be marked empty so
  143. // that the next read will cause a fill_input_buffer call that can suspend.
  144. // Arranging for additional bytes to be discarded before reloading the input
  145. // buffer is the application writer's problem.
  146. void LLImageJPEG::decodeSkipInputData (j_decompress_ptr cinfo, long num_bytes)
  147. {
  148. jpeg_source_mgr* src = cinfo->src;
  149. // LLImageJPEG* self = (LLImageJPEG*) cinfo->client_data;
  150. src->next_input_byte += (size_t) num_bytes;
  151. src->bytes_in_buffer -= (size_t) num_bytes;
  152. }
  153. void LLImageJPEG::decodeTermSource (j_decompress_ptr cinfo)
  154. {
  155. // no work necessary here
  156. }
  157. // Returns true when done, whether or not decode was successful.
  158. BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time)
  159. {
  160. llassert_always(raw_image);
  161. resetLastError();
  162. // Check to make sure that this instance has been initialized with data
  163. if (!getData() || (0 == getDataSize()))
  164. {
  165. setLastError("LLImageJPEG trying to decode an image with no data!");
  166. return TRUE; // done
  167. }
  168. S32 row_stride = 0;
  169. U8* raw_image_data = NULL;
  170. ////////////////////////////////////////
  171. // Step 1: allocate and initialize JPEG decompression object
  172. // This struct contains the JPEG decompression parameters and pointers to
  173. // working space (which is allocated as needed by the JPEG library).
  174. struct jpeg_decompress_struct cinfo;
  175. struct jpeg_error_mgr jerr;
  176. cinfo.err = jpeg_std_error(&jerr);
  177. // Customize with our own callbacks
  178. jerr.error_exit = &LLImageJPEG::errorExit; // Error exit handler: does not return to caller
  179. jerr.emit_message = &LLImageJPEG::errorEmitMessage; // Conditionally emit a trace or warning message
  180. jerr.output_message = &LLImageJPEG::errorOutputMessage; // Routine that actually outputs a trace or error message
  181. //
  182. //try/catch will crash on Mac and Linux if LLImageJPEG::errorExit throws an error
  183. //so as instead, we use setjmp/longjmp to avoid this crash, which is the best we can get. --bao
  184. //
  185. if(setjmp(sSetjmpBuffer))
  186. {
  187. jpeg_destroy_decompress(&cinfo);
  188. return TRUE; // done
  189. }
  190. try
  191. {
  192. // Now we can initialize the JPEG decompression object.
  193. jpeg_create_decompress(&cinfo);
  194. ////////////////////////////////////////
  195. // Step 2: specify data source
  196. // (Code is modified version of jpeg_stdio_src();
  197. if (cinfo.src == NULL)
  198. {
  199. cinfo.src = (struct jpeg_source_mgr *)
  200. (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT,
  201. sizeof(struct jpeg_source_mgr));
  202. }
  203. cinfo.src->init_source = &LLImageJPEG::decodeInitSource;
  204. cinfo.src->fill_input_buffer = &LLImageJPEG::decodeFillInputBuffer;
  205. cinfo.src->skip_input_data = &LLImageJPEG::decodeSkipInputData;
  206. cinfo.src->resync_to_restart = jpeg_resync_to_restart; // For now, use default method, but we should be able to do better.
  207. cinfo.src->term_source = &LLImageJPEG::decodeTermSource;
  208. cinfo.src->bytes_in_buffer = getDataSize();
  209. cinfo.src->next_input_byte = getData();
  210. ////////////////////////////////////////
  211. // Step 3: read file parameters with jpeg_read_header()
  212. jpeg_read_header(&cinfo, TRUE);
  213. // We can ignore the return value from jpeg_read_header since
  214. // (a) suspension is not possible with our data source, and
  215. // (b) we passed TRUE to reject a tables-only JPEG file as an error.
  216. // See libjpeg.doc for more info.
  217. setSize(cinfo.image_width, cinfo.image_height, 3); // Force to 3 components (RGB)
  218. raw_image->resize(getWidth(), getHeight(), getComponents());
  219. raw_image_data = raw_image->getData();
  220. ////////////////////////////////////////
  221. // Step 4: set parameters for decompression
  222. cinfo.out_color_components = 3;
  223. cinfo.out_color_space = JCS_RGB;
  224. ////////////////////////////////////////
  225. // Step 5: Start decompressor
  226. jpeg_start_decompress(&cinfo);
  227. // We can ignore the return value since suspension is not possible
  228. // with our data source.
  229. // We may need to do some setup of our own at this point before reading
  230. // the data. After jpeg_start_decompress() we have the correct scaled
  231. // output image dimensions available, as well as the output colormap
  232. // if we asked for color quantization.
  233. // In this example, we need to make an output work buffer of the right size.
  234. // JSAMPLEs per row in output buffer
  235. row_stride = cinfo.output_width * cinfo.output_components;
  236. ////////////////////////////////////////
  237. // Step 6: while (scan lines remain to be read)
  238. // jpeg_read_scanlines(...);
  239. // Here we use the library's state variable cinfo.output_scanline as the
  240. // loop counter, so that we don't have to keep track ourselves.
  241. // Move pointer to last line
  242. raw_image_data += row_stride * (cinfo.output_height - 1);
  243. while (cinfo.output_scanline < cinfo.output_height)
  244. {
  245. // jpeg_read_scanlines expects an array of pointers to scanlines.
  246. // Here the array is only one element long, but you could ask for
  247. // more than one scanline at a time if that's more convenient.
  248. jpeg_read_scanlines(&cinfo, &raw_image_data, 1);
  249. raw_image_data -= row_stride; // move pointer up a line
  250. }
  251. ////////////////////////////////////////
  252. // Step 7: Finish decompression
  253. jpeg_finish_decompress(&cinfo);
  254. ////////////////////////////////////////
  255. // Step 8: Release JPEG decompression object
  256. jpeg_destroy_decompress(&cinfo);
  257. }
  258. catch (int)
  259. {
  260. jpeg_destroy_decompress(&cinfo);
  261. return TRUE; // done
  262. }
  263. // Check to see whether any corrupt-data warnings occurred
  264. if( jerr.num_warnings != 0 )
  265. {
  266. // TODO: extract the warning to find out what went wrong.
  267. setLastError( "Unable to decode JPEG image.");
  268. return TRUE; // done
  269. }
  270. return TRUE;
  271. }
  272. // Initialize destination --- called by jpeg_start_compress before any data is actually written.
  273. // static
  274. void LLImageJPEG::encodeInitDestination ( j_compress_ptr cinfo )
  275. {
  276. LLImageJPEG* self = (LLImageJPEG*) cinfo->client_data;
  277. cinfo->dest->next_output_byte = self->mOutputBuffer;
  278. cinfo->dest->free_in_buffer = self->mOutputBufferSize;
  279. }
  280. // Empty the output buffer --- called whenever buffer fills up.
  281. //
  282. // In typical applications, this should write the entire output buffer
  283. // (ignoring the current state of next_output_byte & free_in_buffer),
  284. // reset the pointer & count to the start of the buffer, and return TRUE
  285. // indicating that the buffer has been dumped.
  286. //
  287. // In applications that need to be able to suspend compression due to output
  288. // overrun, a FALSE return indicates that the buffer cannot be emptied now.
  289. // In this situation, the compressor will return to its caller (possibly with
  290. // an indication that it has not accepted all the supplied scanlines). The
  291. // application should resume compression after it has made more room in the
  292. // output buffer. Note that there are substantial restrictions on the use of
  293. // suspension --- see the documentation.
  294. //
  295. // When suspending, the compressor will back up to a convenient restart point
  296. // (typically the start of the current MCU). next_output_byte & free_in_buffer
  297. // indicate where the restart point will be if the current call returns FALSE.
  298. // Data beyond this point will be regenerated after resumption, so do not
  299. // write it out when emptying the buffer externally.
  300. boolean LLImageJPEG::encodeEmptyOutputBuffer( j_compress_ptr cinfo )
  301. {
  302. LLImageJPEG* self = (LLImageJPEG*) cinfo->client_data;
  303. // Should very rarely happen, since our output buffer is
  304. // as large as the input to start out with.
  305. // Double the buffer size;
  306. S32 new_buffer_size = self->mOutputBufferSize * 2;
  307. U8* new_buffer = new U8[ new_buffer_size ];
  308. if (!new_buffer)
  309. {
  310. llerrs << "Out of memory in LLImageJPEG::encodeEmptyOutputBuffer( j_compress_ptr cinfo )" << llendl;
  311. return FALSE;
  312. }
  313. memcpy( new_buffer, self->mOutputBuffer, self->mOutputBufferSize ); /* Flawfinder: ignore */
  314. delete[] self->mOutputBuffer;
  315. self->mOutputBuffer = new_buffer;
  316. cinfo->dest->next_output_byte = self->mOutputBuffer + self->mOutputBufferSize;
  317. cinfo->dest->free_in_buffer = self->mOutputBufferSize;
  318. self->mOutputBufferSize = new_buffer_size;
  319. return TRUE;
  320. }
  321. // Terminate destination --- called by jpeg_finish_compress
  322. // after all data has been written. Usually needs to flush buffer.
  323. //
  324. // NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
  325. // application must deal with any cleanup that should happen even
  326. // for error exit.
  327. void LLImageJPEG::encodeTermDestination( j_compress_ptr cinfo )
  328. {
  329. LLImageJPEG* self = (LLImageJPEG*) cinfo->client_data;
  330. S32 file_bytes = (S32)(self->mOutputBufferSize - cinfo->dest->free_in_buffer);
  331. self->allocateData(file_bytes);
  332. memcpy( self->getData(), self->mOutputBuffer, file_bytes ); /* Flawfinder: ignore */
  333. }
  334. // static
  335. void LLImageJPEG::errorExit( j_common_ptr cinfo )
  336. {
  337. //LLImageJPEG* self = (LLImageJPEG*) cinfo->client_data;
  338. // Always display the message
  339. (*cinfo->err->output_message)(cinfo);
  340. // Let the memory manager delete any temp files
  341. jpeg_destroy(cinfo);
  342. // Return control to the setjmp point
  343. longjmp(sSetjmpBuffer, 1) ;
  344. }
  345. // Decide whether to emit a trace or warning message.
  346. // msg_level is one of:
  347. // -1: recoverable corrupt-data warning, may want to abort.
  348. // 0: important advisory messages (always display to user).
  349. // 1: first level of tracing detail.
  350. // 2,3,...: successively more detailed tracing messages.
  351. // An application might override this method if it wanted to abort on warnings
  352. // or change the policy about which messages to display.
  353. // static
  354. void LLImageJPEG::errorEmitMessage( j_common_ptr cinfo, int msg_level )
  355. {
  356. struct jpeg_error_mgr * err = cinfo->err;
  357. if (msg_level < 0)
  358. {
  359. // It's a warning message. Since corrupt files may generate many warnings,
  360. // the policy implemented here is to show only the first warning,
  361. // unless trace_level >= 3.
  362. if (err->num_warnings == 0 || err->trace_level >= 3)
  363. {
  364. (*err->output_message) (cinfo);
  365. }
  366. // Always count warnings in num_warnings.
  367. err->num_warnings++;
  368. }
  369. else
  370. {
  371. // It's a trace message. Show it if trace_level >= msg_level.
  372. if (err->trace_level >= msg_level)
  373. {
  374. (*err->output_message) (cinfo);
  375. }
  376. }
  377. }
  378. // static
  379. void LLImageJPEG::errorOutputMessage( j_common_ptr cinfo )
  380. {
  381. // Create the message
  382. char buffer[JMSG_LENGTH_MAX]; /* Flawfinder: ignore */
  383. (*cinfo->err->format_message) (cinfo, buffer);
  384. std::string error = buffer ;
  385. LLImage::setLastError(error);
  386. BOOL is_decode = (cinfo->is_decompressor != 0);
  387. llwarns << "LLImageJPEG " << (is_decode ? "decode " : "encode ") << " failed: " << buffer << llendl;
  388. }
  389. BOOL LLImageJPEG::encode( const LLImageRaw* raw_image, F32 encode_time )
  390. {
  391. llassert_always(raw_image);
  392. resetLastError();
  393. switch( raw_image->getComponents() )
  394. {
  395. case 1:
  396. case 3:
  397. break;
  398. default:
  399. setLastError("Unable to encode a JPEG image that doesn't have 1 or 3 components.");
  400. return FALSE;
  401. }
  402. setSize(raw_image->getWidth(), raw_image->getHeight(), raw_image->getComponents());
  403. // Allocate a temporary buffer big enough to hold the entire compressed image (and then some)
  404. // (Note: we make it bigger in emptyOutputBuffer() if we need to)
  405. delete[] mOutputBuffer;
  406. mOutputBufferSize = getWidth() * getHeight() * getComponents() + 1024;
  407. mOutputBuffer = new U8[ mOutputBufferSize ];
  408. const U8* raw_image_data = NULL;
  409. S32 row_stride = 0;
  410. ////////////////////////////////////////
  411. // Step 1: allocate and initialize JPEG compression object
  412. // This struct contains the JPEG compression parameters and pointers to
  413. // working space (which is allocated as needed by the JPEG library).
  414. struct jpeg_compress_struct cinfo;
  415. cinfo.client_data = this;
  416. // We have to set up the error handler first, in case the initialization
  417. // step fails. (Unlikely, but it could happen if you are out of memory.)
  418. // This routine fills in the contents of struct jerr, and returns jerr's
  419. // address which we place into the link field in cinfo.
  420. struct jpeg_error_mgr jerr;
  421. cinfo.err = jpeg_std_error(&jerr);
  422. // Customize with our own callbacks
  423. jerr.error_exit = &LLImageJPEG::errorExit; // Error exit handler: does not return to caller
  424. jerr.emit_message = &LLImageJPEG::errorEmitMessage; // Conditionally emit a trace or warning message
  425. jerr.output_message = &LLImageJPEG::errorOutputMessage; // Routine that actually outputs a trace or error message
  426. //
  427. //try/catch will crash on Mac and Linux if LLImageJPEG::errorExit throws an error
  428. //so as instead, we use setjmp/longjmp to avoid this crash, which is the best we can get. --bao
  429. //
  430. if( setjmp(sSetjmpBuffer) )
  431. {
  432. // If we get here, the JPEG code has signaled an error.
  433. // We need to clean up the JPEG object, close the input file, and return.
  434. jpeg_destroy_compress(&cinfo);
  435. delete[] mOutputBuffer;
  436. mOutputBuffer = NULL;
  437. mOutputBufferSize = 0;
  438. return FALSE;
  439. }
  440. try
  441. {
  442. // Now we can initialize the JPEG compression object.
  443. jpeg_create_compress(&cinfo);
  444. ////////////////////////////////////////
  445. // Step 2: specify data destination
  446. // (code is a modified form of jpeg_stdio_dest() )
  447. if( cinfo.dest == NULL)
  448. {
  449. cinfo.dest = (struct jpeg_destination_mgr *)
  450. (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT,
  451. sizeof(struct jpeg_destination_mgr));
  452. }
  453. cinfo.dest->next_output_byte = mOutputBuffer; // => next byte to write in buffer
  454. cinfo.dest->free_in_buffer = mOutputBufferSize; // # of byte spaces remaining in buffer
  455. cinfo.dest->init_destination = &LLImageJPEG::encodeInitDestination;
  456. cinfo.dest->empty_output_buffer = &LLImageJPEG::encodeEmptyOutputBuffer;
  457. cinfo.dest->term_destination = &LLImageJPEG::encodeTermDestination;
  458. ////////////////////////////////////////
  459. // Step 3: set parameters for compression
  460. //
  461. // First we supply a description of the input image.
  462. // Four fields of the cinfo struct must be filled in:
  463. cinfo.image_width = getWidth(); // image width and height, in pixels
  464. cinfo.image_height = getHeight();
  465. switch( getComponents() )
  466. {
  467. case 1:
  468. cinfo.input_components = 1; // # of color components per pixel
  469. cinfo.in_color_space = JCS_GRAYSCALE; // colorspace of input image
  470. break;
  471. case 3:
  472. cinfo.input_components = 3; // # of color components per pixel
  473. cinfo.in_color_space = JCS_RGB; // colorspace of input image
  474. break;
  475. default:
  476. setLastError("Unable to encode a JPEG image that doesn't have 1 or 3 components.");
  477. return FALSE;
  478. }
  479. // Now use the library's routine to set default compression parameters.
  480. // (You must set at least cinfo.in_color_space before calling this,
  481. // since the defaults depend on the source color space.)
  482. jpeg_set_defaults(&cinfo);
  483. // Now you can set any non-default parameters you wish to.
  484. jpeg_set_quality(&cinfo, mEncodeQuality, TRUE ); // limit to baseline-JPEG values
  485. ////////////////////////////////////////
  486. // Step 4: Start compressor
  487. //
  488. // TRUE ensures that we will write a complete interchange-JPEG file.
  489. // Pass TRUE unless you are very sure of what you're doing.
  490. jpeg_start_compress(&cinfo, TRUE);
  491. ////////////////////////////////////////
  492. // Step 5: while (scan lines remain to be written)
  493. // jpeg_write_scanlines(...);
  494. // Here we use the library's state variable cinfo.next_scanline as the
  495. // loop counter, so that we don't have to keep track ourselves.
  496. // To keep things simple, we pass one scanline per call; you can pass
  497. // more if you wish, though.
  498. row_stride = getWidth() * getComponents(); // JSAMPLEs per row in image_buffer
  499. // NOTE: For compatibility with LLImage, we need to invert the rows.
  500. raw_image_data = raw_image->getData();
  501. const U8* last_row_data = raw_image_data + (getHeight()-1) * row_stride;
  502. JSAMPROW row_pointer[1]; // pointer to JSAMPLE row[s]
  503. while (cinfo.next_scanline < cinfo.image_height)
  504. {
  505. // jpeg_write_scanlines expects an array of pointers to scanlines.
  506. // Here the array is only one element long, but you could pass
  507. // more than one scanline at a time if that's more convenient.
  508. //Ugly const uncast here (jpeg_write_scanlines should take a const* but doesn't)
  509. //row_pointer[0] = (JSAMPROW)(raw_image_data + (cinfo.next_scanline * row_stride));
  510. row_pointer[0] = (JSAMPROW)(last_row_data - (cinfo.next_scanline * row_stride));
  511. jpeg_write_scanlines(&cinfo, row_pointer, 1);
  512. }
  513. ////////////////////////////////////////
  514. // Step 6: Finish compression
  515. jpeg_finish_compress(&cinfo);
  516. // After finish_compress, we can release the temp output buffer.
  517. delete[] mOutputBuffer;
  518. mOutputBuffer = NULL;
  519. mOutputBufferSize = 0;
  520. ////////////////////////////////////////
  521. // Step 7: release JPEG compression object
  522. jpeg_destroy_compress(&cinfo);
  523. }
  524. catch(int)
  525. {
  526. jpeg_destroy_compress(&cinfo);
  527. delete[] mOutputBuffer;
  528. mOutputBuffer = NULL;
  529. mOutputBufferSize = 0;
  530. return FALSE;
  531. }
  532. return TRUE;
  533. }