OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2006 Apple Computer, Inc. | 2 * Copyright (C) 2006 Apple Computer, Inc. |
3 * | 3 * |
4 * Portions are Copyright (C) 2001-6 mozilla.org | 4 * Portions are Copyright (C) 2001-6 mozilla.org |
5 * | 5 * |
6 * Other contributors: | 6 * Other contributors: |
7 * Stuart Parmenter <stuart@mozilla.com> | 7 * Stuart Parmenter <stuart@mozilla.com> |
8 * | 8 * |
9 * This library is free software; you can redistribute it and/or | 9 * This library is free software; you can redistribute it and/or |
10 * modify it under the terms of the GNU Lesser General Public | 10 * modify it under the terms of the GNU Lesser General Public |
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
385 // We updated |next_input_byte|, so we need to update |m_lastByteSet| | 385 // We updated |next_input_byte|, so we need to update |m_lastByteSet| |
386 // so we know not to update |m_restartPosition| again. | 386 // so we know not to update |m_restartPosition| again. |
387 m_lastSetByte = m_info.src->next_input_byte; | 387 m_lastSetByte = m_info.src->next_input_byte; |
388 } | 388 } |
389 | 389 |
390 bool fillBuffer() | 390 bool fillBuffer() |
391 { | 391 { |
392 if (m_needsRestart) { | 392 if (m_needsRestart) { |
393 m_needsRestart = false; | 393 m_needsRestart = false; |
394 m_nextReadPosition = m_restartPosition; | 394 m_nextReadPosition = m_restartPosition; |
395 } else if (m_lastSetByte != m_info.src->next_input_byte) { | 395 } else { |
396 // next_input_byte was updated by jpeg, meaning that it found a rest
art position. | 396 updateRestartPosition(); |
397 m_restartPosition = m_nextReadPosition - m_info.src->bytes_in_buffer
; | |
398 } | 397 } |
399 | 398 |
400 const char* segment; | 399 const char* segment; |
401 const unsigned bytes = m_data->getSomeData(segment, m_nextReadPosition); | 400 const unsigned bytes = m_data->getSomeData(segment, m_nextReadPosition); |
402 if (bytes == 0) { | 401 if (bytes == 0) { |
403 // We had to suspend. When we resume, we will need to start from the
restart position. | 402 // We had to suspend. When we resume, we will need to start from the
restart position. |
404 m_needsRestart = true; | 403 m_needsRestart = true; |
405 // Let libjpeg know that the buffer needs to be refilled. | 404 clearBuffer(); |
406 m_info.src->bytes_in_buffer = 0; | |
407 m_info.src->next_input_byte = nullptr; | |
408 m_lastSetByte = nullptr; | |
409 return false; | 405 return false; |
410 } | 406 } |
411 | 407 |
412 m_nextReadPosition += bytes; | 408 m_nextReadPosition += bytes; |
413 m_info.src->bytes_in_buffer = bytes; | 409 m_info.src->bytes_in_buffer = bytes; |
414 const JOCTET* nextByte = reinterpret_cast_ptr<const JOCTET*>(segment); | 410 const JOCTET* nextByte = reinterpret_cast_ptr<const JOCTET*>(segment); |
415 m_info.src->next_input_byte = nextByte; | 411 m_info.src->next_input_byte = nextByte; |
416 m_lastSetByte = nextByte; | 412 m_lastSetByte = nextByte; |
417 return true; | 413 return true; |
418 } | 414 } |
419 | 415 |
420 void setData(SharedBuffer* data) | 416 void setData(SharedBuffer* data) |
421 { | 417 { |
422 if (m_data.get() == data) | 418 if (m_data.get() == data) |
423 return; | 419 return; |
424 | 420 |
425 m_data = data; | 421 m_data = data; |
426 | 422 |
427 // If a restart is needed, the next call to fillBuffer will read from th
e new SharedBuffer. | 423 // If a restart is needed, the next call to fillBuffer will read from th
e new SharedBuffer. |
428 if (m_needsRestart) | 424 if (m_needsRestart) |
429 return; | 425 return; |
430 | 426 |
431 // Otherwise, empty the buffer, and leave the position the same, so fill
Buffer continues | 427 // Otherwise, empty the buffer, and leave the position the same, so fill
Buffer continues |
432 // reading from the same position in the new SharedBuffer. | 428 // reading from the same position in the new SharedBuffer. |
433 m_nextReadPosition -= m_info.src->bytes_in_buffer; | 429 m_nextReadPosition -= m_info.src->bytes_in_buffer; |
434 m_info.src->bytes_in_buffer = 0; | 430 clearBuffer(); |
435 m_info.src->next_input_byte = nullptr; | |
436 m_lastSetByte = nullptr; | |
437 } | 431 } |
438 | 432 |
439 bool decode(bool onlySize) | 433 bool decode(bool onlySize) |
440 { | 434 { |
441 // We need to do the setjmp here. Otherwise bad things will happen | 435 // We need to do the setjmp here. Otherwise bad things will happen |
442 if (setjmp(m_err.setjmp_buffer)) | 436 if (setjmp(m_err.setjmp_buffer)) |
443 return m_decoder->setFailed(); | 437 return m_decoder->setFailed(); |
444 | 438 |
445 J_COLOR_SPACE overrideColorSpace = JCS_UNKNOWN; | 439 J_COLOR_SPACE overrideColorSpace = JCS_UNKNOWN; |
446 switch (m_state) { | 440 switch (m_state) { |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
524 | 518 |
525 // Don't allocate a giant and superfluous memory buffer when the | 519 // Don't allocate a giant and superfluous memory buffer when the |
526 // image is a sequential JPEG. | 520 // image is a sequential JPEG. |
527 m_info.buffered_image = jpeg_has_multiple_scans(&m_info); | 521 m_info.buffered_image = jpeg_has_multiple_scans(&m_info); |
528 if (m_info.buffered_image) { | 522 if (m_info.buffered_image) { |
529 m_err.pub.emit_message = emit_message; | 523 m_err.pub.emit_message = emit_message; |
530 m_err.num_corrupt_warnings = 0; | 524 m_err.num_corrupt_warnings = 0; |
531 } | 525 } |
532 | 526 |
533 if (onlySize) { | 527 if (onlySize) { |
| 528 // This exits the function while there is still potentially |
| 529 // data in the buffer. Before this function is called again, |
| 530 // the SharedBuffer may be collapsed (by a call to |
| 531 // mergeSegmentsIntoBuffer), invalidating the "buffer" (which |
| 532 // in reality is a pointer into the SharedBuffer's data). |
| 533 // Defensively empty the buffer, but first find the latest |
| 534 // restart position and signal to restart, so the next call to |
| 535 // fillBuffer will resume from the correct point. |
| 536 m_needsRestart = true; |
| 537 updateRestartPosition(); |
| 538 clearBuffer(); |
534 return true; | 539 return true; |
535 } | 540 } |
536 // FALL THROUGH | 541 // FALL THROUGH |
537 | 542 |
538 case JPEG_START_DECOMPRESS: | 543 case JPEG_START_DECOMPRESS: |
539 // Set parameters for decompression. | 544 // Set parameters for decompression. |
540 // FIXME -- Should reset dct_method and dither mode for final pass | 545 // FIXME -- Should reset dct_method and dither mode for final pass |
541 // of progressive JPEG. | 546 // of progressive JPEG. |
542 m_info.dct_method = JDCT_ISLOW; | 547 m_info.dct_method = JDCT_ISLOW; |
543 m_info.dither_mode = JDITHER_FS; | 548 m_info.dither_mode = JDITHER_FS; |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
675 // We currently only support color profiles for RGB profiled images. | 680 // We currently only support color profiles for RGB profiled images. |
676 ASSERT(rgbData == qcms_profile_get_color_space(inputProfile)); | 681 ASSERT(rgbData == qcms_profile_get_color_space(inputProfile)); |
677 qcms_data_type dataFormat = hasAlpha ? QCMS_DATA_RGBA_8 : QCMS_DATA_RGB_
8; | 682 qcms_data_type dataFormat = hasAlpha ? QCMS_DATA_RGBA_8 : QCMS_DATA_RGB_
8; |
678 // FIXME: Don't force perceptual intent if the image profile contains an
intent. | 683 // FIXME: Don't force perceptual intent if the image profile contains an
intent. |
679 m_transform = qcms_transform_create(inputProfile, dataFormat, deviceProf
ile, dataFormat, QCMS_INTENT_PERCEPTUAL); | 684 m_transform = qcms_transform_create(inputProfile, dataFormat, deviceProf
ile, dataFormat, QCMS_INTENT_PERCEPTUAL); |
680 qcms_profile_release(inputProfile); | 685 qcms_profile_release(inputProfile); |
681 } | 686 } |
682 #endif | 687 #endif |
683 | 688 |
684 private: | 689 private: |
| 690 void updateRestartPosition() |
| 691 { |
| 692 if (m_lastSetByte != m_info.src->next_input_byte) { |
| 693 // next_input_byte was updated by jpeg, meaning that it found a rest
art position. |
| 694 m_restartPosition = m_nextReadPosition - m_info.src->bytes_in_buffer
; |
| 695 } |
| 696 } |
| 697 |
| 698 void clearBuffer() |
| 699 { |
| 700 // Let libjpeg know that the buffer needs to be refilled. |
| 701 m_info.src->bytes_in_buffer = 0; |
| 702 m_info.src->next_input_byte = nullptr; |
| 703 m_lastSetByte = nullptr; |
| 704 } |
| 705 |
685 RefPtr<SharedBuffer> m_data; | 706 RefPtr<SharedBuffer> m_data; |
686 JPEGImageDecoder* m_decoder; | 707 JPEGImageDecoder* m_decoder; |
687 // True if we need to back up to m_restartPosition. | 708 // True if we need to back up to m_restartPosition. |
688 bool m_needsRestart; | 709 bool m_needsRestart; |
689 // If libjpeg needed to restart, this is the position to restart from. | 710 // If libjpeg needed to restart, this is the position to restart from. |
690 unsigned m_restartPosition; | 711 unsigned m_restartPosition; |
691 // This is the position where we will read from, unless there is a restart. | 712 // This is the position where we will read from, unless there is a restart. |
692 unsigned m_nextReadPosition; | 713 unsigned m_nextReadPosition; |
693 // This is how we know to update the restart position. It is the last value | 714 // This is how we know to update the restart position. It is the last value |
694 // we set to next_input_byte. libjpeg will update next_input_byte when it | 715 // we set to next_input_byte. libjpeg will update next_input_byte when it |
(...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1055 // has failed. | 1076 // has failed. |
1056 if (!m_reader->decode(onlySize) && isAllDataReceived()) | 1077 if (!m_reader->decode(onlySize) && isAllDataReceived()) |
1057 setFailed(); | 1078 setFailed(); |
1058 | 1079 |
1059 // If decoding is done or failed, we don't need the JPEGImageReader anymore. | 1080 // If decoding is done or failed, we don't need the JPEGImageReader anymore. |
1060 if (isComplete(this, onlySize) || failed()) | 1081 if (isComplete(this, onlySize) || failed()) |
1061 m_reader.clear(); | 1082 m_reader.clear(); |
1062 } | 1083 } |
1063 | 1084 |
1064 } | 1085 } |
OLD | NEW |