Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(218)

Side by Side Diff: Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp

Issue 1358643002: Fix caching bug in JPEGImageDecoder (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Respond to pkasting's comments in patch set 1 Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | Source/platform/image-decoders/jpeg/JPEGImageDecoderTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | Source/platform/image-decoders/jpeg/JPEGImageDecoderTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698