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

Side by Side Diff: Source/core/platform/image-decoders/gif/GIFImageReader.cpp

Issue 15350006: Decode GIF image frames on demand. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Rebased Created 7 years, 6 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
OLDNEW
1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK ***** 2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * 4 *
5 * The contents of this file are subject to the Mozilla Public License Version 5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with 6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at 7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/ 8 * http://www.mozilla.org/MPL/
9 * 9 *
10 * Software distributed under the License is distributed on an "AS IS" basis, 10 * Software distributed under the License is distributed on an "AS IS" basis,
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after
344 344
345 // If this frame is data complete then the previous loop must have completel y decoded all LZW blocks. 345 // If this frame is data complete then the previous loop must have completel y decoded all LZW blocks.
346 // There will be no more decoding for this frame so it's time to cleanup. 346 // There will be no more decoding for this frame so it's time to cleanup.
347 if (isComplete()) { 347 if (isComplete()) {
348 *frameDecoded = true; 348 *frameDecoded = true;
349 m_lzwContext.clear(); 349 m_lzwContext.clear();
350 } 350 }
351 return true; 351 return true;
352 } 352 }
353 353
354 // Decode all frames before haltAtFrame. 354 // Decode a frame.
355 // This method uses GIFFrameContext:decode() to decode each frame; decoding erro r is reported to client as a critical failure. 355 // This method uses GIFFrameContext:decode() to decode the frame; decoding error is reported to client as a critical failure.
356 // Return true if decoding has progressed. Return false if an error has occurred . 356 // Return true if decoding has progressed. Return false if an error has occurred .
357 bool GIFImageReader::decode(GIFImageDecoder::GIFQuery query, unsigned haltAtFram e) 357 bool GIFImageReader::decode(size_t frameIndex)
358 {
359 bool frameDecoded = false;
360 GIFFrameContext* currentFrame = m_frames[frameIndex].get();
361
362 return currentFrame->decode(data(0), m_data->size(), m_client, &frameDecoded )
363 && (!frameDecoded || m_client->frameComplete(frameIndex));
364 }
365
366 bool GIFImageReader::parse(GIFImageDecoder::GIFParseQuery query)
358 { 367 {
359 ASSERT(m_bytesRead <= m_data->size()); 368 ASSERT(m_bytesRead <= m_data->size());
360 369
361 if (!parse(m_bytesRead, m_data->size() - m_bytesRead, query == GIFImageDecod er::GIFSizeQuery)) 370 return parseData(m_bytesRead, m_data->size() - m_bytesRead, query);
362 return false;
363
364 if (query != GIFImageDecoder::GIFFullQuery)
365 return true;
366
367 while (m_currentDecodingFrame < std::min(m_frames.size(), static_cast<size_t >(haltAtFrame))) {
368 bool frameDecoded = false;
369 GIFFrameContext* currentFrame = m_frames[m_currentDecodingFrame].get();
370
371 if (!currentFrame->decode(data(0), m_data->size(), m_client, &frameDecod ed))
372 return false;
373
374 // We need more data to continue decoding.
375 if (!frameDecoded)
376 break;
377
378 if (!m_client->frameComplete(m_currentDecodingFrame, currentFrame->delay Time, currentFrame->disposalMethod))
379 return false;
380 ++m_currentDecodingFrame;
381 }
382
383 // All frames decoded.
384 if (m_currentDecodingFrame == m_frames.size() && m_parseCompleted)
385 m_client->gifComplete();
386 return true;
387 } 371 }
388 372
389 // Parse incoming GIF data stream into internal data structures. 373 // Parse incoming GIF data stream into internal data structures.
390 // Return true if parsing has progressed or there is not enough data. 374 // Return true if parsing has progressed or there is not enough data.
391 // Return false if a fatal error is encountered. 375 // Return false if a fatal error is encountered.
392 bool GIFImageReader::parse(size_t dataPosition, size_t len, bool parseSizeOnly) 376 bool GIFImageReader::parseData(size_t dataPosition, size_t len, GIFImageDecoder: :GIFParseQuery query)
393 { 377 {
394 if (!len) { 378 if (!len) {
395 // No new data has come in since the last call, just ignore this call. 379 // No new data has come in since the last call, just ignore this call.
396 return true; 380 return true;
397 } 381 }
398 382
399 if (len < m_bytesToConsume) 383 if (len < m_bytesToConsume)
400 return true; 384 return true;
401 385
402 // This loop reads as many components from |m_data| as possible. 386 // This loop reads as many components from |m_data| as possible.
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
443 // individual images can be smaller than the screen size and located with an origin anywhere 427 // individual images can be smaller than the screen size and located with an origin anywhere
444 // within the screen. 428 // within the screen.
445 m_screenWidth = GETINT16(currentComponent); 429 m_screenWidth = GETINT16(currentComponent);
446 m_screenHeight = GETINT16(currentComponent + 2); 430 m_screenHeight = GETINT16(currentComponent + 2);
447 431
448 // CALLBACK: Inform the decoderplugin of our size. 432 // CALLBACK: Inform the decoderplugin of our size.
449 // Note: A subsequent frame might have dimensions larger than the "s creen" dimensions. 433 // Note: A subsequent frame might have dimensions larger than the "s creen" dimensions.
450 if (m_client && !m_client->setSize(m_screenWidth, m_screenHeight)) 434 if (m_client && !m_client->setSize(m_screenWidth, m_screenHeight))
451 return false; 435 return false;
452 436
453 m_screenBgcolor = currentComponent[5];
454 m_globalColormapSize = 2 << (currentComponent[4] & 0x07); 437 m_globalColormapSize = 2 << (currentComponent[4] & 0x07);
455 438
456 if ((currentComponent[4] & 0x80) && m_globalColormapSize > 0) { /* g lobal map */ 439 if ((currentComponent[4] & 0x80) && m_globalColormapSize > 0) { /* g lobal map */
457 // Get the global colormap 440 // Get the global colormap
458 const size_t globalColormapBytes = 3 * m_globalColormapSize; 441 const size_t globalColormapBytes = 3 * m_globalColormapSize;
459 m_globalColormapPosition = dataPosition; 442 m_globalColormapPosition = dataPosition;
460 443
461 if (len < globalColormapBytes) { 444 if (len < globalColormapBytes) {
462 // Wait until we have enough bytes to consume the entire col ormap at once. 445 // Wait until we have enough bytes to consume the entire col ormap at once.
463 GETN(globalColormapBytes, GIFGlobalColormap); 446 GETN(globalColormapBytes, GIFGlobalColormap);
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
668 } 651 }
669 652
670 // Work around more broken GIF files that have zero image width or h eight 653 // Work around more broken GIF files that have zero image width or h eight
671 if (!height || !width) { 654 if (!height || !width) {
672 height = m_screenHeight; 655 height = m_screenHeight;
673 width = m_screenWidth; 656 width = m_screenWidth;
674 if (!height || !width) 657 if (!height || !width)
675 return false; 658 return false;
676 } 659 }
677 660
678 if (parseSizeOnly) { 661 if (query == GIFImageDecoder::GIFSizeQuery) {
679 // The decoder needs to stop. Hand back the number of bytes we c onsumed from 662 // The decoder needs to stop. Hand back the number of bytes we c onsumed from
680 // buffer minus 9 (the amount we consumed to read the header). 663 // buffer minus 9 (the amount we consumed to read the header).
681 setRemainingBytes(len + 9); 664 setRemainingBytes(len + 9);
682 GETN(9, GIFImageHeader); 665 GETN(9, GIFImageHeader);
683 return true; 666 return true;
684 } 667 }
685 668
686 addFrameIfNecessary(); 669 addFrameIfNecessary();
687 GIFFrameContext* currentFrame = m_frames.last().get(); 670 GIFFrameContext* currentFrame = m_frames.last().get();
688 671
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
815 rowPosition = 0; 798 rowPosition = 0;
816 rowsRemaining = m_frameContext->height; 799 rowsRemaining = m_frameContext->height;
817 800
818 // Clearing the whole suffix table lets us be more tolerant of bad data. 801 // Clearing the whole suffix table lets us be more tolerant of bad data.
819 suffix.fill(0); 802 suffix.fill(0);
820 for (int i = 0; i < clearCode; i++) 803 for (int i = 0; i < clearCode; i++)
821 suffix[i] = i; 804 suffix[i] = i;
822 stackp = 0; 805 stackp = 0;
823 return true; 806 return true;
824 } 807 }
OLDNEW
« no previous file with comments | « Source/core/platform/image-decoders/gif/GIFImageReader.h ('k') | Source/core/platform/image-decoders/ico/ICOImageDecoder.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698