| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (C) 2006 Apple Computer, Inc. | |
| 3 * | |
| 4 * Portions are Copyright (C) 2001-6 mozilla.org | |
| 5 * | |
| 6 * Other contributors: | |
| 7 * Stuart Parmenter <stuart@mozilla.com> | |
| 8 * | |
| 9 * This library is free software; you can redistribute it and/or | |
| 10 * modify it under the terms of the GNU Lesser General Public | |
| 11 * License as published by the Free Software Foundation; either | |
| 12 * version 2.1 of the License, or (at your option) any later version. | |
| 13 * | |
| 14 * This library is distributed in the hope that it will be useful, | |
| 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 17 * Lesser General Public License for more details. | |
| 18 * | |
| 19 * You should have received a copy of the GNU Lesser General Public | |
| 20 * License along with this library; if not, write to the Free Software | |
| 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
| 22 * | |
| 23 * Alternatively, the contents of this file may be used under the terms | |
| 24 * of either the Mozilla Public License Version 1.1, found at | |
| 25 * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public | |
| 26 * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html | |
| 27 * (the "GPL"), in which case the provisions of the MPL or the GPL are | |
| 28 * applicable instead of those above. If you wish to allow use of your | |
| 29 * version of this file only under the terms of one of those two | |
| 30 * licenses (the MPL or the GPL) and not to allow others to use your | |
| 31 * version of this file under the LGPL, indicate your decision by | |
| 32 * deletingthe provisions above and replace them with the notice and | |
| 33 * other provisions required by the MPL or the GPL, as the case may be. | |
| 34 * If you do not delete the provisions above, a recipient may use your | |
| 35 * version of this file under any of the LGPL, the MPL or the GPL. | |
| 36 */ | |
| 37 | |
| 38 #include "platform/image-decoders/jpeg/JPEGImageDecoder.h" | |
| 39 | |
| 40 #include <memory> | |
| 41 #include "platform/instrumentation/PlatformInstrumentation.h" | |
| 42 #include "platform/wtf/PtrUtil.h" | |
| 43 | |
| 44 extern "C" { | |
| 45 #include <stdio.h> // jpeglib.h needs stdio FILE. | |
| 46 #include "jpeglib.h" | |
| 47 #include "iccjpeg.h" | |
| 48 #include <setjmp.h> | |
| 49 } | |
| 50 | |
| 51 #if CPU(BIG_ENDIAN) || CPU(MIDDLE_ENDIAN) | |
| 52 #error Blink assumes a little-endian target. | |
| 53 #endif | |
| 54 | |
| 55 #if defined(JCS_ALPHA_EXTENSIONS) | |
| 56 #define TURBO_JPEG_RGB_SWIZZLE | |
| 57 #if SK_B32_SHIFT // Output little-endian RGBA pixels (Android). | |
| 58 inline J_COLOR_SPACE rgbOutputColorSpace() { | |
| 59 return JCS_EXT_RGBA; | |
| 60 } | |
| 61 #else // Output little-endian BGRA pixels. | |
| 62 inline J_COLOR_SPACE rgbOutputColorSpace() { | |
| 63 return JCS_EXT_BGRA; | |
| 64 } | |
| 65 #endif | |
| 66 inline bool turboSwizzled(J_COLOR_SPACE colorSpace) { | |
| 67 return colorSpace == JCS_EXT_RGBA || colorSpace == JCS_EXT_BGRA; | |
| 68 } | |
| 69 #else | |
| 70 inline J_COLOR_SPACE rgbOutputColorSpace() { | |
| 71 return JCS_RGB; | |
| 72 } | |
| 73 #endif | |
| 74 | |
| 75 namespace { | |
| 76 | |
| 77 const int exifMarker = JPEG_APP0 + 1; | |
| 78 | |
| 79 // JPEG only supports a denominator of 8. | |
| 80 const unsigned scaleDenominator = 8; | |
| 81 | |
| 82 } // namespace | |
| 83 | |
| 84 namespace blink { | |
| 85 | |
| 86 struct decoder_error_mgr { | |
| 87 DISALLOW_NEW(); | |
| 88 struct jpeg_error_mgr pub; // "public" fields for IJG library | |
| 89 int num_corrupt_warnings; // Counts corrupt warning messages | |
| 90 jmp_buf setjmp_buffer; // For handling catastropic errors | |
| 91 }; | |
| 92 | |
| 93 struct decoder_source_mgr { | |
| 94 DISALLOW_NEW(); | |
| 95 struct jpeg_source_mgr pub; // "public" fields for IJG library | |
| 96 JPEGImageReader* reader; | |
| 97 }; | |
| 98 | |
| 99 enum jstate { | |
| 100 JPEG_HEADER, // Reading JFIF headers | |
| 101 JPEG_START_DECOMPRESS, | |
| 102 JPEG_DECOMPRESS_PROGRESSIVE, // Output progressive pixels | |
| 103 JPEG_DECOMPRESS_SEQUENTIAL, // Output sequential pixels | |
| 104 JPEG_DONE | |
| 105 }; | |
| 106 | |
| 107 enum yuv_subsampling { | |
| 108 YUV_UNKNOWN, | |
| 109 YUV_410, | |
| 110 YUV_411, | |
| 111 YUV_420, | |
| 112 YUV_422, | |
| 113 YUV_440, | |
| 114 YUV_444 | |
| 115 }; | |
| 116 | |
| 117 void init_source(j_decompress_ptr jd); | |
| 118 boolean fill_input_buffer(j_decompress_ptr jd); | |
| 119 void skip_input_data(j_decompress_ptr jd, long num_bytes); | |
| 120 void term_source(j_decompress_ptr jd); | |
| 121 void error_exit(j_common_ptr cinfo); | |
| 122 void emit_message(j_common_ptr cinfo, int msg_level); | |
| 123 | |
| 124 static unsigned ReadUint16(JOCTET* data, bool is_big_endian) { | |
| 125 if (is_big_endian) | |
| 126 return (GETJOCTET(data[0]) << 8) | GETJOCTET(data[1]); | |
| 127 return (GETJOCTET(data[1]) << 8) | GETJOCTET(data[0]); | |
| 128 } | |
| 129 | |
| 130 static unsigned ReadUint32(JOCTET* data, bool is_big_endian) { | |
| 131 if (is_big_endian) | |
| 132 return (GETJOCTET(data[0]) << 24) | (GETJOCTET(data[1]) << 16) | | |
| 133 (GETJOCTET(data[2]) << 8) | GETJOCTET(data[3]); | |
| 134 return (GETJOCTET(data[3]) << 24) | (GETJOCTET(data[2]) << 16) | | |
| 135 (GETJOCTET(data[1]) << 8) | GETJOCTET(data[0]); | |
| 136 } | |
| 137 | |
| 138 static bool CheckExifHeader(jpeg_saved_marker_ptr marker, | |
| 139 bool& is_big_endian, | |
| 140 unsigned& ifd_offset) { | |
| 141 // For exif data, the APP1 block is followed by 'E', 'x', 'i', 'f', '\0', | |
| 142 // then a fill byte, and then a tiff file that contains the metadata. | |
| 143 // A tiff file starts with 'I', 'I' (intel / little endian byte order) or | |
| 144 // 'M', 'M' (motorola / big endian byte order), followed by (uint16_t)42, | |
| 145 // followed by an uint32_t with the offset to the tag block, relative to the | |
| 146 // tiff file start. | |
| 147 const unsigned kExifHeaderSize = 14; | |
| 148 if (!(marker->marker == exifMarker && | |
| 149 marker->data_length >= kExifHeaderSize && marker->data[0] == 'E' && | |
| 150 marker->data[1] == 'x' && marker->data[2] == 'i' && | |
| 151 marker->data[3] == 'f' && | |
| 152 marker->data[4] == '\0' | |
| 153 // data[5] is a fill byte | |
| 154 && ((marker->data[6] == 'I' && marker->data[7] == 'I') || | |
| 155 (marker->data[6] == 'M' && marker->data[7] == 'M')))) | |
| 156 return false; | |
| 157 | |
| 158 is_big_endian = marker->data[6] == 'M'; | |
| 159 if (ReadUint16(marker->data + 8, is_big_endian) != 42) | |
| 160 return false; | |
| 161 | |
| 162 ifd_offset = ReadUint32(marker->data + 10, is_big_endian); | |
| 163 return true; | |
| 164 } | |
| 165 | |
| 166 static ImageOrientation ReadImageOrientation(jpeg_decompress_struct* info) { | |
| 167 // The JPEG decoder looks at EXIF metadata. | |
| 168 // FIXME: Possibly implement XMP and IPTC support. | |
| 169 const unsigned kOrientationTag = 0x112; | |
| 170 const unsigned kShortType = 3; | |
| 171 for (jpeg_saved_marker_ptr marker = info->marker_list; marker; | |
| 172 marker = marker->next) { | |
| 173 bool is_big_endian; | |
| 174 unsigned ifd_offset; | |
| 175 if (!CheckExifHeader(marker, is_big_endian, ifd_offset)) | |
| 176 continue; | |
| 177 const unsigned kOffsetToTiffData = | |
| 178 6; // Account for 'Exif\0<fill byte>' header. | |
| 179 if (marker->data_length < kOffsetToTiffData || | |
| 180 ifd_offset >= marker->data_length - kOffsetToTiffData) | |
| 181 continue; | |
| 182 ifd_offset += kOffsetToTiffData; | |
| 183 | |
| 184 // The jpeg exif container format contains a tiff block for metadata. | |
| 185 // A tiff image file directory (ifd) consists of a uint16_t describing | |
| 186 // the number of ifd entries, followed by that many entries. | |
| 187 // When touching this code, it's useful to look at the tiff spec: | |
| 188 // http://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf | |
| 189 JOCTET* ifd = marker->data + ifd_offset; | |
| 190 JOCTET* end = marker->data + marker->data_length; | |
| 191 if (end - ifd < 2) | |
| 192 continue; | |
| 193 unsigned tag_count = ReadUint16(ifd, is_big_endian); | |
| 194 ifd += 2; // Skip over the uint16 that was just read. | |
| 195 | |
| 196 // Every ifd entry is 2 bytes of tag, 2 bytes of contents datatype, | |
| 197 // 4 bytes of number-of-elements, and 4 bytes of either offset to the | |
| 198 // tag data, or if the data is small enough, the inlined data itself. | |
| 199 const int kIfdEntrySize = 12; | |
| 200 for (unsigned i = 0; i < tag_count && end - ifd >= kIfdEntrySize; | |
| 201 ++i, ifd += kIfdEntrySize) { | |
| 202 unsigned tag = ReadUint16(ifd, is_big_endian); | |
| 203 unsigned type = ReadUint16(ifd + 2, is_big_endian); | |
| 204 unsigned count = ReadUint32(ifd + 4, is_big_endian); | |
| 205 if (tag == kOrientationTag && type == kShortType && count == 1) | |
| 206 return ImageOrientation::FromEXIFValue( | |
| 207 ReadUint16(ifd + 8, is_big_endian)); | |
| 208 } | |
| 209 } | |
| 210 | |
| 211 return ImageOrientation(); | |
| 212 } | |
| 213 | |
| 214 static IntSize ComputeYUVSize(const jpeg_decompress_struct* info, | |
| 215 int component) { | |
| 216 return IntSize(info->cur_comp_info[component]->downsampled_width, | |
| 217 info->cur_comp_info[component]->downsampled_height); | |
| 218 } | |
| 219 | |
| 220 static size_t ComputeYUVWidthBytes(const jpeg_decompress_struct* info, | |
| 221 int component) { | |
| 222 return info->cur_comp_info[component]->width_in_blocks * DCTSIZE; | |
| 223 } | |
| 224 | |
| 225 static yuv_subsampling YuvSubsampling(const jpeg_decompress_struct& info) { | |
| 226 if ((DCTSIZE == 8) && (info.num_components == 3) && (info.scale_denom <= 8) && | |
| 227 (info.cur_comp_info[0]) && (info.cur_comp_info[1]) && | |
| 228 (info.cur_comp_info[2]) && (info.cur_comp_info[1]->h_samp_factor == 1) && | |
| 229 (info.cur_comp_info[1]->v_samp_factor == 1) && | |
| 230 (info.cur_comp_info[2]->h_samp_factor == 1) && | |
| 231 (info.cur_comp_info[2]->v_samp_factor == 1)) { | |
| 232 int h = info.cur_comp_info[0]->h_samp_factor; | |
| 233 int v = info.cur_comp_info[0]->v_samp_factor; | |
| 234 // 4:4:4 : (h == 1) && (v == 1) | |
| 235 // 4:4:0 : (h == 1) && (v == 2) | |
| 236 // 4:2:2 : (h == 2) && (v == 1) | |
| 237 // 4:2:0 : (h == 2) && (v == 2) | |
| 238 // 4:1:1 : (h == 4) && (v == 1) | |
| 239 // 4:1:0 : (h == 4) && (v == 2) | |
| 240 if (v == 1) { | |
| 241 switch (h) { | |
| 242 case 1: | |
| 243 return YUV_444; | |
| 244 case 2: | |
| 245 return YUV_422; | |
| 246 case 4: | |
| 247 return YUV_411; | |
| 248 default: | |
| 249 break; | |
| 250 } | |
| 251 } else if (v == 2) { | |
| 252 switch (h) { | |
| 253 case 1: | |
| 254 return YUV_440; | |
| 255 case 2: | |
| 256 return YUV_420; | |
| 257 case 4: | |
| 258 return YUV_410; | |
| 259 default: | |
| 260 break; | |
| 261 } | |
| 262 } | |
| 263 } | |
| 264 | |
| 265 return YUV_UNKNOWN; | |
| 266 } | |
| 267 | |
| 268 static void ProgressMonitor(j_common_ptr info) { | |
| 269 int scan = ((j_decompress_ptr)info)->input_scan_number; | |
| 270 // Progressive images with a very large number of scans can cause the | |
| 271 // decoder to hang. Here we use the progress monitor to abort on | |
| 272 // a very large number of scans. 100 is arbitrary, but much larger | |
| 273 // than the number of scans we might expect in a normal image. | |
| 274 if (scan >= 100) { | |
| 275 error_exit(info); | |
| 276 } | |
| 277 } | |
| 278 | |
| 279 class JPEGImageReader final { | |
| 280 USING_FAST_MALLOC(JPEGImageReader); | |
| 281 WTF_MAKE_NONCOPYABLE(JPEGImageReader); | |
| 282 | |
| 283 public: | |
| 284 JPEGImageReader(JPEGImageDecoder* decoder) | |
| 285 : decoder_(decoder), | |
| 286 needs_restart_(false), | |
| 287 restart_position_(0), | |
| 288 next_read_position_(0), | |
| 289 last_set_byte_(nullptr), | |
| 290 state_(JPEG_HEADER), | |
| 291 samples_(nullptr) { | |
| 292 memset(&info_, 0, sizeof(jpeg_decompress_struct)); | |
| 293 | |
| 294 // Set up the normal JPEG error routines, then override error_exit. | |
| 295 info_.err = jpeg_std_error(&err_.pub); | |
| 296 err_.pub.error_exit = error_exit; | |
| 297 | |
| 298 // Allocate and initialize JPEG decompression object. | |
| 299 jpeg_create_decompress(&info_); | |
| 300 | |
| 301 // Initialize source manager. | |
| 302 memset(&src_, 0, sizeof(decoder_source_mgr)); | |
| 303 info_.src = reinterpret_cast_ptr<jpeg_source_mgr*>(&src_); | |
| 304 | |
| 305 // Set up callback functions. | |
| 306 src_.pub.init_source = init_source; | |
| 307 src_.pub.fill_input_buffer = fill_input_buffer; | |
| 308 src_.pub.skip_input_data = skip_input_data; | |
| 309 src_.pub.resync_to_restart = jpeg_resync_to_restart; | |
| 310 src_.pub.term_source = term_source; | |
| 311 src_.reader = this; | |
| 312 | |
| 313 // Set up a progress monitor. | |
| 314 info_.progress = &progress_mgr_; | |
| 315 progress_mgr_.progress_monitor = ProgressMonitor; | |
| 316 | |
| 317 // Retain ICC color profile markers for color management. | |
| 318 setup_read_icc_profile(&info_); | |
| 319 | |
| 320 // Keep APP1 blocks, for obtaining exif data. | |
| 321 jpeg_save_markers(&info_, exifMarker, 0xFFFF); | |
| 322 } | |
| 323 | |
| 324 ~JPEGImageReader() { jpeg_destroy_decompress(&info_); } | |
| 325 | |
| 326 void SkipBytes(long num_bytes) { | |
| 327 if (num_bytes <= 0) | |
| 328 return; | |
| 329 | |
| 330 size_t bytes_to_skip = static_cast<size_t>(num_bytes); | |
| 331 | |
| 332 if (bytes_to_skip < info_.src->bytes_in_buffer) { | |
| 333 // The next byte needed is in the buffer. Move to it. | |
| 334 info_.src->bytes_in_buffer -= bytes_to_skip; | |
| 335 info_.src->next_input_byte += bytes_to_skip; | |
| 336 } else { | |
| 337 // Move beyond the buffer and empty it. | |
| 338 next_read_position_ = | |
| 339 next_read_position_ + bytes_to_skip - info_.src->bytes_in_buffer; | |
| 340 info_.src->bytes_in_buffer = 0; | |
| 341 info_.src->next_input_byte = nullptr; | |
| 342 } | |
| 343 | |
| 344 // This is a valid restart position. | |
| 345 restart_position_ = next_read_position_ - info_.src->bytes_in_buffer; | |
| 346 // We updated |next_input_byte|, so we need to update |last_byte_set_| | |
| 347 // so we know not to update |restart_position_| again. | |
| 348 last_set_byte_ = info_.src->next_input_byte; | |
| 349 } | |
| 350 | |
| 351 bool FillBuffer() { | |
| 352 if (needs_restart_) { | |
| 353 needs_restart_ = false; | |
| 354 next_read_position_ = restart_position_; | |
| 355 } else { | |
| 356 UpdateRestartPosition(); | |
| 357 } | |
| 358 | |
| 359 const char* segment; | |
| 360 const size_t bytes = data_->GetSomeData(segment, next_read_position_); | |
| 361 if (bytes == 0) { | |
| 362 // We had to suspend. When we resume, we will need to start from the | |
| 363 // restart position. | |
| 364 needs_restart_ = true; | |
| 365 ClearBuffer(); | |
| 366 return false; | |
| 367 } | |
| 368 | |
| 369 next_read_position_ += bytes; | |
| 370 info_.src->bytes_in_buffer = bytes; | |
| 371 const JOCTET* next_byte = reinterpret_cast_ptr<const JOCTET*>(segment); | |
| 372 info_.src->next_input_byte = next_byte; | |
| 373 last_set_byte_ = next_byte; | |
| 374 return true; | |
| 375 } | |
| 376 | |
| 377 void SetData(SegmentReader* data) { | |
| 378 if (data_.Get() == data) | |
| 379 return; | |
| 380 | |
| 381 data_ = data; | |
| 382 | |
| 383 // If a restart is needed, the next call to fillBuffer will read from the | |
| 384 // new SegmentReader. | |
| 385 if (needs_restart_) | |
| 386 return; | |
| 387 | |
| 388 // Otherwise, empty the buffer, and leave the position the same, so | |
| 389 // FillBuffer continues reading from the same position in the new | |
| 390 // SegmentReader. | |
| 391 next_read_position_ -= info_.src->bytes_in_buffer; | |
| 392 ClearBuffer(); | |
| 393 } | |
| 394 | |
| 395 bool Decode(bool only_size) { | |
| 396 // We need to do the setjmp here. Otherwise bad things will happen | |
| 397 if (setjmp(err_.setjmp_buffer)) | |
| 398 return decoder_->SetFailed(); | |
| 399 | |
| 400 J_COLOR_SPACE override_color_space = JCS_UNKNOWN; | |
| 401 switch (state_) { | |
| 402 case JPEG_HEADER: | |
| 403 // Read file parameters with jpeg_read_header(). | |
| 404 if (jpeg_read_header(&info_, true) == JPEG_SUSPENDED) | |
| 405 return false; // I/O suspension. | |
| 406 | |
| 407 switch (info_.jpeg_color_space) { | |
| 408 case JCS_YCbCr: | |
| 409 // libjpeg can convert YCbCr image pixels to RGB. | |
| 410 info_.out_color_space = rgbOutputColorSpace(); | |
| 411 if (decoder_->HasImagePlanes() && | |
| 412 (YuvSubsampling(info_) != YUV_UNKNOWN)) | |
| 413 override_color_space = JCS_YCbCr; | |
| 414 break; | |
| 415 case JCS_GRAYSCALE: | |
| 416 case JCS_RGB: | |
| 417 // libjpeg can convert GRAYSCALE image pixels to RGB. | |
| 418 info_.out_color_space = rgbOutputColorSpace(); | |
| 419 break; | |
| 420 case JCS_CMYK: | |
| 421 case JCS_YCCK: | |
| 422 // libjpeg can convert YCCK to CMYK, but neither to RGB, so we | |
| 423 // manually convert CMKY to RGB. | |
| 424 info_.out_color_space = JCS_CMYK; | |
| 425 break; | |
| 426 default: | |
| 427 return decoder_->SetFailed(); | |
| 428 } | |
| 429 | |
| 430 state_ = JPEG_START_DECOMPRESS; | |
| 431 | |
| 432 // We can fill in the size now that the header is available. | |
| 433 if (!decoder_->SetSize(info_.image_width, info_.image_height)) | |
| 434 return false; | |
| 435 | |
| 436 // Calculate and set decoded size. | |
| 437 info_.scale_num = decoder_->DesiredScaleNumerator(); | |
| 438 info_.scale_denom = scaleDenominator; | |
| 439 // Scaling caused by running low on memory isn't supported by YUV | |
| 440 // decoding since YUV decoding is performed on full sized images. At | |
| 441 // this point, buffers and various image info structs have already been | |
| 442 // set up for the scaled size after reading the image header using this | |
| 443 // decoder, so using the full size is no longer possible. | |
| 444 if (info_.scale_num != info_.scale_denom) | |
| 445 override_color_space = JCS_UNKNOWN; | |
| 446 jpeg_calc_output_dimensions(&info_); | |
| 447 decoder_->SetDecodedSize(info_.output_width, info_.output_height); | |
| 448 | |
| 449 decoder_->SetOrientation(ReadImageOrientation(Info())); | |
| 450 | |
| 451 // Allow color management of the decoded RGBA pixels if possible. | |
| 452 if (!decoder_->IgnoresColorSpace()) { | |
| 453 JOCTET* profile = nullptr; | |
| 454 unsigned profile_length = 0; | |
| 455 if (read_icc_profile(Info(), &profile, &profile_length)) { | |
| 456 Decoder()->SetEmbeddedColorProfile(reinterpret_cast<char*>(profile), | |
| 457 profile_length); | |
| 458 free(profile); | |
| 459 } | |
| 460 if (Decoder()->ColorTransform()) { | |
| 461 override_color_space = JCS_UNKNOWN; | |
| 462 } | |
| 463 } | |
| 464 if (override_color_space == JCS_YCbCr) { | |
| 465 info_.out_color_space = JCS_YCbCr; | |
| 466 info_.raw_data_out = TRUE; | |
| 467 uv_size_ = ComputeYUVSize( | |
| 468 &info_, | |
| 469 1); // U size and V size have to be the same if we got here | |
| 470 } | |
| 471 | |
| 472 // Don't allocate a giant and superfluous memory buffer when the | |
| 473 // image is a sequential JPEG. | |
| 474 info_.buffered_image = jpeg_has_multiple_scans(&info_); | |
| 475 if (info_.buffered_image) { | |
| 476 err_.pub.emit_message = emit_message; | |
| 477 err_.num_corrupt_warnings = 0; | |
| 478 } | |
| 479 | |
| 480 if (only_size) { | |
| 481 // This exits the function while there is still potentially | |
| 482 // data in the buffer. Before this function is called again, | |
| 483 // the SharedBuffer may be collapsed (by a call to | |
| 484 // MergeSegmentsIntoBuffer), invalidating the "buffer" (which | |
| 485 // in reality is a pointer into the SharedBuffer's data). | |
| 486 // Defensively empty the buffer, but first find the latest | |
| 487 // restart position and signal to restart, so the next call to | |
| 488 // FillBuffer will resume from the correct point. | |
| 489 needs_restart_ = true; | |
| 490 UpdateRestartPosition(); | |
| 491 ClearBuffer(); | |
| 492 return true; | |
| 493 } | |
| 494 // FALL THROUGH | |
| 495 | |
| 496 case JPEG_START_DECOMPRESS: | |
| 497 // Set parameters for decompression. | |
| 498 // FIXME -- Should reset dct_method and dither mode for final pass | |
| 499 // of progressive JPEG. | |
| 500 info_.dct_method = JDCT_ISLOW; | |
| 501 info_.dither_mode = JDITHER_FS; | |
| 502 info_.do_fancy_upsampling = true; | |
| 503 info_.do_block_smoothing = true; | |
| 504 info_.enable_2pass_quant = false; | |
| 505 // FIXME: should we just assert these? | |
| 506 info_.enable_external_quant = false; | |
| 507 info_.enable_1pass_quant = false; | |
| 508 info_.quantize_colors = false; | |
| 509 info_.colormap = 0; | |
| 510 | |
| 511 // Make a one-row-high sample array that will go away when done with | |
| 512 // image. Always make it big enough to hold one RGBA row. Since this | |
| 513 // uses the IJG memory manager, it must be allocated before the call | |
| 514 // to jpeg_start_decompress(). | |
| 515 samples_ = AllocateSampleArray(); | |
| 516 | |
| 517 // Start decompressor. | |
| 518 if (!jpeg_start_decompress(&info_)) | |
| 519 return false; // I/O suspension. | |
| 520 | |
| 521 // If this is a progressive JPEG ... | |
| 522 state_ = (info_.buffered_image) ? JPEG_DECOMPRESS_PROGRESSIVE | |
| 523 : JPEG_DECOMPRESS_SEQUENTIAL; | |
| 524 // FALL THROUGH | |
| 525 | |
| 526 case JPEG_DECOMPRESS_SEQUENTIAL: | |
| 527 if (state_ == JPEG_DECOMPRESS_SEQUENTIAL) { | |
| 528 if (!decoder_->OutputScanlines()) | |
| 529 return false; // I/O suspension. | |
| 530 | |
| 531 // If we've completed image output... | |
| 532 DCHECK_EQ(info_.output_scanline, info_.output_height); | |
| 533 state_ = JPEG_DONE; | |
| 534 } | |
| 535 // FALL THROUGH | |
| 536 | |
| 537 case JPEG_DECOMPRESS_PROGRESSIVE: | |
| 538 if (state_ == JPEG_DECOMPRESS_PROGRESSIVE) { | |
| 539 int status = 0; | |
| 540 do { | |
| 541 decoder_error_mgr* err = | |
| 542 reinterpret_cast_ptr<decoder_error_mgr*>(info_.err); | |
| 543 if (err->num_corrupt_warnings) | |
| 544 break; | |
| 545 status = jpeg_consume_input(&info_); | |
| 546 } while ((status != JPEG_SUSPENDED) && (status != JPEG_REACHED_EOI)); | |
| 547 | |
| 548 for (;;) { | |
| 549 if (!info_.output_scanline) { | |
| 550 int scan = info_.input_scan_number; | |
| 551 | |
| 552 // If we haven't displayed anything yet | |
| 553 // (output_scan_number == 0) and we have enough data for | |
| 554 // a complete scan, force output of the last full scan. | |
| 555 if (!info_.output_scan_number && (scan > 1) && | |
| 556 (status != JPEG_REACHED_EOI)) | |
| 557 --scan; | |
| 558 | |
| 559 if (!jpeg_start_output(&info_, scan)) | |
| 560 return false; // I/O suspension. | |
| 561 } | |
| 562 | |
| 563 if (info_.output_scanline == 0xffffff) | |
| 564 info_.output_scanline = 0; | |
| 565 | |
| 566 if (!decoder_->OutputScanlines()) { | |
| 567 if (decoder_->Failed()) | |
| 568 return false; | |
| 569 // If no scan lines were read, flag it so we don't call | |
| 570 // jpeg_start_output() multiple times for the same scan. | |
| 571 if (!info_.output_scanline) | |
| 572 info_.output_scanline = 0xffffff; | |
| 573 | |
| 574 return false; // I/O suspension. | |
| 575 } | |
| 576 | |
| 577 if (info_.output_scanline == info_.output_height) { | |
| 578 if (!jpeg_finish_output(&info_)) | |
| 579 return false; // I/O suspension. | |
| 580 | |
| 581 if (jpeg_input_complete(&info_) && | |
| 582 (info_.input_scan_number == info_.output_scan_number)) | |
| 583 break; | |
| 584 | |
| 585 info_.output_scanline = 0; | |
| 586 } | |
| 587 } | |
| 588 | |
| 589 state_ = JPEG_DONE; | |
| 590 } | |
| 591 // FALL THROUGH | |
| 592 | |
| 593 case JPEG_DONE: | |
| 594 // Finish decompression. | |
| 595 return jpeg_finish_decompress(&info_); | |
| 596 } | |
| 597 | |
| 598 return true; | |
| 599 } | |
| 600 | |
| 601 jpeg_decompress_struct* Info() { return &info_; } | |
| 602 JSAMPARRAY Samples() const { return samples_; } | |
| 603 JPEGImageDecoder* Decoder() { return decoder_; } | |
| 604 IntSize UvSize() const { return uv_size_; } | |
| 605 | |
| 606 private: | |
| 607 JSAMPARRAY AllocateSampleArray() { | |
| 608 // Some output color spaces don't need the sample array: don't allocate in that | |
| 609 // case. | |
| 610 #if defined(TURBO_JPEG_RGB_SWIZZLE) | |
| 611 if (turboSwizzled(info_.out_color_space)) | |
| 612 return nullptr; | |
| 613 #endif | |
| 614 | |
| 615 if (info_.out_color_space != JCS_YCbCr) | |
| 616 return (*info_.mem->alloc_sarray)( | |
| 617 reinterpret_cast_ptr<j_common_ptr>(&info_), JPOOL_IMAGE, | |
| 618 4 * info_.output_width, 1); | |
| 619 | |
| 620 // Compute the width of the Y plane in bytes. This may be larger than the | |
| 621 // output width, since the jpeg library requires that the allocated width be | |
| 622 // a multiple of DCTSIZE. Note that this buffer will be used as garbage | |
| 623 // memory for rows that extend below the actual height of the image. We can | |
| 624 // reuse the same memory for the U and V planes, since we are guaranteed | |
| 625 // that the Y plane width is at least as large as the U and V plane widths. | |
| 626 int width_bytes = ComputeYUVWidthBytes(&info_, 0); | |
| 627 return (*info_.mem->alloc_sarray)( | |
| 628 reinterpret_cast_ptr<j_common_ptr>(&info_), JPOOL_IMAGE, width_bytes, | |
| 629 1); | |
| 630 } | |
| 631 | |
| 632 void UpdateRestartPosition() { | |
| 633 if (last_set_byte_ != info_.src->next_input_byte) { | |
| 634 // next_input_byte was updated by jpeg, meaning that it found a restart | |
| 635 // position. | |
| 636 restart_position_ = next_read_position_ - info_.src->bytes_in_buffer; | |
| 637 } | |
| 638 } | |
| 639 | |
| 640 void ClearBuffer() { | |
| 641 // Let libjpeg know that the buffer needs to be refilled. | |
| 642 info_.src->bytes_in_buffer = 0; | |
| 643 info_.src->next_input_byte = nullptr; | |
| 644 last_set_byte_ = nullptr; | |
| 645 } | |
| 646 | |
| 647 RefPtr<SegmentReader> data_; | |
| 648 JPEGImageDecoder* decoder_; | |
| 649 | |
| 650 // Input reading: True if we need to back up to restart_position_. | |
| 651 bool needs_restart_; | |
| 652 // If libjpeg needed to restart, this is the position to restart from. | |
| 653 size_t restart_position_; | |
| 654 // This is the position where we will read from, unless there is a restart. | |
| 655 size_t next_read_position_; | |
| 656 // This is how we know to update the restart position. It is the last value | |
| 657 // we set to next_input_byte. libjpeg will update next_input_byte when it | |
| 658 // has found the next restart position, so if it no longer matches this | |
| 659 // value, we know we've reached the next restart position. | |
| 660 const JOCTET* last_set_byte_; | |
| 661 | |
| 662 jpeg_decompress_struct info_; | |
| 663 decoder_error_mgr err_; | |
| 664 decoder_source_mgr src_; | |
| 665 jpeg_progress_mgr progress_mgr_; | |
| 666 jstate state_; | |
| 667 | |
| 668 JSAMPARRAY samples_; | |
| 669 IntSize uv_size_; | |
| 670 }; | |
| 671 | |
| 672 void error_exit( | |
| 673 j_common_ptr cinfo) // Decoding failed: return control to the setjmp point. | |
| 674 { | |
| 675 longjmp(reinterpret_cast_ptr<decoder_error_mgr*>(cinfo->err)->setjmp_buffer, | |
| 676 -1); | |
| 677 } | |
| 678 | |
| 679 void emit_message(j_common_ptr cinfo, int msg_level) { | |
| 680 if (msg_level >= 0) | |
| 681 return; | |
| 682 | |
| 683 decoder_error_mgr* err = reinterpret_cast_ptr<decoder_error_mgr*>(cinfo->err); | |
| 684 err->pub.num_warnings++; | |
| 685 | |
| 686 // Detect and count corrupt JPEG warning messages. | |
| 687 const char* warning = 0; | |
| 688 int code = err->pub.msg_code; | |
| 689 if (code > 0 && code <= err->pub.last_jpeg_message) | |
| 690 warning = err->pub.jpeg_message_table[code]; | |
| 691 if (warning && !strncmp("Corrupt JPEG", warning, 12)) | |
| 692 err->num_corrupt_warnings++; | |
| 693 } | |
| 694 | |
| 695 void init_source(j_decompress_ptr) {} | |
| 696 | |
| 697 void skip_input_data(j_decompress_ptr jd, long num_bytes) { | |
| 698 reinterpret_cast_ptr<decoder_source_mgr*>(jd->src)->reader->SkipBytes( | |
| 699 num_bytes); | |
| 700 } | |
| 701 | |
| 702 boolean fill_input_buffer(j_decompress_ptr jd) { | |
| 703 return reinterpret_cast_ptr<decoder_source_mgr*>(jd->src) | |
| 704 ->reader->FillBuffer(); | |
| 705 } | |
| 706 | |
| 707 void term_source(j_decompress_ptr jd) { | |
| 708 reinterpret_cast_ptr<decoder_source_mgr*>(jd->src) | |
| 709 ->reader->Decoder() | |
| 710 ->Complete(); | |
| 711 } | |
| 712 | |
| 713 JPEGImageDecoder::JPEGImageDecoder(AlphaOption alpha_option, | |
| 714 const ColorBehavior& color_behavior, | |
| 715 size_t max_decoded_bytes) | |
| 716 : ImageDecoder(alpha_option, color_behavior, max_decoded_bytes) {} | |
| 717 | |
| 718 JPEGImageDecoder::~JPEGImageDecoder() {} | |
| 719 | |
| 720 bool JPEGImageDecoder::SetSize(unsigned width, unsigned height) { | |
| 721 if (!ImageDecoder::SetSize(width, height)) | |
| 722 return false; | |
| 723 | |
| 724 if (!DesiredScaleNumerator()) | |
| 725 return SetFailed(); | |
| 726 | |
| 727 SetDecodedSize(width, height); | |
| 728 return true; | |
| 729 } | |
| 730 | |
| 731 void JPEGImageDecoder::OnSetData(SegmentReader* data) { | |
| 732 if (reader_) | |
| 733 reader_->SetData(data); | |
| 734 } | |
| 735 | |
| 736 void JPEGImageDecoder::SetDecodedSize(unsigned width, unsigned height) { | |
| 737 decoded_size_ = IntSize(width, height); | |
| 738 } | |
| 739 | |
| 740 IntSize JPEGImageDecoder::DecodedYUVSize(int component) const { | |
| 741 DCHECK_GE(component, 0); | |
| 742 DCHECK_LE(component, 2); | |
| 743 DCHECK(reader_); | |
| 744 const jpeg_decompress_struct* info = reader_->Info(); | |
| 745 | |
| 746 DCHECK_EQ(info->out_color_space, JCS_YCbCr); | |
| 747 return ComputeYUVSize(info, component); | |
| 748 } | |
| 749 | |
| 750 size_t JPEGImageDecoder::DecodedYUVWidthBytes(int component) const { | |
| 751 DCHECK_GE(component, 0); | |
| 752 DCHECK_LE(component, 2); | |
| 753 DCHECK(reader_); | |
| 754 const jpeg_decompress_struct* info = reader_->Info(); | |
| 755 | |
| 756 DCHECK_EQ(info->out_color_space, JCS_YCbCr); | |
| 757 return ComputeYUVWidthBytes(info, component); | |
| 758 } | |
| 759 | |
| 760 unsigned JPEGImageDecoder::DesiredScaleNumerator() const { | |
| 761 size_t original_bytes = Size().Width() * Size().Height() * 4; | |
| 762 | |
| 763 if (original_bytes <= max_decoded_bytes_) | |
| 764 return scaleDenominator; | |
| 765 | |
| 766 // Downsample according to the maximum decoded size. | |
| 767 unsigned scale_numerator = static_cast<unsigned>(floor(sqrt( | |
| 768 // MSVC needs explicit parameter type for sqrt(). | |
| 769 static_cast<float>(max_decoded_bytes_ * scaleDenominator * | |
| 770 scaleDenominator / original_bytes)))); | |
| 771 | |
| 772 return scale_numerator; | |
| 773 } | |
| 774 | |
| 775 bool JPEGImageDecoder::CanDecodeToYUV() { | |
| 776 // Calling IsSizeAvailable() ensures the reader is created and the output | |
| 777 // color space is set. | |
| 778 return IsSizeAvailable() && reader_->Info()->out_color_space == JCS_YCbCr; | |
| 779 } | |
| 780 | |
| 781 bool JPEGImageDecoder::DecodeToYUV() { | |
| 782 if (!HasImagePlanes()) | |
| 783 return false; | |
| 784 | |
| 785 PlatformInstrumentation::WillDecodeImage("JPEG"); | |
| 786 Decode(false); | |
| 787 PlatformInstrumentation::DidDecodeImage(); | |
| 788 return !Failed(); | |
| 789 } | |
| 790 | |
| 791 void JPEGImageDecoder::SetImagePlanes( | |
| 792 std::unique_ptr<ImagePlanes> image_planes) { | |
| 793 image_planes_ = std::move(image_planes); | |
| 794 } | |
| 795 | |
| 796 // At the moment we support only JCS_RGB and JCS_CMYK values of the | |
| 797 // J_COLOR_SPACE enum. | |
| 798 // If you need a specific implementation for other J_COLOR_SPACE values, | |
| 799 // please add a full template specialization for this function below. | |
| 800 template <J_COLOR_SPACE colorSpace> | |
| 801 void SetPixel(ImageFrame::PixelData*, JSAMPARRAY samples, int column) = delete; | |
| 802 | |
| 803 // Used only for debugging with libjpeg (instead of libjpeg-turbo). | |
| 804 template <> | |
| 805 void SetPixel<JCS_RGB>(ImageFrame::PixelData* pixel, | |
| 806 JSAMPARRAY samples, | |
| 807 int column) { | |
| 808 JSAMPLE* jsample = *samples + column * 3; | |
| 809 ImageFrame::SetRGBARaw(pixel, jsample[0], jsample[1], jsample[2], 255); | |
| 810 } | |
| 811 | |
| 812 template <> | |
| 813 void SetPixel<JCS_CMYK>(ImageFrame::PixelData* pixel, | |
| 814 JSAMPARRAY samples, | |
| 815 int column) { | |
| 816 JSAMPLE* jsample = *samples + column * 4; | |
| 817 | |
| 818 // Source is 'Inverted CMYK', output is RGB. | |
| 819 // See: http://www.easyrgb.com/math.php?MATH=M12#text12 | |
| 820 // Or: http://www.ilkeratalay.com/colorspacesfaq.php#rgb | |
| 821 // From CMYK to CMY: | |
| 822 // X = X * (1 - K ) + K [for X = C, M, or Y] | |
| 823 // Thus, from Inverted CMYK to CMY is: | |
| 824 // X = (1-iX) * (1 - (1-iK)) + (1-iK) => 1 - iX*iK | |
| 825 // From CMY (0..1) to RGB (0..1): | |
| 826 // R = 1 - C => 1 - (1 - iC*iK) => iC*iK [G and B similar] | |
| 827 unsigned k = jsample[3]; | |
| 828 ImageFrame::SetRGBARaw(pixel, jsample[0] * k / 255, jsample[1] * k / 255, | |
| 829 jsample[2] * k / 255, 255); | |
| 830 } | |
| 831 | |
| 832 // Used only for JCS_CMYK and JCS_RGB output. Note that JCS_RGB is used only | |
| 833 // for debugging with libjpeg (instead of libjpeg-turbo). | |
| 834 template <J_COLOR_SPACE colorSpace> | |
| 835 bool OutputRows(JPEGImageReader* reader, ImageFrame& buffer) { | |
| 836 JSAMPARRAY samples = reader->Samples(); | |
| 837 jpeg_decompress_struct* info = reader->Info(); | |
| 838 int width = info->output_width; | |
| 839 | |
| 840 while (info->output_scanline < info->output_height) { | |
| 841 // jpeg_read_scanlines will increase the scanline counter, so we | |
| 842 // save the scanline before calling it. | |
| 843 int y = info->output_scanline; | |
| 844 // Request one scanline: returns 0 or 1 scanlines. | |
| 845 if (jpeg_read_scanlines(info, samples, 1) != 1) | |
| 846 return false; | |
| 847 | |
| 848 ImageFrame::PixelData* pixel = buffer.GetAddr(0, y); | |
| 849 for (int x = 0; x < width; ++pixel, ++x) | |
| 850 SetPixel<colorSpace>(pixel, samples, x); | |
| 851 | |
| 852 SkColorSpaceXform* xform = reader->Decoder()->ColorTransform(); | |
| 853 if (JCS_RGB == colorSpace && xform) { | |
| 854 ImageFrame::PixelData* row = buffer.GetAddr(0, y); | |
| 855 xform->apply(XformColorFormat(), row, XformColorFormat(), row, width, | |
| 856 kOpaque_SkAlphaType); | |
| 857 } | |
| 858 } | |
| 859 | |
| 860 buffer.SetPixelsChanged(true); | |
| 861 return true; | |
| 862 } | |
| 863 | |
| 864 static bool OutputRawData(JPEGImageReader* reader, ImagePlanes* image_planes) { | |
| 865 JSAMPARRAY samples = reader->Samples(); | |
| 866 jpeg_decompress_struct* info = reader->Info(); | |
| 867 | |
| 868 JSAMPARRAY bufferraw[3]; | |
| 869 JSAMPROW bufferraw2[32]; | |
| 870 bufferraw[0] = &bufferraw2[0]; // Y channel rows (8 or 16) | |
| 871 bufferraw[1] = &bufferraw2[16]; // U channel rows (8) | |
| 872 bufferraw[2] = &bufferraw2[24]; // V channel rows (8) | |
| 873 int y_height = info->output_height; | |
| 874 int v = info->comp_info[0].v_samp_factor; | |
| 875 IntSize uv_size = reader->UvSize(); | |
| 876 int uv_height = uv_size.Height(); | |
| 877 JSAMPROW output_y = static_cast<JSAMPROW>(image_planes->Plane(0)); | |
| 878 JSAMPROW output_u = static_cast<JSAMPROW>(image_planes->Plane(1)); | |
| 879 JSAMPROW output_v = static_cast<JSAMPROW>(image_planes->Plane(2)); | |
| 880 size_t row_bytes_y = image_planes->RowBytes(0); | |
| 881 size_t row_bytes_u = image_planes->RowBytes(1); | |
| 882 size_t row_bytes_v = image_planes->RowBytes(2); | |
| 883 | |
| 884 // Request 8 or 16 scanlines: returns 0 or more scanlines. | |
| 885 int y_scanlines_to_read = DCTSIZE * v; | |
| 886 JSAMPROW dummy_row = *samples; | |
| 887 while (info->output_scanline < info->output_height) { | |
| 888 // Assign 8 or 16 rows of memory to read the Y channel. | |
| 889 for (int i = 0; i < y_scanlines_to_read; ++i) { | |
| 890 int scanline = info->output_scanline + i; | |
| 891 if (scanline < y_height) { | |
| 892 bufferraw2[i] = &output_y[scanline * row_bytes_y]; | |
| 893 } else { | |
| 894 bufferraw2[i] = dummy_row; | |
| 895 } | |
| 896 } | |
| 897 | |
| 898 // Assign 8 rows of memory to read the U and V channels. | |
| 899 int scaled_scanline = info->output_scanline / v; | |
| 900 for (int i = 0; i < 8; ++i) { | |
| 901 int scanline = scaled_scanline + i; | |
| 902 if (scanline < uv_height) { | |
| 903 bufferraw2[16 + i] = &output_u[scanline * row_bytes_u]; | |
| 904 bufferraw2[24 + i] = &output_v[scanline * row_bytes_v]; | |
| 905 } else { | |
| 906 bufferraw2[16 + i] = dummy_row; | |
| 907 bufferraw2[24 + i] = dummy_row; | |
| 908 } | |
| 909 } | |
| 910 | |
| 911 JDIMENSION scanlines_read = | |
| 912 jpeg_read_raw_data(info, bufferraw, y_scanlines_to_read); | |
| 913 if (!scanlines_read) | |
| 914 return false; | |
| 915 } | |
| 916 | |
| 917 info->output_scanline = std::min(info->output_scanline, info->output_height); | |
| 918 return true; | |
| 919 } | |
| 920 | |
| 921 bool JPEGImageDecoder::OutputScanlines() { | |
| 922 if (HasImagePlanes()) | |
| 923 return OutputRawData(reader_.get(), image_planes_.get()); | |
| 924 | |
| 925 if (frame_buffer_cache_.IsEmpty()) | |
| 926 return false; | |
| 927 | |
| 928 jpeg_decompress_struct* info = reader_->Info(); | |
| 929 | |
| 930 // Initialize the framebuffer if needed. | |
| 931 ImageFrame& buffer = frame_buffer_cache_[0]; | |
| 932 if (buffer.GetStatus() == ImageFrame::kFrameEmpty) { | |
| 933 DCHECK_EQ(info->output_width, | |
| 934 static_cast<JDIMENSION>(decoded_size_.Width())); | |
| 935 DCHECK_EQ(info->output_height, | |
| 936 static_cast<JDIMENSION>(decoded_size_.Height())); | |
| 937 | |
| 938 if (!buffer.AllocatePixelData(info->output_width, info->output_height, | |
| 939 ColorSpaceForSkImages())) | |
| 940 return SetFailed(); | |
| 941 | |
| 942 buffer.ZeroFillPixelData(); | |
| 943 // The buffer is transparent outside the decoded area while the image is | |
| 944 // loading. The image will be marked fully opaque in Complete(). | |
| 945 buffer.SetStatus(ImageFrame::kFramePartial); | |
| 946 buffer.SetHasAlpha(true); | |
| 947 | |
| 948 // For JPEGs, the frame always fills the entire image. | |
| 949 buffer.SetOriginalFrameRect(IntRect(IntPoint(), Size())); | |
| 950 } | |
| 951 | |
| 952 #if defined(TURBO_JPEG_RGB_SWIZZLE) | |
| 953 if (turboSwizzled(info->out_color_space)) { | |
| 954 while (info->output_scanline < info->output_height) { | |
| 955 unsigned char* row = reinterpret_cast_ptr<unsigned char*>( | |
| 956 buffer.GetAddr(0, info->output_scanline)); | |
| 957 if (jpeg_read_scanlines(info, &row, 1) != 1) | |
| 958 return false; | |
| 959 | |
| 960 SkColorSpaceXform* xform = ColorTransform(); | |
| 961 if (xform) { | |
| 962 xform->apply(XformColorFormat(), row, XformColorFormat(), row, | |
| 963 info->output_width, kOpaque_SkAlphaType); | |
| 964 } | |
| 965 } | |
| 966 buffer.SetPixelsChanged(true); | |
| 967 return true; | |
| 968 } | |
| 969 #endif | |
| 970 | |
| 971 switch (info->out_color_space) { | |
| 972 case JCS_RGB: | |
| 973 return OutputRows<JCS_RGB>(reader_.get(), buffer); | |
| 974 case JCS_CMYK: | |
| 975 return OutputRows<JCS_CMYK>(reader_.get(), buffer); | |
| 976 default: | |
| 977 NOTREACHED(); | |
| 978 } | |
| 979 | |
| 980 return SetFailed(); | |
| 981 } | |
| 982 | |
| 983 void JPEGImageDecoder::Complete() { | |
| 984 if (frame_buffer_cache_.IsEmpty()) | |
| 985 return; | |
| 986 | |
| 987 frame_buffer_cache_[0].SetHasAlpha(false); | |
| 988 frame_buffer_cache_[0].SetStatus(ImageFrame::kFrameComplete); | |
| 989 } | |
| 990 | |
| 991 inline bool IsComplete(const JPEGImageDecoder* decoder, bool only_size) { | |
| 992 if (decoder->HasImagePlanes() && !only_size) | |
| 993 return true; | |
| 994 | |
| 995 return decoder->FrameIsDecodedAtIndex(0); | |
| 996 } | |
| 997 | |
| 998 void JPEGImageDecoder::Decode(bool only_size) { | |
| 999 if (Failed()) | |
| 1000 return; | |
| 1001 | |
| 1002 if (!reader_) { | |
| 1003 reader_ = WTF::MakeUnique<JPEGImageReader>(this); | |
| 1004 reader_->SetData(data_.Get()); | |
| 1005 } | |
| 1006 | |
| 1007 // If we couldn't decode the image but have received all the data, decoding | |
| 1008 // has failed. | |
| 1009 if (!reader_->Decode(only_size) && IsAllDataReceived()) | |
| 1010 SetFailed(); | |
| 1011 | |
| 1012 // If decoding is done or failed, we don't need the JPEGImageReader anymore. | |
| 1013 if (IsComplete(this, only_size) || Failed()) | |
| 1014 reader_.reset(); | |
| 1015 } | |
| 1016 | |
| 1017 } // namespace blink | |
| OLD | NEW |