/* * Read enough of the stream to initialize the SkGifCodec. * Returns a bool representing success or failure. * * @param codecOut * If it returned true, and codecOut was not nullptr, * codecOut will be set to a new SkGifCodec. * * @param gifOut * If it returned true, and codecOut was nullptr, * gifOut must be non-nullptr and gifOut will be set to a new * GifFileType pointer. * * @param stream * Deleted on failure. * codecOut will take ownership of it in the case where we created a codec. * Ownership is unchanged when we returned a gifOut. * */ bool SkGifCodec::ReadHeader(SkStream* stream, SkCodec** codecOut, GifFileType** gifOut) { SkAutoTDelete<SkStream> streamDeleter(stream); // Read gif header, logical screen descriptor, and global color table SkAutoTCallVProc<GifFileType, CloseGif> gif(open_gif(stream)); if (nullptr == gif) { gif_error("DGifOpen failed.\n"); return false; } // Read through gif extensions to get to the image data. Set the // transparent index based on the extension data. uint32_t transIndex; SkCodec::Result result = ReadUpToFirstImage(gif, &transIndex); if (kSuccess != result){ return false; } // Read the image descriptor if (GIF_ERROR == DGifGetImageDesc(gif)) { return false; } // If reading the image descriptor is successful, the image count will be // incremented. SkASSERT(gif->ImageCount >= 1); if (nullptr != codecOut) { SkISize size; SkIRect frameRect; if (!GetDimensions(gif, &size, &frameRect)) { gif_error("Invalid gif size.\n"); return false; } bool frameIsSubset = (size != frameRect.size()); // Determine the encoded alpha type. The transIndex might be valid if it less // than 256. We are not certain that the index is valid until we process the color // table, since some gifs have color tables with less than 256 colors. If // there might be a valid transparent index, we must indicate that the image has // alpha. // In the case where we must support alpha, we indicate kBinary, since every // pixel will either be fully opaque or fully transparent. SkEncodedInfo::Alpha alpha = (transIndex < 256) ? SkEncodedInfo::kBinary_Alpha : SkEncodedInfo::kOpaque_Alpha; // Return the codec // Use kPalette since Gifs are encoded with a color table. // Use 8-bits per component, since this is the output we get from giflib. // FIXME: Gifs can actually be encoded with 4-bits per pixel. Can we support this? SkEncodedInfo info = SkEncodedInfo::Make(SkEncodedInfo::kPalette_Color, alpha, 8); *codecOut = new SkGifCodec(size.width(), size.height(), info, streamDeleter.release(), gif.release(), transIndex, frameRect, frameIsSubset); } else { SkASSERT(nullptr != gifOut); streamDeleter.release(); *gifOut = gif.release(); } return true; }
/* * Read enough of the stream to initialize the SkGifCodec. * Returns a bool representing success or failure. * * @param codecOut * If it returned true, and codecOut was not nullptr, * codecOut will be set to a new SkGifCodec. * * @param gifOut * If it returned true, and codecOut was nullptr, * gifOut must be non-nullptr and gifOut will be set to a new * GifFileType pointer. * * @param stream * Deleted on failure. * codecOut will take ownership of it in the case where we created a codec. * Ownership is unchanged when we returned a gifOut. * */ bool SkGifCodec::ReadHeader(SkStream* stream, SkCodec** codecOut, GifFileType** gifOut) { SkAutoTDelete<SkStream> streamDeleter(stream); // Read gif header, logical screen descriptor, and global color table SkAutoTCallVProc<GifFileType, CloseGif> gif(open_gif(stream)); if (nullptr == gif) { gif_error("DGifOpen failed.\n"); return false; } // Read through gif extensions to get to the image data. Set the // transparent index based on the extension data. uint32_t transIndex; SkCodec::Result result = ReadUpToFirstImage(gif, &transIndex); if (kSuccess != result){ return false; } // Read the image descriptor if (GIF_ERROR == DGifGetImageDesc(gif)) { return false; } // If reading the image descriptor is successful, the image count will be // incremented. SkASSERT(gif->ImageCount >= 1); if (nullptr != codecOut) { SkISize size; SkIRect frameRect; if (!GetDimensions(gif, &size, &frameRect)) { gif_error("Invalid gif size.\n"); return false; } bool frameIsSubset = (size != frameRect.size()); // Determine the recommended alpha type. The transIndex might be valid if it less // than 256. We are not certain that the index is valid until we process the color // table, since some gifs have color tables with less than 256 colors. If // there might be a valid transparent index, we must indicate that the image has // alpha. // In the case where we must support alpha, we have the option to set the // suggested alpha type to kPremul or kUnpremul. Both are valid since the alpha // component will always be 0xFF or the entire 32-bit pixel will be set to zero. // We prefer kPremul because we support kPremul, and it is more efficient to use // kPremul directly even when kUnpremul is supported. SkAlphaType alphaType = (transIndex < 256) ? kPremul_SkAlphaType : kOpaque_SkAlphaType; // Return the codec // kIndex is the most natural color type for gifs, so we set this as // the default. SkImageInfo imageInfo = SkImageInfo::Make(size.width(), size.height(), kIndex_8_SkColorType, alphaType); *codecOut = new SkGifCodec(imageInfo, streamDeleter.detach(), gif.detach(), transIndex, frameRect, frameIsSubset); } else { SkASSERT(nullptr != gifOut); streamDeleter.detach(); *gifOut = gif.detach(); } return true; }