1741143878b23d22cd9cb7b9cba8055179115ce17msarett/* 2741143878b23d22cd9cb7b9cba8055179115ce17msarett * Copyright 2015 Google Inc. 3741143878b23d22cd9cb7b9cba8055179115ce17msarett * 4741143878b23d22cd9cb7b9cba8055179115ce17msarett * Use of this source code is governed by a BSD-style license that can be 5741143878b23d22cd9cb7b9cba8055179115ce17msarett * found in the LICENSE file. 6741143878b23d22cd9cb7b9cba8055179115ce17msarett */ 7741143878b23d22cd9cb7b9cba8055179115ce17msarett 8741143878b23d22cd9cb7b9cba8055179115ce17msarett#include "SkCodec_libbmp.h" 9741143878b23d22cd9cb7b9cba8055179115ce17msarett#include "SkCodecPriv.h" 10741143878b23d22cd9cb7b9cba8055179115ce17msarett#include "SkColorPriv.h" 11741143878b23d22cd9cb7b9cba8055179115ce17msarett#include "SkStream.h" 12741143878b23d22cd9cb7b9cba8055179115ce17msarett 13741143878b23d22cd9cb7b9cba8055179115ce17msarett/* 14741143878b23d22cd9cb7b9cba8055179115ce17msarett * 15741143878b23d22cd9cb7b9cba8055179115ce17msarett * Checks if the conversion between the input image and the requested output 16741143878b23d22cd9cb7b9cba8055179115ce17msarett * image has been implemented 17741143878b23d22cd9cb7b9cba8055179115ce17msarett * 18741143878b23d22cd9cb7b9cba8055179115ce17msarett */ 19741143878b23d22cd9cb7b9cba8055179115ce17msarettstatic bool conversion_possible(const SkImageInfo& dst, 20741143878b23d22cd9cb7b9cba8055179115ce17msarett const SkImageInfo& src) { 21eed039b5ffbdff958053ac80b09451ad6caa1787msarett // Ensure that the profile type is unchanged 22eed039b5ffbdff958053ac80b09451ad6caa1787msarett if (dst.profileType() != src.profileType()) { 23741143878b23d22cd9cb7b9cba8055179115ce17msarett return false; 24741143878b23d22cd9cb7b9cba8055179115ce17msarett } 25eed039b5ffbdff958053ac80b09451ad6caa1787msarett 26438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett // Check for supported alpha types 27438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett if (src.alphaType() != dst.alphaType()) { 28438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett if (kOpaque_SkAlphaType == src.alphaType()) { 29438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett // If the source is opaque, we must decode to opaque 30438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett return false; 31438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett } 32438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett 33438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett // The source is not opaque 34438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett switch (dst.alphaType()) { 35438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett case kPremul_SkAlphaType: 36438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett case kUnpremul_SkAlphaType: 37438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett // The source is not opaque, so either of these is okay 38438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett break; 39438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett default: 40438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett // We cannot decode a non-opaque image to opaque (or unknown) 41438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett return false; 42438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett } 43438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett } 44438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett 45438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett // Check for supported color types 46eed039b5ffbdff958053ac80b09451ad6caa1787msarett switch (dst.colorType()) { 47438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett // Allow output to kN32 from any type of input 48eed039b5ffbdff958053ac80b09451ad6caa1787msarett case kN32_SkColorType: 49438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett return true; 50438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett // Allow output to kIndex_8 from compatible inputs 51438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett case kIndex_8_SkColorType: 52438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett return kIndex_8_SkColorType == src.colorType(); 53eed039b5ffbdff958053ac80b09451ad6caa1787msarett default: 54eed039b5ffbdff958053ac80b09451ad6caa1787msarett return false; 55741143878b23d22cd9cb7b9cba8055179115ce17msarett } 56741143878b23d22cd9cb7b9cba8055179115ce17msarett} 57741143878b23d22cd9cb7b9cba8055179115ce17msarett 58741143878b23d22cd9cb7b9cba8055179115ce17msarett/* 59741143878b23d22cd9cb7b9cba8055179115ce17msarett * 60741143878b23d22cd9cb7b9cba8055179115ce17msarett * Defines the version and type of the second bitmap header 61741143878b23d22cd9cb7b9cba8055179115ce17msarett * 62741143878b23d22cd9cb7b9cba8055179115ce17msarett */ 63741143878b23d22cd9cb7b9cba8055179115ce17msarettenum BitmapHeaderType { 64741143878b23d22cd9cb7b9cba8055179115ce17msarett kInfoV1_BitmapHeaderType, 65741143878b23d22cd9cb7b9cba8055179115ce17msarett kInfoV2_BitmapHeaderType, 66741143878b23d22cd9cb7b9cba8055179115ce17msarett kInfoV3_BitmapHeaderType, 67741143878b23d22cd9cb7b9cba8055179115ce17msarett kInfoV4_BitmapHeaderType, 68741143878b23d22cd9cb7b9cba8055179115ce17msarett kInfoV5_BitmapHeaderType, 69741143878b23d22cd9cb7b9cba8055179115ce17msarett kOS2V1_BitmapHeaderType, 70741143878b23d22cd9cb7b9cba8055179115ce17msarett kOS2VX_BitmapHeaderType, 71741143878b23d22cd9cb7b9cba8055179115ce17msarett kUnknown_BitmapHeaderType 72741143878b23d22cd9cb7b9cba8055179115ce17msarett}; 73741143878b23d22cd9cb7b9cba8055179115ce17msarett 74741143878b23d22cd9cb7b9cba8055179115ce17msarett/* 75741143878b23d22cd9cb7b9cba8055179115ce17msarett * 76741143878b23d22cd9cb7b9cba8055179115ce17msarett * Possible bitmap compression types 77741143878b23d22cd9cb7b9cba8055179115ce17msarett * 78741143878b23d22cd9cb7b9cba8055179115ce17msarett */ 79741143878b23d22cd9cb7b9cba8055179115ce17msarettenum BitmapCompressionMethod { 80741143878b23d22cd9cb7b9cba8055179115ce17msarett kNone_BitmapCompressionMethod = 0, 81741143878b23d22cd9cb7b9cba8055179115ce17msarett k8BitRLE_BitmapCompressionMethod = 1, 82741143878b23d22cd9cb7b9cba8055179115ce17msarett k4BitRLE_BitmapCompressionMethod = 2, 83741143878b23d22cd9cb7b9cba8055179115ce17msarett kBitMasks_BitmapCompressionMethod = 3, 84741143878b23d22cd9cb7b9cba8055179115ce17msarett kJpeg_BitmapCompressionMethod = 4, 85741143878b23d22cd9cb7b9cba8055179115ce17msarett kPng_BitmapCompressionMethod = 5, 86741143878b23d22cd9cb7b9cba8055179115ce17msarett kAlphaBitMasks_BitmapCompressionMethod = 6, 87741143878b23d22cd9cb7b9cba8055179115ce17msarett kCMYK_BitmapCompressionMethod = 11, 88741143878b23d22cd9cb7b9cba8055179115ce17msarett kCMYK8BitRLE_BitmapCompressionMethod = 12, 89741143878b23d22cd9cb7b9cba8055179115ce17msarett kCMYK4BitRLE_BitmapCompressionMethod = 13 90741143878b23d22cd9cb7b9cba8055179115ce17msarett}; 91741143878b23d22cd9cb7b9cba8055179115ce17msarett 92741143878b23d22cd9cb7b9cba8055179115ce17msarett/* 93741143878b23d22cd9cb7b9cba8055179115ce17msarett * 94741143878b23d22cd9cb7b9cba8055179115ce17msarett * Checks the start of the stream to see if the image is a bitmap 95741143878b23d22cd9cb7b9cba8055179115ce17msarett * 96741143878b23d22cd9cb7b9cba8055179115ce17msarett */ 97741143878b23d22cd9cb7b9cba8055179115ce17msarettbool SkBmpCodec::IsBmp(SkStream* stream) { 98741143878b23d22cd9cb7b9cba8055179115ce17msarett // TODO: Support "IC", "PT", "CI", "CP", "BA" 99741143878b23d22cd9cb7b9cba8055179115ce17msarett const char bmpSig[] = { 'B', 'M' }; 100741143878b23d22cd9cb7b9cba8055179115ce17msarett char buffer[sizeof(bmpSig)]; 101741143878b23d22cd9cb7b9cba8055179115ce17msarett return stream->read(buffer, sizeof(bmpSig)) == sizeof(bmpSig) && 102741143878b23d22cd9cb7b9cba8055179115ce17msarett !memcmp(buffer, bmpSig, sizeof(bmpSig)); 103741143878b23d22cd9cb7b9cba8055179115ce17msarett} 104741143878b23d22cd9cb7b9cba8055179115ce17msarett 105741143878b23d22cd9cb7b9cba8055179115ce17msarett/* 106741143878b23d22cd9cb7b9cba8055179115ce17msarett * 107741143878b23d22cd9cb7b9cba8055179115ce17msarett * Assumes IsBmp was called and returned true 1089bde918754bc292469d801f156f3b626eb3db780msarett * Creates a bmp decoder 109741143878b23d22cd9cb7b9cba8055179115ce17msarett * Reads enough of the stream to determine the image format 110741143878b23d22cd9cb7b9cba8055179115ce17msarett * 111741143878b23d22cd9cb7b9cba8055179115ce17msarett */ 112741143878b23d22cd9cb7b9cba8055179115ce17msarettSkCodec* SkBmpCodec::NewFromStream(SkStream* stream) { 1139bde918754bc292469d801f156f3b626eb3db780msarett return SkBmpCodec::NewFromStream(stream, false); 1149bde918754bc292469d801f156f3b626eb3db780msarett} 1159bde918754bc292469d801f156f3b626eb3db780msarett 1169bde918754bc292469d801f156f3b626eb3db780msarett/* 1179bde918754bc292469d801f156f3b626eb3db780msarett * 1189bde918754bc292469d801f156f3b626eb3db780msarett * Creates a bmp decoder for a bmp embedded in ico 1199bde918754bc292469d801f156f3b626eb3db780msarett * Reads enough of the stream to determine the image format 1209bde918754bc292469d801f156f3b626eb3db780msarett * 1219bde918754bc292469d801f156f3b626eb3db780msarett */ 1229bde918754bc292469d801f156f3b626eb3db780msarettSkCodec* SkBmpCodec::NewFromIco(SkStream* stream) { 1239bde918754bc292469d801f156f3b626eb3db780msarett return SkBmpCodec::NewFromStream(stream, true); 1249bde918754bc292469d801f156f3b626eb3db780msarett} 1259bde918754bc292469d801f156f3b626eb3db780msarett 1269bde918754bc292469d801f156f3b626eb3db780msarett/* 1279bde918754bc292469d801f156f3b626eb3db780msarett * 12879e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo * Read enough of the stream to initialize the SkBmpCodec. Returns a bool 12979e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo * representing success or failure. If it returned true, and codecOut was 13079e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo * not NULL, it will be set to a new SkBmpCodec. 1310a7e69cb9b4e3929d659891d152a2c0b59bff4e0scroggo * Does *not* take ownership of the passed in SkStream. 1329bde918754bc292469d801f156f3b626eb3db780msarett * 1339bde918754bc292469d801f156f3b626eb3db780msarett */ 13479e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggobool SkBmpCodec::ReadHeader(SkStream* stream, bool isIco, SkCodec** codecOut) { 135741143878b23d22cd9cb7b9cba8055179115ce17msarett // Header size constants 136741143878b23d22cd9cb7b9cba8055179115ce17msarett static const uint32_t kBmpHeaderBytes = 14; 137741143878b23d22cd9cb7b9cba8055179115ce17msarett static const uint32_t kBmpHeaderBytesPlusFour = kBmpHeaderBytes + 4; 138741143878b23d22cd9cb7b9cba8055179115ce17msarett static const uint32_t kBmpOS2V1Bytes = 12; 139741143878b23d22cd9cb7b9cba8055179115ce17msarett static const uint32_t kBmpOS2V2Bytes = 64; 140741143878b23d22cd9cb7b9cba8055179115ce17msarett static const uint32_t kBmpInfoBaseBytes = 16; 141741143878b23d22cd9cb7b9cba8055179115ce17msarett static const uint32_t kBmpInfoV1Bytes = 40; 142741143878b23d22cd9cb7b9cba8055179115ce17msarett static const uint32_t kBmpInfoV2Bytes = 52; 143741143878b23d22cd9cb7b9cba8055179115ce17msarett static const uint32_t kBmpInfoV3Bytes = 56; 144741143878b23d22cd9cb7b9cba8055179115ce17msarett static const uint32_t kBmpInfoV4Bytes = 108; 145741143878b23d22cd9cb7b9cba8055179115ce17msarett static const uint32_t kBmpInfoV5Bytes = 124; 146741143878b23d22cd9cb7b9cba8055179115ce17msarett static const uint32_t kBmpMaskBytes = 12; 147741143878b23d22cd9cb7b9cba8055179115ce17msarett 1487aa846c6837f527067e7ab5fdeacdbd502696382tomhudson // The total bytes in the bmp file 1499bde918754bc292469d801f156f3b626eb3db780msarett // We only need to use this value for RLE decoding, so we will only 1509bde918754bc292469d801f156f3b626eb3db780msarett // check that it is valid in the RLE case. 1519bde918754bc292469d801f156f3b626eb3db780msarett uint32_t totalBytes; 1527aa846c6837f527067e7ab5fdeacdbd502696382tomhudson // The offset from the start of the file where the pixel data begins 1539bde918754bc292469d801f156f3b626eb3db780msarett uint32_t offset; 1547aa846c6837f527067e7ab5fdeacdbd502696382tomhudson // The size of the second (info) header in bytes 1559bde918754bc292469d801f156f3b626eb3db780msarett uint32_t infoBytes; 1569bde918754bc292469d801f156f3b626eb3db780msarett 1579bde918754bc292469d801f156f3b626eb3db780msarett // Bmps embedded in Icos skip the first Bmp header 1589bde918754bc292469d801f156f3b626eb3db780msarett if (!isIco) { 1599bde918754bc292469d801f156f3b626eb3db780msarett // Read the first header and the size of the second header 1609bde918754bc292469d801f156f3b626eb3db780msarett SkAutoTDeleteArray<uint8_t> hBuffer( 1619bde918754bc292469d801f156f3b626eb3db780msarett SkNEW_ARRAY(uint8_t, kBmpHeaderBytesPlusFour)); 1629bde918754bc292469d801f156f3b626eb3db780msarett if (stream->read(hBuffer.get(), kBmpHeaderBytesPlusFour) != 1639bde918754bc292469d801f156f3b626eb3db780msarett kBmpHeaderBytesPlusFour) { 164230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Error: unable to read first bitmap header.\n"); 16579e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo return false; 1669bde918754bc292469d801f156f3b626eb3db780msarett } 1679bde918754bc292469d801f156f3b626eb3db780msarett 1689bde918754bc292469d801f156f3b626eb3db780msarett totalBytes = get_int(hBuffer.get(), 2); 1699bde918754bc292469d801f156f3b626eb3db780msarett offset = get_int(hBuffer.get(), 10); 1709bde918754bc292469d801f156f3b626eb3db780msarett if (offset < kBmpHeaderBytes + kBmpOS2V1Bytes) { 171230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Error: invalid starting location for pixel data\n"); 17279e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo return false; 1739bde918754bc292469d801f156f3b626eb3db780msarett } 1749bde918754bc292469d801f156f3b626eb3db780msarett 1759bde918754bc292469d801f156f3b626eb3db780msarett // The size of the second (info) header in bytes 1769bde918754bc292469d801f156f3b626eb3db780msarett // The size is the first field of the second header, so we have already 1779bde918754bc292469d801f156f3b626eb3db780msarett // read the first four infoBytes. 1789bde918754bc292469d801f156f3b626eb3db780msarett infoBytes = get_int(hBuffer.get(), 14); 1799bde918754bc292469d801f156f3b626eb3db780msarett if (infoBytes < kBmpOS2V1Bytes) { 180230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Error: invalid second header size.\n"); 18179e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo return false; 1829bde918754bc292469d801f156f3b626eb3db780msarett } 1839bde918754bc292469d801f156f3b626eb3db780msarett } else { 1849bde918754bc292469d801f156f3b626eb3db780msarett // This value is only used by RLE compression. Bmp in Ico files do not 1859bde918754bc292469d801f156f3b626eb3db780msarett // use RLE. If the compression field is incorrectly signaled as RLE, 1869bde918754bc292469d801f156f3b626eb3db780msarett // we will catch this and signal an error below. 1879bde918754bc292469d801f156f3b626eb3db780msarett totalBytes = 0; 1889bde918754bc292469d801f156f3b626eb3db780msarett 1899bde918754bc292469d801f156f3b626eb3db780msarett // Bmps in Ico cannot specify an offset. We will always assume that 1909bde918754bc292469d801f156f3b626eb3db780msarett // pixel data begins immediately after the color table. This value 1919bde918754bc292469d801f156f3b626eb3db780msarett // will be corrected below. 1929bde918754bc292469d801f156f3b626eb3db780msarett offset = 0; 1939bde918754bc292469d801f156f3b626eb3db780msarett 1949bde918754bc292469d801f156f3b626eb3db780msarett // Read the size of the second header 1959bde918754bc292469d801f156f3b626eb3db780msarett SkAutoTDeleteArray<uint8_t> hBuffer( 1969bde918754bc292469d801f156f3b626eb3db780msarett SkNEW_ARRAY(uint8_t, 4)); 1979bde918754bc292469d801f156f3b626eb3db780msarett if (stream->read(hBuffer.get(), 4) != 4) { 198230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Error: unable to read size of second bitmap header.\n"); 19979e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo return false; 2009bde918754bc292469d801f156f3b626eb3db780msarett } 2019bde918754bc292469d801f156f3b626eb3db780msarett infoBytes = get_int(hBuffer.get(), 0); 2029bde918754bc292469d801f156f3b626eb3db780msarett if (infoBytes < kBmpOS2V1Bytes) { 203230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Error: invalid second header size.\n"); 20479e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo return false; 2059bde918754bc292469d801f156f3b626eb3db780msarett } 2067aa846c6837f527067e7ab5fdeacdbd502696382tomhudson } 2079bde918754bc292469d801f156f3b626eb3db780msarett 2089bde918754bc292469d801f156f3b626eb3db780msarett // We already read the first four bytes of the info header to get the size 209741143878b23d22cd9cb7b9cba8055179115ce17msarett const uint32_t infoBytesRemaining = infoBytes - 4; 210741143878b23d22cd9cb7b9cba8055179115ce17msarett 211741143878b23d22cd9cb7b9cba8055179115ce17msarett // Read the second header 212741143878b23d22cd9cb7b9cba8055179115ce17msarett SkAutoTDeleteArray<uint8_t> iBuffer( 213741143878b23d22cd9cb7b9cba8055179115ce17msarett SkNEW_ARRAY(uint8_t, infoBytesRemaining)); 214741143878b23d22cd9cb7b9cba8055179115ce17msarett if (stream->read(iBuffer.get(), infoBytesRemaining) != infoBytesRemaining) { 215230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Error: unable to read second bitmap header.\n"); 21679e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo return false; 217741143878b23d22cd9cb7b9cba8055179115ce17msarett } 218741143878b23d22cd9cb7b9cba8055179115ce17msarett 219741143878b23d22cd9cb7b9cba8055179115ce17msarett // The number of bits used per pixel in the pixel data 220741143878b23d22cd9cb7b9cba8055179115ce17msarett uint16_t bitsPerPixel; 221741143878b23d22cd9cb7b9cba8055179115ce17msarett 222741143878b23d22cd9cb7b9cba8055179115ce17msarett // The compression method for the pixel data 223741143878b23d22cd9cb7b9cba8055179115ce17msarett uint32_t compression = kNone_BitmapCompressionMethod; 224741143878b23d22cd9cb7b9cba8055179115ce17msarett 225741143878b23d22cd9cb7b9cba8055179115ce17msarett // Number of colors in the color table, defaults to 0 or max (see below) 226741143878b23d22cd9cb7b9cba8055179115ce17msarett uint32_t numColors = 0; 227741143878b23d22cd9cb7b9cba8055179115ce17msarett 228741143878b23d22cd9cb7b9cba8055179115ce17msarett // Bytes per color in the color table, early versions use 3, most use 4 229741143878b23d22cd9cb7b9cba8055179115ce17msarett uint32_t bytesPerColor; 230741143878b23d22cd9cb7b9cba8055179115ce17msarett 231741143878b23d22cd9cb7b9cba8055179115ce17msarett // The image width and height 232741143878b23d22cd9cb7b9cba8055179115ce17msarett int width, height; 233741143878b23d22cd9cb7b9cba8055179115ce17msarett 234741143878b23d22cd9cb7b9cba8055179115ce17msarett // Determine image information depending on second header format 235741143878b23d22cd9cb7b9cba8055179115ce17msarett BitmapHeaderType headerType; 236741143878b23d22cd9cb7b9cba8055179115ce17msarett if (infoBytes >= kBmpInfoBaseBytes) { 237741143878b23d22cd9cb7b9cba8055179115ce17msarett // Check the version of the header 238741143878b23d22cd9cb7b9cba8055179115ce17msarett switch (infoBytes) { 239741143878b23d22cd9cb7b9cba8055179115ce17msarett case kBmpInfoV1Bytes: 240741143878b23d22cd9cb7b9cba8055179115ce17msarett headerType = kInfoV1_BitmapHeaderType; 241741143878b23d22cd9cb7b9cba8055179115ce17msarett break; 242741143878b23d22cd9cb7b9cba8055179115ce17msarett case kBmpInfoV2Bytes: 243741143878b23d22cd9cb7b9cba8055179115ce17msarett headerType = kInfoV2_BitmapHeaderType; 244741143878b23d22cd9cb7b9cba8055179115ce17msarett break; 245741143878b23d22cd9cb7b9cba8055179115ce17msarett case kBmpInfoV3Bytes: 246741143878b23d22cd9cb7b9cba8055179115ce17msarett headerType = kInfoV3_BitmapHeaderType; 247741143878b23d22cd9cb7b9cba8055179115ce17msarett break; 248741143878b23d22cd9cb7b9cba8055179115ce17msarett case kBmpInfoV4Bytes: 249741143878b23d22cd9cb7b9cba8055179115ce17msarett headerType = kInfoV4_BitmapHeaderType; 250741143878b23d22cd9cb7b9cba8055179115ce17msarett break; 251741143878b23d22cd9cb7b9cba8055179115ce17msarett case kBmpInfoV5Bytes: 252741143878b23d22cd9cb7b9cba8055179115ce17msarett headerType = kInfoV5_BitmapHeaderType; 253741143878b23d22cd9cb7b9cba8055179115ce17msarett break; 254741143878b23d22cd9cb7b9cba8055179115ce17msarett case 16: 255741143878b23d22cd9cb7b9cba8055179115ce17msarett case 20: 256741143878b23d22cd9cb7b9cba8055179115ce17msarett case 24: 257741143878b23d22cd9cb7b9cba8055179115ce17msarett case 28: 258741143878b23d22cd9cb7b9cba8055179115ce17msarett case 32: 259741143878b23d22cd9cb7b9cba8055179115ce17msarett case 36: 260741143878b23d22cd9cb7b9cba8055179115ce17msarett case 42: 261741143878b23d22cd9cb7b9cba8055179115ce17msarett case 46: 262741143878b23d22cd9cb7b9cba8055179115ce17msarett case 48: 263741143878b23d22cd9cb7b9cba8055179115ce17msarett case 60: 264741143878b23d22cd9cb7b9cba8055179115ce17msarett case kBmpOS2V2Bytes: 265741143878b23d22cd9cb7b9cba8055179115ce17msarett headerType = kOS2VX_BitmapHeaderType; 266741143878b23d22cd9cb7b9cba8055179115ce17msarett break; 267741143878b23d22cd9cb7b9cba8055179115ce17msarett default: 268741143878b23d22cd9cb7b9cba8055179115ce17msarett // We do not signal an error here because there is the 269741143878b23d22cd9cb7b9cba8055179115ce17msarett // possibility of new or undocumented bmp header types. Most 270741143878b23d22cd9cb7b9cba8055179115ce17msarett // of the newer versions of bmp headers are similar to and 271741143878b23d22cd9cb7b9cba8055179115ce17msarett // build off of the older versions, so we may still be able to 272741143878b23d22cd9cb7b9cba8055179115ce17msarett // decode the bmp. 273230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Warning: unknown bmp header format.\n"); 274741143878b23d22cd9cb7b9cba8055179115ce17msarett headerType = kUnknown_BitmapHeaderType; 275741143878b23d22cd9cb7b9cba8055179115ce17msarett break; 276741143878b23d22cd9cb7b9cba8055179115ce17msarett } 277741143878b23d22cd9cb7b9cba8055179115ce17msarett // We check the size of the header before entering the if statement. 278741143878b23d22cd9cb7b9cba8055179115ce17msarett // We should not reach this point unless the size is large enough for 279741143878b23d22cd9cb7b9cba8055179115ce17msarett // these required fields. 280741143878b23d22cd9cb7b9cba8055179115ce17msarett SkASSERT(infoBytesRemaining >= 12); 281741143878b23d22cd9cb7b9cba8055179115ce17msarett width = get_int(iBuffer.get(), 0); 282741143878b23d22cd9cb7b9cba8055179115ce17msarett height = get_int(iBuffer.get(), 4); 283741143878b23d22cd9cb7b9cba8055179115ce17msarett bitsPerPixel = get_short(iBuffer.get(), 10); 284741143878b23d22cd9cb7b9cba8055179115ce17msarett 285741143878b23d22cd9cb7b9cba8055179115ce17msarett // Some versions do not have these fields, so we check before 286741143878b23d22cd9cb7b9cba8055179115ce17msarett // overwriting the default value. 287741143878b23d22cd9cb7b9cba8055179115ce17msarett if (infoBytesRemaining >= 16) { 288741143878b23d22cd9cb7b9cba8055179115ce17msarett compression = get_int(iBuffer.get(), 12); 289741143878b23d22cd9cb7b9cba8055179115ce17msarett if (infoBytesRemaining >= 32) { 290741143878b23d22cd9cb7b9cba8055179115ce17msarett numColors = get_int(iBuffer.get(), 28); 291741143878b23d22cd9cb7b9cba8055179115ce17msarett } 292741143878b23d22cd9cb7b9cba8055179115ce17msarett } 293741143878b23d22cd9cb7b9cba8055179115ce17msarett 294741143878b23d22cd9cb7b9cba8055179115ce17msarett // All of the headers that reach this point, store color table entries 295741143878b23d22cd9cb7b9cba8055179115ce17msarett // using 4 bytes per pixel. 296741143878b23d22cd9cb7b9cba8055179115ce17msarett bytesPerColor = 4; 297741143878b23d22cd9cb7b9cba8055179115ce17msarett } else if (infoBytes >= kBmpOS2V1Bytes) { 298741143878b23d22cd9cb7b9cba8055179115ce17msarett // The OS2V1 is treated separately because it has a unique format 299741143878b23d22cd9cb7b9cba8055179115ce17msarett headerType = kOS2V1_BitmapHeaderType; 300741143878b23d22cd9cb7b9cba8055179115ce17msarett width = (int) get_short(iBuffer.get(), 0); 301741143878b23d22cd9cb7b9cba8055179115ce17msarett height = (int) get_short(iBuffer.get(), 2); 302741143878b23d22cd9cb7b9cba8055179115ce17msarett bitsPerPixel = get_short(iBuffer.get(), 6); 303741143878b23d22cd9cb7b9cba8055179115ce17msarett bytesPerColor = 3; 304741143878b23d22cd9cb7b9cba8055179115ce17msarett } else { 305741143878b23d22cd9cb7b9cba8055179115ce17msarett // There are no valid bmp headers 306230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Error: second bitmap header size is invalid.\n"); 30779e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo return false; 308741143878b23d22cd9cb7b9cba8055179115ce17msarett } 309741143878b23d22cd9cb7b9cba8055179115ce17msarett 310741143878b23d22cd9cb7b9cba8055179115ce17msarett // Check for valid dimensions from header 311741143878b23d22cd9cb7b9cba8055179115ce17msarett RowOrder rowOrder = kBottomUp_RowOrder; 312741143878b23d22cd9cb7b9cba8055179115ce17msarett if (height < 0) { 313741143878b23d22cd9cb7b9cba8055179115ce17msarett height = -height; 314741143878b23d22cd9cb7b9cba8055179115ce17msarett rowOrder = kTopDown_RowOrder; 315741143878b23d22cd9cb7b9cba8055179115ce17msarett } 3169bde918754bc292469d801f156f3b626eb3db780msarett // The height field for bmp in ico is double the actual height because they 3179bde918754bc292469d801f156f3b626eb3db780msarett // contain an XOR mask followed by an AND mask 3189bde918754bc292469d801f156f3b626eb3db780msarett if (isIco) { 3199bde918754bc292469d801f156f3b626eb3db780msarett height /= 2; 3209bde918754bc292469d801f156f3b626eb3db780msarett } 3214b17fa353e777de309ca8b0706f1d3e326b59822msarett if (width <= 0 || height <= 0) { 3224b17fa353e777de309ca8b0706f1d3e326b59822msarett // TODO: Decide if we want to disable really large bmps as well. 3234b17fa353e777de309ca8b0706f1d3e326b59822msarett // https://code.google.com/p/skia/issues/detail?id=3617 324230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Error: invalid bitmap dimensions.\n"); 32579e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo return false; 326741143878b23d22cd9cb7b9cba8055179115ce17msarett } 327741143878b23d22cd9cb7b9cba8055179115ce17msarett 328741143878b23d22cd9cb7b9cba8055179115ce17msarett // Create mask struct 329741143878b23d22cd9cb7b9cba8055179115ce17msarett SkMasks::InputMasks inputMasks; 330eed039b5ffbdff958053ac80b09451ad6caa1787msarett memset(&inputMasks, 0, sizeof(SkMasks::InputMasks)); 331741143878b23d22cd9cb7b9cba8055179115ce17msarett 332741143878b23d22cd9cb7b9cba8055179115ce17msarett // Determine the input compression format and set bit masks if necessary 333741143878b23d22cd9cb7b9cba8055179115ce17msarett uint32_t maskBytes = 0; 334741143878b23d22cd9cb7b9cba8055179115ce17msarett BitmapInputFormat inputFormat = kUnknown_BitmapInputFormat; 335741143878b23d22cd9cb7b9cba8055179115ce17msarett switch (compression) { 336741143878b23d22cd9cb7b9cba8055179115ce17msarett case kNone_BitmapCompressionMethod: 337741143878b23d22cd9cb7b9cba8055179115ce17msarett inputFormat = kStandard_BitmapInputFormat; 338741143878b23d22cd9cb7b9cba8055179115ce17msarett break; 339741143878b23d22cd9cb7b9cba8055179115ce17msarett case k8BitRLE_BitmapCompressionMethod: 340741143878b23d22cd9cb7b9cba8055179115ce17msarett if (bitsPerPixel != 8) { 341230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Warning: correcting invalid bitmap format.\n"); 342741143878b23d22cd9cb7b9cba8055179115ce17msarett bitsPerPixel = 8; 343741143878b23d22cd9cb7b9cba8055179115ce17msarett } 344741143878b23d22cd9cb7b9cba8055179115ce17msarett inputFormat = kRLE_BitmapInputFormat; 345741143878b23d22cd9cb7b9cba8055179115ce17msarett break; 346741143878b23d22cd9cb7b9cba8055179115ce17msarett case k4BitRLE_BitmapCompressionMethod: 347741143878b23d22cd9cb7b9cba8055179115ce17msarett if (bitsPerPixel != 4) { 348230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Warning: correcting invalid bitmap format.\n"); 349741143878b23d22cd9cb7b9cba8055179115ce17msarett bitsPerPixel = 4; 350741143878b23d22cd9cb7b9cba8055179115ce17msarett } 351741143878b23d22cd9cb7b9cba8055179115ce17msarett inputFormat = kRLE_BitmapInputFormat; 352741143878b23d22cd9cb7b9cba8055179115ce17msarett break; 353741143878b23d22cd9cb7b9cba8055179115ce17msarett case kAlphaBitMasks_BitmapCompressionMethod: 354741143878b23d22cd9cb7b9cba8055179115ce17msarett case kBitMasks_BitmapCompressionMethod: 355741143878b23d22cd9cb7b9cba8055179115ce17msarett // Load the masks 356741143878b23d22cd9cb7b9cba8055179115ce17msarett inputFormat = kBitMask_BitmapInputFormat; 357741143878b23d22cd9cb7b9cba8055179115ce17msarett switch (headerType) { 358741143878b23d22cd9cb7b9cba8055179115ce17msarett case kInfoV1_BitmapHeaderType: { 359741143878b23d22cd9cb7b9cba8055179115ce17msarett // The V1 header stores the bit masks after the header 360741143878b23d22cd9cb7b9cba8055179115ce17msarett SkAutoTDeleteArray<uint8_t> mBuffer( 361741143878b23d22cd9cb7b9cba8055179115ce17msarett SkNEW_ARRAY(uint8_t, kBmpMaskBytes)); 362741143878b23d22cd9cb7b9cba8055179115ce17msarett if (stream->read(mBuffer.get(), kBmpMaskBytes) != 363741143878b23d22cd9cb7b9cba8055179115ce17msarett kBmpMaskBytes) { 364230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Error: unable to read bit inputMasks.\n"); 36579e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo return false; 366741143878b23d22cd9cb7b9cba8055179115ce17msarett } 367741143878b23d22cd9cb7b9cba8055179115ce17msarett maskBytes = kBmpMaskBytes; 368741143878b23d22cd9cb7b9cba8055179115ce17msarett inputMasks.red = get_int(mBuffer.get(), 0); 369741143878b23d22cd9cb7b9cba8055179115ce17msarett inputMasks.green = get_int(mBuffer.get(), 4); 370741143878b23d22cd9cb7b9cba8055179115ce17msarett inputMasks.blue = get_int(mBuffer.get(), 8); 371741143878b23d22cd9cb7b9cba8055179115ce17msarett break; 372741143878b23d22cd9cb7b9cba8055179115ce17msarett } 373741143878b23d22cd9cb7b9cba8055179115ce17msarett case kInfoV2_BitmapHeaderType: 374741143878b23d22cd9cb7b9cba8055179115ce17msarett case kInfoV3_BitmapHeaderType: 375741143878b23d22cd9cb7b9cba8055179115ce17msarett case kInfoV4_BitmapHeaderType: 376741143878b23d22cd9cb7b9cba8055179115ce17msarett case kInfoV5_BitmapHeaderType: 377741143878b23d22cd9cb7b9cba8055179115ce17msarett // Header types are matched based on size. If the header 378741143878b23d22cd9cb7b9cba8055179115ce17msarett // is V2+, we are guaranteed to be able to read at least 379741143878b23d22cd9cb7b9cba8055179115ce17msarett // this size. 380741143878b23d22cd9cb7b9cba8055179115ce17msarett SkASSERT(infoBytesRemaining >= 48); 381741143878b23d22cd9cb7b9cba8055179115ce17msarett inputMasks.red = get_int(iBuffer.get(), 36); 382741143878b23d22cd9cb7b9cba8055179115ce17msarett inputMasks.green = get_int(iBuffer.get(), 40); 383741143878b23d22cd9cb7b9cba8055179115ce17msarett inputMasks.blue = get_int(iBuffer.get(), 44); 384741143878b23d22cd9cb7b9cba8055179115ce17msarett break; 385741143878b23d22cd9cb7b9cba8055179115ce17msarett case kOS2VX_BitmapHeaderType: 386741143878b23d22cd9cb7b9cba8055179115ce17msarett // TODO: Decide if we intend to support this. 387741143878b23d22cd9cb7b9cba8055179115ce17msarett // It is unsupported in the previous version and 388741143878b23d22cd9cb7b9cba8055179115ce17msarett // in chromium. I have not come across a test case 389741143878b23d22cd9cb7b9cba8055179115ce17msarett // that uses this format. 390230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Error: huffman format unsupported.\n"); 39179e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo return false; 392741143878b23d22cd9cb7b9cba8055179115ce17msarett default: 393230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Error: invalid bmp bit masks header.\n"); 39479e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo return false; 395741143878b23d22cd9cb7b9cba8055179115ce17msarett } 396741143878b23d22cd9cb7b9cba8055179115ce17msarett break; 397741143878b23d22cd9cb7b9cba8055179115ce17msarett case kJpeg_BitmapCompressionMethod: 398741143878b23d22cd9cb7b9cba8055179115ce17msarett if (24 == bitsPerPixel) { 399741143878b23d22cd9cb7b9cba8055179115ce17msarett inputFormat = kRLE_BitmapInputFormat; 400741143878b23d22cd9cb7b9cba8055179115ce17msarett break; 401741143878b23d22cd9cb7b9cba8055179115ce17msarett } 402741143878b23d22cd9cb7b9cba8055179115ce17msarett // Fall through 403741143878b23d22cd9cb7b9cba8055179115ce17msarett case kPng_BitmapCompressionMethod: 404741143878b23d22cd9cb7b9cba8055179115ce17msarett // TODO: Decide if we intend to support this. 405741143878b23d22cd9cb7b9cba8055179115ce17msarett // It is unsupported in the previous version and 406741143878b23d22cd9cb7b9cba8055179115ce17msarett // in chromium. I think it is used mostly for printers. 407230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Error: compression format not supported.\n"); 40879e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo return false; 409741143878b23d22cd9cb7b9cba8055179115ce17msarett case kCMYK_BitmapCompressionMethod: 410741143878b23d22cd9cb7b9cba8055179115ce17msarett case kCMYK8BitRLE_BitmapCompressionMethod: 411741143878b23d22cd9cb7b9cba8055179115ce17msarett case kCMYK4BitRLE_BitmapCompressionMethod: 412741143878b23d22cd9cb7b9cba8055179115ce17msarett // TODO: Same as above. 413230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Error: CMYK not supported for bitmap decoding.\n"); 41479e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo return false; 415741143878b23d22cd9cb7b9cba8055179115ce17msarett default: 416230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Error: invalid format for bitmap decoding.\n"); 41779e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo return false; 418741143878b23d22cd9cb7b9cba8055179115ce17msarett } 419741143878b23d22cd9cb7b9cba8055179115ce17msarett 420741143878b23d22cd9cb7b9cba8055179115ce17msarett // Most versions of bmps should be rendered as opaque. Either they do 421741143878b23d22cd9cb7b9cba8055179115ce17msarett // not have an alpha channel, or they expect the alpha channel to be 4229bde918754bc292469d801f156f3b626eb3db780msarett // ignored. V3+ bmp files introduce an alpha mask and allow the creator 423741143878b23d22cd9cb7b9cba8055179115ce17msarett // of the image to use the alpha channels. However, many of these images 4249bde918754bc292469d801f156f3b626eb3db780msarett // leave the alpha channel blank and expect to be rendered as opaque. This 4259bde918754bc292469d801f156f3b626eb3db780msarett // is the case for almost all V3 images, so we render these as opaque. For 4269bde918754bc292469d801f156f3b626eb3db780msarett // V4+, we will use the alpha channel, and fix the image later if it turns 4279bde918754bc292469d801f156f3b626eb3db780msarett // out to be fully transparent. 4289bde918754bc292469d801f156f3b626eb3db780msarett // As an exception, V3 bmp-in-ico may use an alpha mask. 429741143878b23d22cd9cb7b9cba8055179115ce17msarett SkAlphaType alphaType = kOpaque_SkAlphaType; 4309bde918754bc292469d801f156f3b626eb3db780msarett if ((kInfoV3_BitmapHeaderType == headerType && isIco) || 4319bde918754bc292469d801f156f3b626eb3db780msarett kInfoV4_BitmapHeaderType == headerType || 432741143878b23d22cd9cb7b9cba8055179115ce17msarett kInfoV5_BitmapHeaderType == headerType) { 433741143878b23d22cd9cb7b9cba8055179115ce17msarett // Header types are matched based on size. If the header is 4349bde918754bc292469d801f156f3b626eb3db780msarett // V3+, we are guaranteed to be able to read at least this size. 435741143878b23d22cd9cb7b9cba8055179115ce17msarett SkASSERT(infoBytesRemaining > 52); 436741143878b23d22cd9cb7b9cba8055179115ce17msarett inputMasks.alpha = get_int(iBuffer.get(), 48); 437741143878b23d22cd9cb7b9cba8055179115ce17msarett if (inputMasks.alpha != 0) { 438741143878b23d22cd9cb7b9cba8055179115ce17msarett alphaType = kUnpremul_SkAlphaType; 439741143878b23d22cd9cb7b9cba8055179115ce17msarett } 440741143878b23d22cd9cb7b9cba8055179115ce17msarett } 441741143878b23d22cd9cb7b9cba8055179115ce17msarett iBuffer.free(); 442741143878b23d22cd9cb7b9cba8055179115ce17msarett 443438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett // Additionally, 32 bit bmp-in-icos use the alpha channel. 444438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett // And, RLE inputs may skip pixels, leaving them as transparent. This 445438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett // is uncommon, but we cannot be certain that an RLE bmp will be opaque. 446438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett if ((isIco && 32 == bitsPerPixel) || (kRLE_BitmapInputFormat == inputFormat)) { 4479bde918754bc292469d801f156f3b626eb3db780msarett alphaType = kUnpremul_SkAlphaType; 4489bde918754bc292469d801f156f3b626eb3db780msarett } 4499bde918754bc292469d801f156f3b626eb3db780msarett 450438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett // Check for valid bits per pixel. 451438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett // At the same time, use this information to choose a suggested color type 452438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett // and to set default masks. 453438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett SkColorType colorType = kN32_SkColorType; 454741143878b23d22cd9cb7b9cba8055179115ce17msarett switch (bitsPerPixel) { 455741143878b23d22cd9cb7b9cba8055179115ce17msarett // In addition to more standard pixel compression formats, bmp supports 456741143878b23d22cd9cb7b9cba8055179115ce17msarett // the use of bit masks to determine pixel components. The standard 457741143878b23d22cd9cb7b9cba8055179115ce17msarett // format for representing 16-bit colors is 555 (XRRRRRGGGGGBBBBB), 458741143878b23d22cd9cb7b9cba8055179115ce17msarett // which does not map well to any Skia color formats. For this reason, 459741143878b23d22cd9cb7b9cba8055179115ce17msarett // we will always enable mask mode with 16 bits per pixel. 460741143878b23d22cd9cb7b9cba8055179115ce17msarett case 16: 461741143878b23d22cd9cb7b9cba8055179115ce17msarett if (kBitMask_BitmapInputFormat != inputFormat) { 462741143878b23d22cd9cb7b9cba8055179115ce17msarett inputMasks.red = 0x7C00; 463741143878b23d22cd9cb7b9cba8055179115ce17msarett inputMasks.green = 0x03E0; 464741143878b23d22cd9cb7b9cba8055179115ce17msarett inputMasks.blue = 0x001F; 465741143878b23d22cd9cb7b9cba8055179115ce17msarett inputFormat = kBitMask_BitmapInputFormat; 466741143878b23d22cd9cb7b9cba8055179115ce17msarett } 467741143878b23d22cd9cb7b9cba8055179115ce17msarett break; 468438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett // We want to decode to kIndex_8 for input formats that are already 469438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett // designed in index format. 470741143878b23d22cd9cb7b9cba8055179115ce17msarett case 1: 471741143878b23d22cd9cb7b9cba8055179115ce17msarett case 2: 472741143878b23d22cd9cb7b9cba8055179115ce17msarett case 4: 473741143878b23d22cd9cb7b9cba8055179115ce17msarett case 8: 474438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett // However, we cannot in RLE format since we may need to leave some 475438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett // pixels as transparent. Similarly, we also cannot for ICO images 476438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett // since we may need to apply a transparent mask. 477438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett if (kRLE_BitmapInputFormat != inputFormat && !isIco) { 478438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett colorType = kIndex_8_SkColorType; 479438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett } 480741143878b23d22cd9cb7b9cba8055179115ce17msarett case 24: 481741143878b23d22cd9cb7b9cba8055179115ce17msarett case 32: 482741143878b23d22cd9cb7b9cba8055179115ce17msarett break; 483741143878b23d22cd9cb7b9cba8055179115ce17msarett default: 484230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Error: invalid input value for bits per pixel.\n"); 48579e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo return false; 486741143878b23d22cd9cb7b9cba8055179115ce17msarett } 487741143878b23d22cd9cb7b9cba8055179115ce17msarett 488741143878b23d22cd9cb7b9cba8055179115ce17msarett // Check that input bit masks are valid and create the masks object 489741143878b23d22cd9cb7b9cba8055179115ce17msarett SkAutoTDelete<SkMasks> 490741143878b23d22cd9cb7b9cba8055179115ce17msarett masks(SkMasks::CreateMasks(inputMasks, bitsPerPixel)); 491741143878b23d22cd9cb7b9cba8055179115ce17msarett if (NULL == masks) { 492230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Error: invalid input masks.\n"); 49379e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo return false; 494741143878b23d22cd9cb7b9cba8055179115ce17msarett } 495741143878b23d22cd9cb7b9cba8055179115ce17msarett 496eed039b5ffbdff958053ac80b09451ad6caa1787msarett // Check for a valid number of total bytes when in RLE mode 497eed039b5ffbdff958053ac80b09451ad6caa1787msarett if (totalBytes <= offset && kRLE_BitmapInputFormat == inputFormat) { 498230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Error: RLE requires valid input size.\n"); 49979e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo return false; 500741143878b23d22cd9cb7b9cba8055179115ce17msarett } 501eed039b5ffbdff958053ac80b09451ad6caa1787msarett const size_t RLEBytes = totalBytes - offset; 502741143878b23d22cd9cb7b9cba8055179115ce17msarett 503eed039b5ffbdff958053ac80b09451ad6caa1787msarett // Calculate the number of bytes read so far 504eed039b5ffbdff958053ac80b09451ad6caa1787msarett const uint32_t bytesRead = kBmpHeaderBytes + infoBytes + maskBytes; 5059bde918754bc292469d801f156f3b626eb3db780msarett if (!isIco && offset < bytesRead) { 506230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Error: pixel data offset less than header size.\n"); 50779e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo return false; 508741143878b23d22cd9cb7b9cba8055179115ce17msarett } 509741143878b23d22cd9cb7b9cba8055179115ce17msarett 51079e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo if (codecOut) { 51179e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo // Return the codec 512438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett // We will use ImageInfo to store width, height, suggested color type, and 513438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett // suggested alpha type. 51479e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo const SkImageInfo& imageInfo = SkImageInfo::Make(width, height, 515438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett colorType, alphaType); 51679e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo *codecOut = SkNEW_ARGS(SkBmpCodec, (imageInfo, stream, bitsPerPixel, 51779e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo inputFormat, masks.detach(), 51879e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo numColors, bytesPerColor, 51979e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo offset - bytesRead, rowOrder, 52079e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo RLEBytes, isIco)); 52179e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo } 52279e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo return true; 52379e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo} 52479e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo 52579e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo/* 52679e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo * 52779e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo * Creates a bmp decoder 52879e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo * Reads enough of the stream to determine the image format 52979e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo * 53079e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo */ 53179e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggoSkCodec* SkBmpCodec::NewFromStream(SkStream* stream, bool isIco) { 5320a7e69cb9b4e3929d659891d152a2c0b59bff4e0scroggo SkAutoTDelete<SkStream> streamDeleter(stream); 53379e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo SkCodec* codec = NULL; 53479e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo if (ReadHeader(stream, isIco, &codec)) { 5350a7e69cb9b4e3929d659891d152a2c0b59bff4e0scroggo // codec has taken ownership of stream, so we do not need to 5360a7e69cb9b4e3929d659891d152a2c0b59bff4e0scroggo // delete it. 5370a7e69cb9b4e3929d659891d152a2c0b59bff4e0scroggo SkASSERT(codec); 5380a7e69cb9b4e3929d659891d152a2c0b59bff4e0scroggo streamDeleter.detach(); 53979e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo return codec; 54079e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo } 54179e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo return NULL; 542741143878b23d22cd9cb7b9cba8055179115ce17msarett} 543741143878b23d22cd9cb7b9cba8055179115ce17msarett 544741143878b23d22cd9cb7b9cba8055179115ce17msarett/* 545741143878b23d22cd9cb7b9cba8055179115ce17msarett * 546741143878b23d22cd9cb7b9cba8055179115ce17msarett * Creates an instance of the decoder 547741143878b23d22cd9cb7b9cba8055179115ce17msarett * Called only by NewFromStream 548741143878b23d22cd9cb7b9cba8055179115ce17msarett * 549741143878b23d22cd9cb7b9cba8055179115ce17msarett */ 550741143878b23d22cd9cb7b9cba8055179115ce17msarettSkBmpCodec::SkBmpCodec(const SkImageInfo& info, SkStream* stream, 551741143878b23d22cd9cb7b9cba8055179115ce17msarett uint16_t bitsPerPixel, BitmapInputFormat inputFormat, 552eed039b5ffbdff958053ac80b09451ad6caa1787msarett SkMasks* masks, uint32_t numColors, 553eed039b5ffbdff958053ac80b09451ad6caa1787msarett uint32_t bytesPerColor, uint32_t offset, 5549bde918754bc292469d801f156f3b626eb3db780msarett RowOrder rowOrder, size_t RLEBytes, bool isIco) 555741143878b23d22cd9cb7b9cba8055179115ce17msarett : INHERITED(info, stream) 556741143878b23d22cd9cb7b9cba8055179115ce17msarett , fBitsPerPixel(bitsPerPixel) 557741143878b23d22cd9cb7b9cba8055179115ce17msarett , fInputFormat(inputFormat) 558741143878b23d22cd9cb7b9cba8055179115ce17msarett , fMasks(masks) 559eed039b5ffbdff958053ac80b09451ad6caa1787msarett , fColorTable(NULL) 560eed039b5ffbdff958053ac80b09451ad6caa1787msarett , fNumColors(numColors) 561eed039b5ffbdff958053ac80b09451ad6caa1787msarett , fBytesPerColor(bytesPerColor) 562eed039b5ffbdff958053ac80b09451ad6caa1787msarett , fOffset(offset) 563741143878b23d22cd9cb7b9cba8055179115ce17msarett , fRowOrder(rowOrder) 564eed039b5ffbdff958053ac80b09451ad6caa1787msarett , fRLEBytes(RLEBytes) 5659bde918754bc292469d801f156f3b626eb3db780msarett , fIsIco(isIco) 5669bde918754bc292469d801f156f3b626eb3db780msarett 567741143878b23d22cd9cb7b9cba8055179115ce17msarett{} 568741143878b23d22cd9cb7b9cba8055179115ce17msarett 569741143878b23d22cd9cb7b9cba8055179115ce17msarett/* 570741143878b23d22cd9cb7b9cba8055179115ce17msarett * 571741143878b23d22cd9cb7b9cba8055179115ce17msarett * Initiates the bitmap decode 572741143878b23d22cd9cb7b9cba8055179115ce17msarett * 573741143878b23d22cd9cb7b9cba8055179115ce17msarett */ 574741143878b23d22cd9cb7b9cba8055179115ce17msarettSkCodec::Result SkBmpCodec::onGetPixels(const SkImageInfo& dstInfo, 575741143878b23d22cd9cb7b9cba8055179115ce17msarett void* dst, size_t dstRowBytes, 576438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett const Options& opts, 577438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett SkPMColor* inputColorPtr, 578438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett int* inputColorCount) { 579eed039b5ffbdff958053ac80b09451ad6caa1787msarett // Check for proper input and output formats 580a096d7a6d03662073f4cd46f7db5fe2cf5495c36halcanary SkCodec::RewindState rewindState = this->rewindIfNeeded(); 581a096d7a6d03662073f4cd46f7db5fe2cf5495c36halcanary if (rewindState == kCouldNotRewind_RewindState) { 582741143878b23d22cd9cb7b9cba8055179115ce17msarett return kCouldNotRewind; 583a096d7a6d03662073f4cd46f7db5fe2cf5495c36halcanary } else if (rewindState == kRewound_RewindState) { 58479e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo if (!ReadHeader(this->stream(), fIsIco, NULL)) { 58579e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo return kCouldNotRewind; 58679e378d9b78c3db28eb97ab9adecb5bfddbf52d8scroggo } 587741143878b23d22cd9cb7b9cba8055179115ce17msarett } 5889bde918754bc292469d801f156f3b626eb3db780msarett if (dstInfo.dimensions() != this->getInfo().dimensions()) { 589230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Error: scaling not supported.\n"); 590741143878b23d22cd9cb7b9cba8055179115ce17msarett return kInvalidScale; 591741143878b23d22cd9cb7b9cba8055179115ce17msarett } 5929bde918754bc292469d801f156f3b626eb3db780msarett if (!conversion_possible(dstInfo, this->getInfo())) { 593230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Error: cannot convert input type to output type.\n"); 594741143878b23d22cd9cb7b9cba8055179115ce17msarett return kInvalidConversion; 595741143878b23d22cd9cb7b9cba8055179115ce17msarett } 596741143878b23d22cd9cb7b9cba8055179115ce17msarett 597eed039b5ffbdff958053ac80b09451ad6caa1787msarett // Create the color table if necessary and prepare the stream for decode 598438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett // Note that if it is non-NULL, inputColorCount will be modified 599438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett if (!createColorTable(dstInfo.alphaType(), inputColorCount)) { 600230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Error: could not create color table.\n"); 601eed039b5ffbdff958053ac80b09451ad6caa1787msarett return kInvalidInput; 602eed039b5ffbdff958053ac80b09451ad6caa1787msarett } 603eed039b5ffbdff958053ac80b09451ad6caa1787msarett 604438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett // Copy the color table to the client if necessary 6059e43cabaa1ff26167e990f0bcb9a5c20d662d52cmsarett copy_color_table(dstInfo, fColorTable, inputColorPtr, inputColorCount); 606438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett 607eed039b5ffbdff958053ac80b09451ad6caa1787msarett // Perform the decode 608741143878b23d22cd9cb7b9cba8055179115ce17msarett switch (fInputFormat) { 609741143878b23d22cd9cb7b9cba8055179115ce17msarett case kBitMask_BitmapInputFormat: 6103c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett return decodeMask(dstInfo, dst, dstRowBytes, opts); 611741143878b23d22cd9cb7b9cba8055179115ce17msarett case kRLE_BitmapInputFormat: 612438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett return decodeRLE(dstInfo, dst, dstRowBytes, opts); 613741143878b23d22cd9cb7b9cba8055179115ce17msarett case kStandard_BitmapInputFormat: 6143c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett return decode(dstInfo, dst, dstRowBytes, opts); 615741143878b23d22cd9cb7b9cba8055179115ce17msarett default: 616741143878b23d22cd9cb7b9cba8055179115ce17msarett SkASSERT(false); 617741143878b23d22cd9cb7b9cba8055179115ce17msarett return kInvalidInput; 618741143878b23d22cd9cb7b9cba8055179115ce17msarett } 619741143878b23d22cd9cb7b9cba8055179115ce17msarett} 620741143878b23d22cd9cb7b9cba8055179115ce17msarett 621741143878b23d22cd9cb7b9cba8055179115ce17msarett/* 622741143878b23d22cd9cb7b9cba8055179115ce17msarett * 623eed039b5ffbdff958053ac80b09451ad6caa1787msarett * Process the color table for the bmp input 624eed039b5ffbdff958053ac80b09451ad6caa1787msarett * 625eed039b5ffbdff958053ac80b09451ad6caa1787msarett */ 626438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett bool SkBmpCodec::createColorTable(SkAlphaType alphaType, int* numColors) { 627eed039b5ffbdff958053ac80b09451ad6caa1787msarett // Allocate memory for color table 628eed039b5ffbdff958053ac80b09451ad6caa1787msarett uint32_t colorBytes = 0; 629eed039b5ffbdff958053ac80b09451ad6caa1787msarett uint32_t maxColors = 0; 630eed039b5ffbdff958053ac80b09451ad6caa1787msarett SkPMColor colorTable[256]; 631eed039b5ffbdff958053ac80b09451ad6caa1787msarett if (fBitsPerPixel <= 8) { 632eed039b5ffbdff958053ac80b09451ad6caa1787msarett // Zero is a default for maxColors 633eed039b5ffbdff958053ac80b09451ad6caa1787msarett // Also set fNumColors to maxColors when it is too large 634eed039b5ffbdff958053ac80b09451ad6caa1787msarett maxColors = 1 << fBitsPerPixel; 635eed039b5ffbdff958053ac80b09451ad6caa1787msarett if (fNumColors == 0 || fNumColors >= maxColors) { 636eed039b5ffbdff958053ac80b09451ad6caa1787msarett fNumColors = maxColors; 637eed039b5ffbdff958053ac80b09451ad6caa1787msarett } 638eed039b5ffbdff958053ac80b09451ad6caa1787msarett 639438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett // Inform the caller of the number of colors 640438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett if (NULL != numColors) { 641438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett // We set the number of colors to maxColors in order to ensure 642438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett // safe memory accesses. Otherwise, an invalid pixel could 643438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett // access memory outside of our color table array. 644438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett *numColors = maxColors; 645438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett } 646438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett 647eed039b5ffbdff958053ac80b09451ad6caa1787msarett // Read the color table from the stream 648eed039b5ffbdff958053ac80b09451ad6caa1787msarett colorBytes = fNumColors * fBytesPerColor; 649eed039b5ffbdff958053ac80b09451ad6caa1787msarett SkAutoTDeleteArray<uint8_t> cBuffer(SkNEW_ARRAY(uint8_t, colorBytes)); 650eed039b5ffbdff958053ac80b09451ad6caa1787msarett if (stream()->read(cBuffer.get(), colorBytes) != colorBytes) { 651230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Error: unable to read color table.\n"); 652eed039b5ffbdff958053ac80b09451ad6caa1787msarett return false; 653eed039b5ffbdff958053ac80b09451ad6caa1787msarett } 654eed039b5ffbdff958053ac80b09451ad6caa1787msarett 655eed039b5ffbdff958053ac80b09451ad6caa1787msarett // Choose the proper packing function 656eed039b5ffbdff958053ac80b09451ad6caa1787msarett SkPMColor (*packARGB) (uint32_t, uint32_t, uint32_t, uint32_t); 657eed039b5ffbdff958053ac80b09451ad6caa1787msarett switch (alphaType) { 658eed039b5ffbdff958053ac80b09451ad6caa1787msarett case kOpaque_SkAlphaType: 659eed039b5ffbdff958053ac80b09451ad6caa1787msarett case kUnpremul_SkAlphaType: 660eed039b5ffbdff958053ac80b09451ad6caa1787msarett packARGB = &SkPackARGB32NoCheck; 661eed039b5ffbdff958053ac80b09451ad6caa1787msarett break; 662eed039b5ffbdff958053ac80b09451ad6caa1787msarett case kPremul_SkAlphaType: 663eed039b5ffbdff958053ac80b09451ad6caa1787msarett packARGB = &SkPreMultiplyARGB; 664eed039b5ffbdff958053ac80b09451ad6caa1787msarett break; 665eed039b5ffbdff958053ac80b09451ad6caa1787msarett default: 666eed039b5ffbdff958053ac80b09451ad6caa1787msarett // This should not be reached because conversion possible 667eed039b5ffbdff958053ac80b09451ad6caa1787msarett // should fail if the alpha type is not one of the above 668eed039b5ffbdff958053ac80b09451ad6caa1787msarett // values. 669eed039b5ffbdff958053ac80b09451ad6caa1787msarett SkASSERT(false); 670eed039b5ffbdff958053ac80b09451ad6caa1787msarett packARGB = NULL; 671eed039b5ffbdff958053ac80b09451ad6caa1787msarett break; 672eed039b5ffbdff958053ac80b09451ad6caa1787msarett } 673eed039b5ffbdff958053ac80b09451ad6caa1787msarett 674eed039b5ffbdff958053ac80b09451ad6caa1787msarett // Fill in the color table 675eed039b5ffbdff958053ac80b09451ad6caa1787msarett uint32_t i = 0; 676eed039b5ffbdff958053ac80b09451ad6caa1787msarett for (; i < fNumColors; i++) { 677eed039b5ffbdff958053ac80b09451ad6caa1787msarett uint8_t blue = get_byte(cBuffer.get(), i*fBytesPerColor); 678eed039b5ffbdff958053ac80b09451ad6caa1787msarett uint8_t green = get_byte(cBuffer.get(), i*fBytesPerColor + 1); 679eed039b5ffbdff958053ac80b09451ad6caa1787msarett uint8_t red = get_byte(cBuffer.get(), i*fBytesPerColor + 2); 680438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett uint8_t alpha; 681438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett if (kOpaque_SkAlphaType == alphaType || kRLE_BitmapInputFormat == fInputFormat) { 682438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett alpha = 0xFF; 683438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett } else { 684438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett alpha = (fMasks->getAlphaMask() >> 24) & 685438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett get_byte(cBuffer.get(), i*fBytesPerColor + 3); 686438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett } 687eed039b5ffbdff958053ac80b09451ad6caa1787msarett colorTable[i] = packARGB(alpha, red, green, blue); 688eed039b5ffbdff958053ac80b09451ad6caa1787msarett } 689eed039b5ffbdff958053ac80b09451ad6caa1787msarett 690eed039b5ffbdff958053ac80b09451ad6caa1787msarett // To avoid segmentation faults on bad pixel data, fill the end of the 691eed039b5ffbdff958053ac80b09451ad6caa1787msarett // color table with black. This is the same the behavior as the 692eed039b5ffbdff958053ac80b09451ad6caa1787msarett // chromium decoder. 693eed039b5ffbdff958053ac80b09451ad6caa1787msarett for (; i < maxColors; i++) { 694eed039b5ffbdff958053ac80b09451ad6caa1787msarett colorTable[i] = SkPackARGB32NoCheck(0xFF, 0, 0, 0); 695eed039b5ffbdff958053ac80b09451ad6caa1787msarett } 6963c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett 6973c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett // Set the color table 6983c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett fColorTable.reset(SkNEW_ARGS(SkColorTable, (colorTable, maxColors))); 699eed039b5ffbdff958053ac80b09451ad6caa1787msarett } 700eed039b5ffbdff958053ac80b09451ad6caa1787msarett 7019bde918754bc292469d801f156f3b626eb3db780msarett // Bmp-in-Ico files do not use an offset to indicate where the pixel data 7029bde918754bc292469d801f156f3b626eb3db780msarett // begins. Pixel data always begins immediately after the color table. 7039bde918754bc292469d801f156f3b626eb3db780msarett if (!fIsIco) { 7049bde918754bc292469d801f156f3b626eb3db780msarett // Check that we have not read past the pixel array offset 7059bde918754bc292469d801f156f3b626eb3db780msarett if(fOffset < colorBytes) { 7069bde918754bc292469d801f156f3b626eb3db780msarett // This may occur on OS 2.1 and other old versions where the color 7079bde918754bc292469d801f156f3b626eb3db780msarett // table defaults to max size, and the bmp tries to use a smaller 7089bde918754bc292469d801f156f3b626eb3db780msarett // color table. This is invalid, and our decision is to indicate 7099bde918754bc292469d801f156f3b626eb3db780msarett // an error, rather than try to guess the intended size of the 7109bde918754bc292469d801f156f3b626eb3db780msarett // color table. 711230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Error: pixel data offset less than color table size.\n"); 7129bde918754bc292469d801f156f3b626eb3db780msarett return false; 7139bde918754bc292469d801f156f3b626eb3db780msarett } 714eed039b5ffbdff958053ac80b09451ad6caa1787msarett 7159bde918754bc292469d801f156f3b626eb3db780msarett // After reading the color table, skip to the start of the pixel array 7169bde918754bc292469d801f156f3b626eb3db780msarett if (stream()->skip(fOffset - colorBytes) != fOffset - colorBytes) { 717230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Error: unable to skip to image data.\n"); 7189bde918754bc292469d801f156f3b626eb3db780msarett return false; 7199bde918754bc292469d801f156f3b626eb3db780msarett } 720eed039b5ffbdff958053ac80b09451ad6caa1787msarett } 721eed039b5ffbdff958053ac80b09451ad6caa1787msarett 7223c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett // Return true on success 723eed039b5ffbdff958053ac80b09451ad6caa1787msarett return true; 724eed039b5ffbdff958053ac80b09451ad6caa1787msarett} 725eed039b5ffbdff958053ac80b09451ad6caa1787msarett 726eed039b5ffbdff958053ac80b09451ad6caa1787msarett/* 727eed039b5ffbdff958053ac80b09451ad6caa1787msarett * 7283c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett * Get the destination row to start filling from 7293c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett * Used to fill the remainder of the image on incomplete input 7303c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett * 7313c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett */ 7323c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarettstatic inline void* get_dst_start_row(void* dst, size_t dstRowBytes, int32_t y, 7333c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett SkBmpCodec::RowOrder rowOrder) { 7343c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett return (SkBmpCodec::kTopDown_RowOrder == rowOrder) ? 7353c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett SkTAddOffset<void*>(dst, y * dstRowBytes) : dst; 7363c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett} 7373c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett 7383c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett/* 7393c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett * 740741143878b23d22cd9cb7b9cba8055179115ce17msarett * Performs the bitmap decoding for bit masks input format 741741143878b23d22cd9cb7b9cba8055179115ce17msarett * 742741143878b23d22cd9cb7b9cba8055179115ce17msarett */ 743741143878b23d22cd9cb7b9cba8055179115ce17msarettSkCodec::Result SkBmpCodec::decodeMask(const SkImageInfo& dstInfo, 7443c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett void* dst, size_t dstRowBytes, 7453c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett const Options& opts) { 746741143878b23d22cd9cb7b9cba8055179115ce17msarett // Set constant values 747741143878b23d22cd9cb7b9cba8055179115ce17msarett const int width = dstInfo.width(); 748741143878b23d22cd9cb7b9cba8055179115ce17msarett const int height = dstInfo.height(); 749741143878b23d22cd9cb7b9cba8055179115ce17msarett const size_t rowBytes = SkAlign4(compute_row_bytes(width, fBitsPerPixel)); 750741143878b23d22cd9cb7b9cba8055179115ce17msarett 751eed039b5ffbdff958053ac80b09451ad6caa1787msarett // Allocate a buffer large enough to hold the full image 752eed039b5ffbdff958053ac80b09451ad6caa1787msarett SkAutoTDeleteArray<uint8_t> 753eed039b5ffbdff958053ac80b09451ad6caa1787msarett srcBuffer(SkNEW_ARRAY(uint8_t, height*rowBytes)); 754eed039b5ffbdff958053ac80b09451ad6caa1787msarett uint8_t* srcRow = srcBuffer.get(); 755741143878b23d22cd9cb7b9cba8055179115ce17msarett 756741143878b23d22cd9cb7b9cba8055179115ce17msarett // Create the swizzler 757eed039b5ffbdff958053ac80b09451ad6caa1787msarett SkAutoTDelete<SkMaskSwizzler> maskSwizzler( 758eed039b5ffbdff958053ac80b09451ad6caa1787msarett SkMaskSwizzler::CreateMaskSwizzler(dstInfo, dst, dstRowBytes, 759eed039b5ffbdff958053ac80b09451ad6caa1787msarett fMasks, fBitsPerPixel)); 760741143878b23d22cd9cb7b9cba8055179115ce17msarett 761741143878b23d22cd9cb7b9cba8055179115ce17msarett // Iterate over rows of the image 762741143878b23d22cd9cb7b9cba8055179115ce17msarett bool transparent = true; 763741143878b23d22cd9cb7b9cba8055179115ce17msarett for (int y = 0; y < height; y++) { 764741143878b23d22cd9cb7b9cba8055179115ce17msarett // Read a row of the input 765eed039b5ffbdff958053ac80b09451ad6caa1787msarett if (stream()->read(srcRow, rowBytes) != rowBytes) { 766230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Warning: incomplete input stream.\n"); 7673c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett // Fill the destination image on failure 768e16b04aa6041efb6507546547737e9603fa1606emsarett SkPMColor fillColor = dstInfo.alphaType() == kOpaque_SkAlphaType ? 769e16b04aa6041efb6507546547737e9603fa1606emsarett SK_ColorBLACK : SK_ColorTRANSPARENT; 770e16b04aa6041efb6507546547737e9603fa1606emsarett if (kNo_ZeroInitialized == opts.fZeroInitialized || 0 != fillColor) { 7713c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett void* dstStart = get_dst_start_row(dst, dstRowBytes, y, fRowOrder); 772e16b04aa6041efb6507546547737e9603fa1606emsarett SkSwizzler::Fill(dstStart, dstInfo, dstRowBytes, dstInfo.height() - y, fillColor, 773e16b04aa6041efb6507546547737e9603fa1606emsarett NULL); 7743c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett } 775741143878b23d22cd9cb7b9cba8055179115ce17msarett return kIncompleteInput; 776741143878b23d22cd9cb7b9cba8055179115ce17msarett } 777741143878b23d22cd9cb7b9cba8055179115ce17msarett 778741143878b23d22cd9cb7b9cba8055179115ce17msarett // Decode the row in destination format 779eed039b5ffbdff958053ac80b09451ad6caa1787msarett int row = kBottomUp_RowOrder == fRowOrder ? height - 1 - y : y; 780eed039b5ffbdff958053ac80b09451ad6caa1787msarett SkSwizzler::ResultAlpha r = maskSwizzler->next(srcRow, row); 781741143878b23d22cd9cb7b9cba8055179115ce17msarett transparent &= SkSwizzler::IsTransparent(r); 782741143878b23d22cd9cb7b9cba8055179115ce17msarett 783741143878b23d22cd9cb7b9cba8055179115ce17msarett // Move to the next row 784eed039b5ffbdff958053ac80b09451ad6caa1787msarett srcRow = SkTAddOffset<uint8_t>(srcRow, rowBytes); 785741143878b23d22cd9cb7b9cba8055179115ce17msarett } 786741143878b23d22cd9cb7b9cba8055179115ce17msarett 787741143878b23d22cd9cb7b9cba8055179115ce17msarett // Some fully transparent bmp images are intended to be opaque. Here, we 788741143878b23d22cd9cb7b9cba8055179115ce17msarett // correct for this possibility. 789741143878b23d22cd9cb7b9cba8055179115ce17msarett if (transparent) { 790eed039b5ffbdff958053ac80b09451ad6caa1787msarett const SkImageInfo& opaqueInfo = 791eed039b5ffbdff958053ac80b09451ad6caa1787msarett dstInfo.makeAlphaType(kOpaque_SkAlphaType); 792eed039b5ffbdff958053ac80b09451ad6caa1787msarett SkAutoTDelete<SkMaskSwizzler> opaqueSwizzler( 793eed039b5ffbdff958053ac80b09451ad6caa1787msarett SkMaskSwizzler::CreateMaskSwizzler(opaqueInfo, dst, dstRowBytes, 794eed039b5ffbdff958053ac80b09451ad6caa1787msarett fMasks, fBitsPerPixel)); 795eed039b5ffbdff958053ac80b09451ad6caa1787msarett srcRow = srcBuffer.get(); 796741143878b23d22cd9cb7b9cba8055179115ce17msarett for (int y = 0; y < height; y++) { 797eed039b5ffbdff958053ac80b09451ad6caa1787msarett // Decode the row in opaque format 798eed039b5ffbdff958053ac80b09451ad6caa1787msarett int row = kBottomUp_RowOrder == fRowOrder ? height - 1 - y : y; 799eed039b5ffbdff958053ac80b09451ad6caa1787msarett opaqueSwizzler->next(srcRow, row); 800eed039b5ffbdff958053ac80b09451ad6caa1787msarett 801eed039b5ffbdff958053ac80b09451ad6caa1787msarett // Move to the next row 802eed039b5ffbdff958053ac80b09451ad6caa1787msarett srcRow = SkTAddOffset<uint8_t>(srcRow, rowBytes); 803741143878b23d22cd9cb7b9cba8055179115ce17msarett } 804741143878b23d22cd9cb7b9cba8055179115ce17msarett } 805741143878b23d22cd9cb7b9cba8055179115ce17msarett 806741143878b23d22cd9cb7b9cba8055179115ce17msarett // Finished decoding the entire image 807741143878b23d22cd9cb7b9cba8055179115ce17msarett return kSuccess; 808741143878b23d22cd9cb7b9cba8055179115ce17msarett} 809741143878b23d22cd9cb7b9cba8055179115ce17msarett 810741143878b23d22cd9cb7b9cba8055179115ce17msarett/* 811741143878b23d22cd9cb7b9cba8055179115ce17msarett * 812741143878b23d22cd9cb7b9cba8055179115ce17msarett * Set an RLE pixel using the color table 813741143878b23d22cd9cb7b9cba8055179115ce17msarett * 814741143878b23d22cd9cb7b9cba8055179115ce17msarett */ 815438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarettvoid SkBmpCodec::setRLEPixel(void* dst, size_t dstRowBytes, 816eed039b5ffbdff958053ac80b09451ad6caa1787msarett const SkImageInfo& dstInfo, uint32_t x, uint32_t y, 817eed039b5ffbdff958053ac80b09451ad6caa1787msarett uint8_t index) { 818eed039b5ffbdff958053ac80b09451ad6caa1787msarett // Set the row 819eed039b5ffbdff958053ac80b09451ad6caa1787msarett int height = dstInfo.height(); 820eed039b5ffbdff958053ac80b09451ad6caa1787msarett int row; 821741143878b23d22cd9cb7b9cba8055179115ce17msarett if (kBottomUp_RowOrder == fRowOrder) { 822eed039b5ffbdff958053ac80b09451ad6caa1787msarett row = height - y - 1; 823eed039b5ffbdff958053ac80b09451ad6caa1787msarett } else { 824eed039b5ffbdff958053ac80b09451ad6caa1787msarett row = y; 825eed039b5ffbdff958053ac80b09451ad6caa1787msarett } 826eed039b5ffbdff958053ac80b09451ad6caa1787msarett 827eed039b5ffbdff958053ac80b09451ad6caa1787msarett // Set the pixel based on destination color type 828eed039b5ffbdff958053ac80b09451ad6caa1787msarett switch (dstInfo.colorType()) { 829eed039b5ffbdff958053ac80b09451ad6caa1787msarett case kN32_SkColorType: { 830438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett SkPMColor* dstRow = SkTAddOffset<SkPMColor>((SkPMColor*) dst, 831eed039b5ffbdff958053ac80b09451ad6caa1787msarett row * (int) dstRowBytes); 832eed039b5ffbdff958053ac80b09451ad6caa1787msarett dstRow[x] = fColorTable->operator[](index); 833eed039b5ffbdff958053ac80b09451ad6caa1787msarett break; 834eed039b5ffbdff958053ac80b09451ad6caa1787msarett } 835eed039b5ffbdff958053ac80b09451ad6caa1787msarett default: 836eed039b5ffbdff958053ac80b09451ad6caa1787msarett // This case should not be reached. We should catch an invalid 837eed039b5ffbdff958053ac80b09451ad6caa1787msarett // color type when we check that the conversion is possible. 838eed039b5ffbdff958053ac80b09451ad6caa1787msarett SkASSERT(false); 839eed039b5ffbdff958053ac80b09451ad6caa1787msarett break; 840eed039b5ffbdff958053ac80b09451ad6caa1787msarett } 841eed039b5ffbdff958053ac80b09451ad6caa1787msarett} 842eed039b5ffbdff958053ac80b09451ad6caa1787msarett 843eed039b5ffbdff958053ac80b09451ad6caa1787msarett/* 844eed039b5ffbdff958053ac80b09451ad6caa1787msarett * 845eed039b5ffbdff958053ac80b09451ad6caa1787msarett * Set an RLE pixel from R, G, B values 846eed039b5ffbdff958053ac80b09451ad6caa1787msarett * 847eed039b5ffbdff958053ac80b09451ad6caa1787msarett */ 848438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarettvoid SkBmpCodec::setRLE24Pixel(void* dst, size_t dstRowBytes, 849eed039b5ffbdff958053ac80b09451ad6caa1787msarett const SkImageInfo& dstInfo, uint32_t x, 850eed039b5ffbdff958053ac80b09451ad6caa1787msarett uint32_t y, uint8_t red, uint8_t green, 851eed039b5ffbdff958053ac80b09451ad6caa1787msarett uint8_t blue) { 852eed039b5ffbdff958053ac80b09451ad6caa1787msarett // Set the row 853eed039b5ffbdff958053ac80b09451ad6caa1787msarett int height = dstInfo.height(); 854eed039b5ffbdff958053ac80b09451ad6caa1787msarett int row; 855eed039b5ffbdff958053ac80b09451ad6caa1787msarett if (kBottomUp_RowOrder == fRowOrder) { 856eed039b5ffbdff958053ac80b09451ad6caa1787msarett row = height - y - 1; 857eed039b5ffbdff958053ac80b09451ad6caa1787msarett } else { 858eed039b5ffbdff958053ac80b09451ad6caa1787msarett row = y; 859eed039b5ffbdff958053ac80b09451ad6caa1787msarett } 860eed039b5ffbdff958053ac80b09451ad6caa1787msarett 861eed039b5ffbdff958053ac80b09451ad6caa1787msarett // Set the pixel based on destination color type 862eed039b5ffbdff958053ac80b09451ad6caa1787msarett switch (dstInfo.colorType()) { 863eed039b5ffbdff958053ac80b09451ad6caa1787msarett case kN32_SkColorType: { 864438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett SkPMColor* dstRow = SkTAddOffset<SkPMColor>((SkPMColor*) dst, 865eed039b5ffbdff958053ac80b09451ad6caa1787msarett row * (int) dstRowBytes); 866eed039b5ffbdff958053ac80b09451ad6caa1787msarett dstRow[x] = SkPackARGB32NoCheck(0xFF, red, green, blue); 867eed039b5ffbdff958053ac80b09451ad6caa1787msarett break; 868eed039b5ffbdff958053ac80b09451ad6caa1787msarett } 869eed039b5ffbdff958053ac80b09451ad6caa1787msarett default: 870eed039b5ffbdff958053ac80b09451ad6caa1787msarett // This case should not be reached. We should catch an invalid 871eed039b5ffbdff958053ac80b09451ad6caa1787msarett // color type when we check that the conversion is possible. 872eed039b5ffbdff958053ac80b09451ad6caa1787msarett SkASSERT(false); 873eed039b5ffbdff958053ac80b09451ad6caa1787msarett break; 874741143878b23d22cd9cb7b9cba8055179115ce17msarett } 875741143878b23d22cd9cb7b9cba8055179115ce17msarett} 876741143878b23d22cd9cb7b9cba8055179115ce17msarett 877741143878b23d22cd9cb7b9cba8055179115ce17msarett/* 878741143878b23d22cd9cb7b9cba8055179115ce17msarett * 879741143878b23d22cd9cb7b9cba8055179115ce17msarett * Performs the bitmap decoding for RLE input format 880741143878b23d22cd9cb7b9cba8055179115ce17msarett * RLE decoding is performed all at once, rather than a one row at a time 881741143878b23d22cd9cb7b9cba8055179115ce17msarett * 882741143878b23d22cd9cb7b9cba8055179115ce17msarett */ 883741143878b23d22cd9cb7b9cba8055179115ce17msarettSkCodec::Result SkBmpCodec::decodeRLE(const SkImageInfo& dstInfo, 884438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett void* dst, size_t dstRowBytes, 885438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett const Options& opts) { 886741143878b23d22cd9cb7b9cba8055179115ce17msarett // Set RLE flags 887741143878b23d22cd9cb7b9cba8055179115ce17msarett static const uint8_t RLE_ESCAPE = 0; 888741143878b23d22cd9cb7b9cba8055179115ce17msarett static const uint8_t RLE_EOL = 0; 889741143878b23d22cd9cb7b9cba8055179115ce17msarett static const uint8_t RLE_EOF = 1; 890741143878b23d22cd9cb7b9cba8055179115ce17msarett static const uint8_t RLE_DELTA = 2; 891741143878b23d22cd9cb7b9cba8055179115ce17msarett 892741143878b23d22cd9cb7b9cba8055179115ce17msarett // Set constant values 893741143878b23d22cd9cb7b9cba8055179115ce17msarett const int width = dstInfo.width(); 894741143878b23d22cd9cb7b9cba8055179115ce17msarett const int height = dstInfo.height(); 895741143878b23d22cd9cb7b9cba8055179115ce17msarett 896741143878b23d22cd9cb7b9cba8055179115ce17msarett // Input buffer parameters 897741143878b23d22cd9cb7b9cba8055179115ce17msarett uint32_t currByte = 0; 898eed039b5ffbdff958053ac80b09451ad6caa1787msarett SkAutoTDeleteArray<uint8_t> buffer(SkNEW_ARRAY(uint8_t, fRLEBytes)); 899eed039b5ffbdff958053ac80b09451ad6caa1787msarett size_t totalBytes = stream()->read(buffer.get(), fRLEBytes); 900eed039b5ffbdff958053ac80b09451ad6caa1787msarett if (totalBytes < fRLEBytes) { 901230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Warning: incomplete RLE file.\n"); 902741143878b23d22cd9cb7b9cba8055179115ce17msarett } else if (totalBytes <= 0) { 903230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Error: could not read RLE image data.\n"); 904741143878b23d22cd9cb7b9cba8055179115ce17msarett return kInvalidInput; 905741143878b23d22cd9cb7b9cba8055179115ce17msarett } 906741143878b23d22cd9cb7b9cba8055179115ce17msarett 907741143878b23d22cd9cb7b9cba8055179115ce17msarett // Destination parameters 908741143878b23d22cd9cb7b9cba8055179115ce17msarett int x = 0; 909741143878b23d22cd9cb7b9cba8055179115ce17msarett int y = 0; 910438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett 911438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett // Set the background as transparent. Then, if the RLE code skips pixels, 912438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett // the skipped pixels will be transparent. 913438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett // Because of the need for transparent pixels, kN32 is the only color 914438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett // type that makes sense for the destination format. 915438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett SkASSERT(kN32_SkColorType == dstInfo.colorType()); 916438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett if (kNo_ZeroInitialized == opts.fZeroInitialized) { 9173c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett SkSwizzler::Fill(dst, dstInfo, dstRowBytes, height, SK_ColorTRANSPARENT, NULL); 918438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett } 919741143878b23d22cd9cb7b9cba8055179115ce17msarett 920741143878b23d22cd9cb7b9cba8055179115ce17msarett while (true) { 921741143878b23d22cd9cb7b9cba8055179115ce17msarett // Every entry takes at least two bytes 922741143878b23d22cd9cb7b9cba8055179115ce17msarett if ((int) totalBytes - currByte < 2) { 923230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Warning: incomplete RLE input.\n"); 924741143878b23d22cd9cb7b9cba8055179115ce17msarett return kIncompleteInput; 925741143878b23d22cd9cb7b9cba8055179115ce17msarett } 926741143878b23d22cd9cb7b9cba8055179115ce17msarett 927741143878b23d22cd9cb7b9cba8055179115ce17msarett // Read the next two bytes. These bytes have different meanings 928741143878b23d22cd9cb7b9cba8055179115ce17msarett // depending on their values. In the first interpretation, the first 929741143878b23d22cd9cb7b9cba8055179115ce17msarett // byte is an escape flag and the second byte indicates what special 930741143878b23d22cd9cb7b9cba8055179115ce17msarett // task to perform. 931741143878b23d22cd9cb7b9cba8055179115ce17msarett const uint8_t flag = buffer.get()[currByte++]; 932741143878b23d22cd9cb7b9cba8055179115ce17msarett const uint8_t task = buffer.get()[currByte++]; 933741143878b23d22cd9cb7b9cba8055179115ce17msarett 934741143878b23d22cd9cb7b9cba8055179115ce17msarett // If we have reached a row that is beyond the image size, and the RLE 935741143878b23d22cd9cb7b9cba8055179115ce17msarett // code does not indicate end of file, abort and signal a warning. 936741143878b23d22cd9cb7b9cba8055179115ce17msarett if (y >= height && (flag != RLE_ESCAPE || (task != RLE_EOF))) { 937230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Warning: invalid RLE input.\n"); 938741143878b23d22cd9cb7b9cba8055179115ce17msarett return kIncompleteInput; 939741143878b23d22cd9cb7b9cba8055179115ce17msarett } 940741143878b23d22cd9cb7b9cba8055179115ce17msarett 941741143878b23d22cd9cb7b9cba8055179115ce17msarett // Perform decoding 942741143878b23d22cd9cb7b9cba8055179115ce17msarett if (RLE_ESCAPE == flag) { 943741143878b23d22cd9cb7b9cba8055179115ce17msarett switch (task) { 944741143878b23d22cd9cb7b9cba8055179115ce17msarett case RLE_EOL: 945741143878b23d22cd9cb7b9cba8055179115ce17msarett x = 0; 946741143878b23d22cd9cb7b9cba8055179115ce17msarett y++; 947741143878b23d22cd9cb7b9cba8055179115ce17msarett break; 948741143878b23d22cd9cb7b9cba8055179115ce17msarett case RLE_EOF: 949741143878b23d22cd9cb7b9cba8055179115ce17msarett return kSuccess; 950741143878b23d22cd9cb7b9cba8055179115ce17msarett case RLE_DELTA: { 951741143878b23d22cd9cb7b9cba8055179115ce17msarett // Two bytes are needed to specify delta 952741143878b23d22cd9cb7b9cba8055179115ce17msarett if ((int) totalBytes - currByte < 2) { 953230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Warning: incomplete RLE input\n"); 954741143878b23d22cd9cb7b9cba8055179115ce17msarett return kIncompleteInput; 955741143878b23d22cd9cb7b9cba8055179115ce17msarett } 956741143878b23d22cd9cb7b9cba8055179115ce17msarett // Modify x and y 957741143878b23d22cd9cb7b9cba8055179115ce17msarett const uint8_t dx = buffer.get()[currByte++]; 958741143878b23d22cd9cb7b9cba8055179115ce17msarett const uint8_t dy = buffer.get()[currByte++]; 959741143878b23d22cd9cb7b9cba8055179115ce17msarett x += dx; 960741143878b23d22cd9cb7b9cba8055179115ce17msarett y += dy; 961741143878b23d22cd9cb7b9cba8055179115ce17msarett if (x > width || y > height) { 962230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Warning: invalid RLE input.\n"); 963741143878b23d22cd9cb7b9cba8055179115ce17msarett return kIncompleteInput; 964741143878b23d22cd9cb7b9cba8055179115ce17msarett } 965741143878b23d22cd9cb7b9cba8055179115ce17msarett break; 966741143878b23d22cd9cb7b9cba8055179115ce17msarett } 967741143878b23d22cd9cb7b9cba8055179115ce17msarett default: { 968741143878b23d22cd9cb7b9cba8055179115ce17msarett // If task does not match any of the above signals, it 969741143878b23d22cd9cb7b9cba8055179115ce17msarett // indicates that we have a sequence of non-RLE pixels. 970741143878b23d22cd9cb7b9cba8055179115ce17msarett // Furthermore, the value of task is equal to the number 971741143878b23d22cd9cb7b9cba8055179115ce17msarett // of pixels to interpret. 972741143878b23d22cd9cb7b9cba8055179115ce17msarett uint8_t numPixels = task; 973741143878b23d22cd9cb7b9cba8055179115ce17msarett const size_t rowBytes = compute_row_bytes(numPixels, 974741143878b23d22cd9cb7b9cba8055179115ce17msarett fBitsPerPixel); 975741143878b23d22cd9cb7b9cba8055179115ce17msarett // Abort if setting numPixels moves us off the edge of the 976741143878b23d22cd9cb7b9cba8055179115ce17msarett // image. Also abort if there are not enough bytes 977741143878b23d22cd9cb7b9cba8055179115ce17msarett // remaining in the stream to set numPixels. 978741143878b23d22cd9cb7b9cba8055179115ce17msarett if (x + numPixels > width || 979741143878b23d22cd9cb7b9cba8055179115ce17msarett (int) totalBytes - currByte < SkAlign2(rowBytes)) { 980230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Warning: invalid RLE input.\n"); 981741143878b23d22cd9cb7b9cba8055179115ce17msarett return kIncompleteInput; 982741143878b23d22cd9cb7b9cba8055179115ce17msarett } 983741143878b23d22cd9cb7b9cba8055179115ce17msarett // Set numPixels number of pixels 984741143878b23d22cd9cb7b9cba8055179115ce17msarett while (numPixels > 0) { 985741143878b23d22cd9cb7b9cba8055179115ce17msarett switch(fBitsPerPixel) { 986741143878b23d22cd9cb7b9cba8055179115ce17msarett case 4: { 987741143878b23d22cd9cb7b9cba8055179115ce17msarett SkASSERT(currByte < totalBytes); 988741143878b23d22cd9cb7b9cba8055179115ce17msarett uint8_t val = buffer.get()[currByte++]; 989438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett setRLEPixel(dst, dstRowBytes, dstInfo, x++, 990eed039b5ffbdff958053ac80b09451ad6caa1787msarett y, val >> 4); 991741143878b23d22cd9cb7b9cba8055179115ce17msarett numPixels--; 992741143878b23d22cd9cb7b9cba8055179115ce17msarett if (numPixels != 0) { 993438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett setRLEPixel(dst, dstRowBytes, dstInfo, 994741143878b23d22cd9cb7b9cba8055179115ce17msarett x++, y, val & 0xF); 995741143878b23d22cd9cb7b9cba8055179115ce17msarett numPixels--; 996741143878b23d22cd9cb7b9cba8055179115ce17msarett } 997741143878b23d22cd9cb7b9cba8055179115ce17msarett break; 998741143878b23d22cd9cb7b9cba8055179115ce17msarett } 999741143878b23d22cd9cb7b9cba8055179115ce17msarett case 8: 1000741143878b23d22cd9cb7b9cba8055179115ce17msarett SkASSERT(currByte < totalBytes); 1001438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett setRLEPixel(dst, dstRowBytes, dstInfo, x++, 1002eed039b5ffbdff958053ac80b09451ad6caa1787msarett y, buffer.get()[currByte++]); 1003741143878b23d22cd9cb7b9cba8055179115ce17msarett numPixels--; 1004741143878b23d22cd9cb7b9cba8055179115ce17msarett break; 1005741143878b23d22cd9cb7b9cba8055179115ce17msarett case 24: { 1006741143878b23d22cd9cb7b9cba8055179115ce17msarett SkASSERT(currByte + 2 < totalBytes); 1007741143878b23d22cd9cb7b9cba8055179115ce17msarett uint8_t blue = buffer.get()[currByte++]; 1008741143878b23d22cd9cb7b9cba8055179115ce17msarett uint8_t green = buffer.get()[currByte++]; 1009741143878b23d22cd9cb7b9cba8055179115ce17msarett uint8_t red = buffer.get()[currByte++]; 1010438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett setRLE24Pixel(dst, dstRowBytes, dstInfo, 1011eed039b5ffbdff958053ac80b09451ad6caa1787msarett x++, y, red, green, blue); 1012741143878b23d22cd9cb7b9cba8055179115ce17msarett numPixels--; 1013741143878b23d22cd9cb7b9cba8055179115ce17msarett } 1014741143878b23d22cd9cb7b9cba8055179115ce17msarett default: 1015741143878b23d22cd9cb7b9cba8055179115ce17msarett SkASSERT(false); 1016741143878b23d22cd9cb7b9cba8055179115ce17msarett return kInvalidInput; 1017741143878b23d22cd9cb7b9cba8055179115ce17msarett } 1018741143878b23d22cd9cb7b9cba8055179115ce17msarett } 1019741143878b23d22cd9cb7b9cba8055179115ce17msarett // Skip a byte if necessary to maintain alignment 1020741143878b23d22cd9cb7b9cba8055179115ce17msarett if (!SkIsAlign2(rowBytes)) { 1021741143878b23d22cd9cb7b9cba8055179115ce17msarett currByte++; 1022741143878b23d22cd9cb7b9cba8055179115ce17msarett } 1023741143878b23d22cd9cb7b9cba8055179115ce17msarett break; 1024741143878b23d22cd9cb7b9cba8055179115ce17msarett } 1025741143878b23d22cd9cb7b9cba8055179115ce17msarett } 1026741143878b23d22cd9cb7b9cba8055179115ce17msarett } else { 1027741143878b23d22cd9cb7b9cba8055179115ce17msarett // If the first byte read is not a flag, it indicates the number of 1028741143878b23d22cd9cb7b9cba8055179115ce17msarett // pixels to set in RLE mode. 1029741143878b23d22cd9cb7b9cba8055179115ce17msarett const uint8_t numPixels = flag; 1030741143878b23d22cd9cb7b9cba8055179115ce17msarett const int endX = SkTMin<int>(x + numPixels, width); 1031741143878b23d22cd9cb7b9cba8055179115ce17msarett 1032741143878b23d22cd9cb7b9cba8055179115ce17msarett if (24 == fBitsPerPixel) { 1033741143878b23d22cd9cb7b9cba8055179115ce17msarett // In RLE24, the second byte read is part of the pixel color. 1034741143878b23d22cd9cb7b9cba8055179115ce17msarett // There are two more required bytes to finish encoding the 1035741143878b23d22cd9cb7b9cba8055179115ce17msarett // color. 1036741143878b23d22cd9cb7b9cba8055179115ce17msarett if ((int) totalBytes - currByte < 2) { 1037230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Warning: incomplete RLE input\n"); 1038741143878b23d22cd9cb7b9cba8055179115ce17msarett return kIncompleteInput; 1039741143878b23d22cd9cb7b9cba8055179115ce17msarett } 1040741143878b23d22cd9cb7b9cba8055179115ce17msarett 1041741143878b23d22cd9cb7b9cba8055179115ce17msarett // Fill the pixels up to endX with the specified color 1042741143878b23d22cd9cb7b9cba8055179115ce17msarett uint8_t blue = task; 1043741143878b23d22cd9cb7b9cba8055179115ce17msarett uint8_t green = buffer.get()[currByte++]; 1044741143878b23d22cd9cb7b9cba8055179115ce17msarett uint8_t red = buffer.get()[currByte++]; 1045741143878b23d22cd9cb7b9cba8055179115ce17msarett while (x < endX) { 1046438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett setRLE24Pixel(dst, dstRowBytes, dstInfo, x++, y, red, 1047eed039b5ffbdff958053ac80b09451ad6caa1787msarett green, blue); 1048741143878b23d22cd9cb7b9cba8055179115ce17msarett } 1049741143878b23d22cd9cb7b9cba8055179115ce17msarett } else { 1050741143878b23d22cd9cb7b9cba8055179115ce17msarett // In RLE8 or RLE4, the second byte read gives the index in the 1051741143878b23d22cd9cb7b9cba8055179115ce17msarett // color table to look up the pixel color. 1052741143878b23d22cd9cb7b9cba8055179115ce17msarett // RLE8 has one color index that gets repeated 1053741143878b23d22cd9cb7b9cba8055179115ce17msarett // RLE4 has two color indexes in the upper and lower 4 bits of 1054741143878b23d22cd9cb7b9cba8055179115ce17msarett // the bytes, which are alternated 1055741143878b23d22cd9cb7b9cba8055179115ce17msarett uint8_t indices[2] = { task, task }; 1056741143878b23d22cd9cb7b9cba8055179115ce17msarett if (4 == fBitsPerPixel) { 1057741143878b23d22cd9cb7b9cba8055179115ce17msarett indices[0] >>= 4; 1058741143878b23d22cd9cb7b9cba8055179115ce17msarett indices[1] &= 0xf; 1059741143878b23d22cd9cb7b9cba8055179115ce17msarett } 1060741143878b23d22cd9cb7b9cba8055179115ce17msarett 1061741143878b23d22cd9cb7b9cba8055179115ce17msarett // Set the indicated number of pixels 1062741143878b23d22cd9cb7b9cba8055179115ce17msarett for (int which = 0; x < endX; x++) { 1063438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett setRLEPixel(dst, dstRowBytes, dstInfo, x, y, 1064741143878b23d22cd9cb7b9cba8055179115ce17msarett indices[which]); 1065741143878b23d22cd9cb7b9cba8055179115ce17msarett which = !which; 1066741143878b23d22cd9cb7b9cba8055179115ce17msarett } 1067741143878b23d22cd9cb7b9cba8055179115ce17msarett } 1068741143878b23d22cd9cb7b9cba8055179115ce17msarett } 1069741143878b23d22cd9cb7b9cba8055179115ce17msarett } 1070741143878b23d22cd9cb7b9cba8055179115ce17msarett} 1071741143878b23d22cd9cb7b9cba8055179115ce17msarett 1072741143878b23d22cd9cb7b9cba8055179115ce17msarett/* 1073741143878b23d22cd9cb7b9cba8055179115ce17msarett * 1074741143878b23d22cd9cb7b9cba8055179115ce17msarett * Performs the bitmap decoding for standard input format 1075741143878b23d22cd9cb7b9cba8055179115ce17msarett * 1076741143878b23d22cd9cb7b9cba8055179115ce17msarett */ 1077741143878b23d22cd9cb7b9cba8055179115ce17msarettSkCodec::Result SkBmpCodec::decode(const SkImageInfo& dstInfo, 10783c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett void* dst, size_t dstRowBytes, 10793c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett const Options& opts) { 1080741143878b23d22cd9cb7b9cba8055179115ce17msarett // Set constant values 1081741143878b23d22cd9cb7b9cba8055179115ce17msarett const int width = dstInfo.width(); 1082741143878b23d22cd9cb7b9cba8055179115ce17msarett const int height = dstInfo.height(); 1083741143878b23d22cd9cb7b9cba8055179115ce17msarett const size_t rowBytes = SkAlign4(compute_row_bytes(width, fBitsPerPixel)); 1084741143878b23d22cd9cb7b9cba8055179115ce17msarett 1085e16b04aa6041efb6507546547737e9603fa1606emsarett // Get swizzler configuration and choose the fill value for failures. We will use 1086e16b04aa6041efb6507546547737e9603fa1606emsarett // zero as the default palette index, black for opaque images, and transparent for 1087e16b04aa6041efb6507546547737e9603fa1606emsarett // non-opaque images. 1088741143878b23d22cd9cb7b9cba8055179115ce17msarett SkSwizzler::SrcConfig config; 1089e16b04aa6041efb6507546547737e9603fa1606emsarett uint32_t fillColorOrIndex; 1090e16b04aa6041efb6507546547737e9603fa1606emsarett bool zeroFill = true; 1091741143878b23d22cd9cb7b9cba8055179115ce17msarett switch (fBitsPerPixel) { 1092741143878b23d22cd9cb7b9cba8055179115ce17msarett case 1: 1093741143878b23d22cd9cb7b9cba8055179115ce17msarett config = SkSwizzler::kIndex1; 1094e16b04aa6041efb6507546547737e9603fa1606emsarett fillColorOrIndex = 0; 1095741143878b23d22cd9cb7b9cba8055179115ce17msarett break; 1096741143878b23d22cd9cb7b9cba8055179115ce17msarett case 2: 1097741143878b23d22cd9cb7b9cba8055179115ce17msarett config = SkSwizzler::kIndex2; 1098e16b04aa6041efb6507546547737e9603fa1606emsarett fillColorOrIndex = 0; 1099741143878b23d22cd9cb7b9cba8055179115ce17msarett break; 1100741143878b23d22cd9cb7b9cba8055179115ce17msarett case 4: 1101741143878b23d22cd9cb7b9cba8055179115ce17msarett config = SkSwizzler::kIndex4; 1102e16b04aa6041efb6507546547737e9603fa1606emsarett fillColorOrIndex = 0; 1103741143878b23d22cd9cb7b9cba8055179115ce17msarett break; 1104741143878b23d22cd9cb7b9cba8055179115ce17msarett case 8: 1105741143878b23d22cd9cb7b9cba8055179115ce17msarett config = SkSwizzler::kIndex; 1106e16b04aa6041efb6507546547737e9603fa1606emsarett fillColorOrIndex = 0; 1107741143878b23d22cd9cb7b9cba8055179115ce17msarett break; 1108741143878b23d22cd9cb7b9cba8055179115ce17msarett case 24: 1109741143878b23d22cd9cb7b9cba8055179115ce17msarett config = SkSwizzler::kBGR; 1110e16b04aa6041efb6507546547737e9603fa1606emsarett fillColorOrIndex = SK_ColorBLACK; 1111e16b04aa6041efb6507546547737e9603fa1606emsarett zeroFill = false; 1112741143878b23d22cd9cb7b9cba8055179115ce17msarett break; 1113741143878b23d22cd9cb7b9cba8055179115ce17msarett case 32: 1114eed039b5ffbdff958053ac80b09451ad6caa1787msarett if (kOpaque_SkAlphaType == dstInfo.alphaType()) { 1115741143878b23d22cd9cb7b9cba8055179115ce17msarett config = SkSwizzler::kBGRX; 1116e16b04aa6041efb6507546547737e9603fa1606emsarett fillColorOrIndex = SK_ColorBLACK; 1117e16b04aa6041efb6507546547737e9603fa1606emsarett zeroFill = false; 1118741143878b23d22cd9cb7b9cba8055179115ce17msarett } else { 1119741143878b23d22cd9cb7b9cba8055179115ce17msarett config = SkSwizzler::kBGRA; 1120e16b04aa6041efb6507546547737e9603fa1606emsarett fillColorOrIndex = SK_ColorTRANSPARENT; 1121741143878b23d22cd9cb7b9cba8055179115ce17msarett } 1122741143878b23d22cd9cb7b9cba8055179115ce17msarett break; 1123741143878b23d22cd9cb7b9cba8055179115ce17msarett default: 1124741143878b23d22cd9cb7b9cba8055179115ce17msarett SkASSERT(false); 1125741143878b23d22cd9cb7b9cba8055179115ce17msarett return kInvalidInput; 1126741143878b23d22cd9cb7b9cba8055179115ce17msarett } 1127741143878b23d22cd9cb7b9cba8055179115ce17msarett 11283c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett // Get a pointer to the color table if it exists 11293c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett const SkPMColor* colorPtr = NULL != fColorTable.get() ? fColorTable->readColors() : NULL; 11303c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett 1131741143878b23d22cd9cb7b9cba8055179115ce17msarett // Create swizzler 1132eed039b5ffbdff958053ac80b09451ad6caa1787msarett SkAutoTDelete<SkSwizzler> swizzler(SkSwizzler::CreateSwizzler(config, 11333c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett colorPtr, dstInfo, dst, dstRowBytes, 1134eed039b5ffbdff958053ac80b09451ad6caa1787msarett SkImageGenerator::kNo_ZeroInitialized)); 1135741143878b23d22cd9cb7b9cba8055179115ce17msarett 1136741143878b23d22cd9cb7b9cba8055179115ce17msarett // Allocate space for a row buffer and a source for the swizzler 1137741143878b23d22cd9cb7b9cba8055179115ce17msarett SkAutoTDeleteArray<uint8_t> srcBuffer(SkNEW_ARRAY(uint8_t, rowBytes)); 1138741143878b23d22cd9cb7b9cba8055179115ce17msarett 1139741143878b23d22cd9cb7b9cba8055179115ce17msarett // Iterate over rows of the image 1140741143878b23d22cd9cb7b9cba8055179115ce17msarett // FIXME: bool transparent = true; 1141741143878b23d22cd9cb7b9cba8055179115ce17msarett for (int y = 0; y < height; y++) { 1142741143878b23d22cd9cb7b9cba8055179115ce17msarett // Read a row of the input 1143741143878b23d22cd9cb7b9cba8055179115ce17msarett if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) { 1144230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Warning: incomplete input stream.\n"); 11453c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett // Fill the destination image on failure 1146e16b04aa6041efb6507546547737e9603fa1606emsarett if (kNo_ZeroInitialized == opts.fZeroInitialized || !zeroFill) { 11473c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett void* dstStart = get_dst_start_row(dst, dstRowBytes, y, fRowOrder); 1148e16b04aa6041efb6507546547737e9603fa1606emsarett SkSwizzler::Fill(dstStart, dstInfo, dstRowBytes, dstInfo.height() - y, 1149e16b04aa6041efb6507546547737e9603fa1606emsarett fillColorOrIndex, colorPtr); 11503c309db75bb8c4c2b58724a0e2f6f3b387ca842cmsarett } 1151741143878b23d22cd9cb7b9cba8055179115ce17msarett return kIncompleteInput; 1152741143878b23d22cd9cb7b9cba8055179115ce17msarett } 1153741143878b23d22cd9cb7b9cba8055179115ce17msarett 1154741143878b23d22cd9cb7b9cba8055179115ce17msarett // Decode the row in destination format 1155741143878b23d22cd9cb7b9cba8055179115ce17msarett uint32_t row; 1156741143878b23d22cd9cb7b9cba8055179115ce17msarett if (kTopDown_RowOrder == fRowOrder) { 1157741143878b23d22cd9cb7b9cba8055179115ce17msarett row = y; 1158741143878b23d22cd9cb7b9cba8055179115ce17msarett } else { 1159741143878b23d22cd9cb7b9cba8055179115ce17msarett row = height - 1 - y; 1160741143878b23d22cd9cb7b9cba8055179115ce17msarett } 1161741143878b23d22cd9cb7b9cba8055179115ce17msarett 1162741143878b23d22cd9cb7b9cba8055179115ce17msarett swizzler->next(srcBuffer.get(), row); 1163741143878b23d22cd9cb7b9cba8055179115ce17msarett // FIXME: SkSwizzler::ResultAlpha r = 1164741143878b23d22cd9cb7b9cba8055179115ce17msarett // swizzler->next(srcBuffer.get(), row); 1165741143878b23d22cd9cb7b9cba8055179115ce17msarett // FIXME: transparent &= SkSwizzler::IsTransparent(r); 1166741143878b23d22cd9cb7b9cba8055179115ce17msarett } 1167741143878b23d22cd9cb7b9cba8055179115ce17msarett 1168741143878b23d22cd9cb7b9cba8055179115ce17msarett // FIXME: This code exists to match the behavior in the chromium decoder 1169741143878b23d22cd9cb7b9cba8055179115ce17msarett // and to follow the bmp specification as it relates to alpha masks. It is 1170741143878b23d22cd9cb7b9cba8055179115ce17msarett // commented out because we have yet to discover a test image that provides 1171741143878b23d22cd9cb7b9cba8055179115ce17msarett // an alpha mask and uses this decode mode. 1172741143878b23d22cd9cb7b9cba8055179115ce17msarett 1173741143878b23d22cd9cb7b9cba8055179115ce17msarett // Now we adjust the output image with some additional behavior that 1174741143878b23d22cd9cb7b9cba8055179115ce17msarett // SkSwizzler does not support. Firstly, all bmp images that contain 1175741143878b23d22cd9cb7b9cba8055179115ce17msarett // alpha are masked by the alpha mask. Secondly, many fully transparent 1176438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett // bmp images are intended to be opaque. Here, we make those corrections 1177438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett // in the kN32 case. 1178741143878b23d22cd9cb7b9cba8055179115ce17msarett /* 1179741143878b23d22cd9cb7b9cba8055179115ce17msarett SkPMColor* dstRow = (SkPMColor*) dst; 1180741143878b23d22cd9cb7b9cba8055179115ce17msarett if (SkSwizzler::kBGRA == config) { 1181741143878b23d22cd9cb7b9cba8055179115ce17msarett for (int y = 0; y < height; y++) { 1182741143878b23d22cd9cb7b9cba8055179115ce17msarett for (int x = 0; x < width; x++) { 1183741143878b23d22cd9cb7b9cba8055179115ce17msarett if (transparent) { 1184741143878b23d22cd9cb7b9cba8055179115ce17msarett dstRow[x] |= 0xFF000000; 1185741143878b23d22cd9cb7b9cba8055179115ce17msarett } else { 1186741143878b23d22cd9cb7b9cba8055179115ce17msarett dstRow[x] &= alphaMask; 1187741143878b23d22cd9cb7b9cba8055179115ce17msarett } 1188741143878b23d22cd9cb7b9cba8055179115ce17msarett dstRow = SkTAddOffset<SkPMColor>(dstRow, dstRowBytes); 1189741143878b23d22cd9cb7b9cba8055179115ce17msarett } 1190741143878b23d22cd9cb7b9cba8055179115ce17msarett } 1191741143878b23d22cd9cb7b9cba8055179115ce17msarett } 1192741143878b23d22cd9cb7b9cba8055179115ce17msarett */ 1193741143878b23d22cd9cb7b9cba8055179115ce17msarett 11949bde918754bc292469d801f156f3b626eb3db780msarett // Finally, apply the AND mask for bmp-in-ico images 11959bde918754bc292469d801f156f3b626eb3db780msarett if (fIsIco) { 11969bde918754bc292469d801f156f3b626eb3db780msarett // The AND mask is always 1 bit per pixel 11979bde918754bc292469d801f156f3b626eb3db780msarett const size_t rowBytes = SkAlign4(compute_row_bytes(width, 1)); 11989bde918754bc292469d801f156f3b626eb3db780msarett 11999bde918754bc292469d801f156f3b626eb3db780msarett SkPMColor* dstPtr = (SkPMColor*) dst; 12009bde918754bc292469d801f156f3b626eb3db780msarett for (int y = 0; y < height; y++) { 12019bde918754bc292469d801f156f3b626eb3db780msarett // The srcBuffer will at least be large enough 12029bde918754bc292469d801f156f3b626eb3db780msarett if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) { 1203230d4ac7013f79a3e79efd4452d7fa5c3f508660scroggo SkCodecPrintf("Warning: incomplete AND mask for bmp-in-ico.\n"); 12049bde918754bc292469d801f156f3b626eb3db780msarett return kIncompleteInput; 12059bde918754bc292469d801f156f3b626eb3db780msarett } 12069bde918754bc292469d801f156f3b626eb3db780msarett 12079bde918754bc292469d801f156f3b626eb3db780msarett int row; 12089bde918754bc292469d801f156f3b626eb3db780msarett if (kBottomUp_RowOrder == fRowOrder) { 12099bde918754bc292469d801f156f3b626eb3db780msarett row = height - y - 1; 12109bde918754bc292469d801f156f3b626eb3db780msarett } else { 12119bde918754bc292469d801f156f3b626eb3db780msarett row = y; 12129bde918754bc292469d801f156f3b626eb3db780msarett } 12139bde918754bc292469d801f156f3b626eb3db780msarett 12149bde918754bc292469d801f156f3b626eb3db780msarett SkPMColor* dstRow = 12159bde918754bc292469d801f156f3b626eb3db780msarett SkTAddOffset<SkPMColor>(dstPtr, row * dstRowBytes); 12169bde918754bc292469d801f156f3b626eb3db780msarett 12179bde918754bc292469d801f156f3b626eb3db780msarett for (int x = 0; x < width; x++) { 12189bde918754bc292469d801f156f3b626eb3db780msarett int quotient; 12199bde918754bc292469d801f156f3b626eb3db780msarett int modulus; 12209bde918754bc292469d801f156f3b626eb3db780msarett SkTDivMod(x, 8, "ient, &modulus); 12219bde918754bc292469d801f156f3b626eb3db780msarett uint32_t shift = 7 - modulus; 12229bde918754bc292469d801f156f3b626eb3db780msarett uint32_t alphaBit = 12239bde918754bc292469d801f156f3b626eb3db780msarett (srcBuffer.get()[quotient] >> shift) & 0x1; 12249bde918754bc292469d801f156f3b626eb3db780msarett dstRow[x] &= alphaBit - 1; 12259bde918754bc292469d801f156f3b626eb3db780msarett } 12269bde918754bc292469d801f156f3b626eb3db780msarett } 12279bde918754bc292469d801f156f3b626eb3db780msarett } 12289bde918754bc292469d801f156f3b626eb3db780msarett 1229741143878b23d22cd9cb7b9cba8055179115ce17msarett // Finished decoding the entire image 1230741143878b23d22cd9cb7b9cba8055179115ce17msarett return kSuccess; 1231741143878b23d22cd9cb7b9cba8055179115ce17msarett} 1232