blob: 66ad0caa2b09b90fdd2449eac1c505596f93031e [file] [log] [blame]
msarett74114382015-03-16 11:55:18 -07001/*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
msarettb46e5e22015-07-30 11:36:40 -07008#include "SkBmpCodec.h"
msarett4ab9d5f2015-08-06 15:34:42 -07009#include "SkBmpMaskCodec.h"
10#include "SkBmpRLECodec.h"
11#include "SkBmpStandardCodec.h"
msarett74114382015-03-16 11:55:18 -070012#include "SkCodecPriv.h"
13#include "SkColorPriv.h"
14#include "SkStream.h"
15
16/*
msarett74114382015-03-16 11:55:18 -070017 * Defines the version and type of the second bitmap header
msarett74114382015-03-16 11:55:18 -070018 */
msarett4ab9d5f2015-08-06 15:34:42 -070019enum BmpHeaderType {
20 kInfoV1_BmpHeaderType,
21 kInfoV2_BmpHeaderType,
22 kInfoV3_BmpHeaderType,
23 kInfoV4_BmpHeaderType,
24 kInfoV5_BmpHeaderType,
25 kOS2V1_BmpHeaderType,
26 kOS2VX_BmpHeaderType,
27 kUnknown_BmpHeaderType
msarett74114382015-03-16 11:55:18 -070028};
29
30/*
msarett74114382015-03-16 11:55:18 -070031 * Possible bitmap compression types
msarett74114382015-03-16 11:55:18 -070032 */
msarett4ab9d5f2015-08-06 15:34:42 -070033enum BmpCompressionMethod {
34 kNone_BmpCompressionMethod = 0,
35 k8BitRLE_BmpCompressionMethod = 1,
36 k4BitRLE_BmpCompressionMethod = 2,
37 kBitMasks_BmpCompressionMethod = 3,
38 kJpeg_BmpCompressionMethod = 4,
39 kPng_BmpCompressionMethod = 5,
40 kAlphaBitMasks_BmpCompressionMethod = 6,
41 kCMYK_BmpCompressionMethod = 11,
42 kCMYK8BitRLE_BmpCompressionMethod = 12,
43 kCMYK4BitRLE_BmpCompressionMethod = 13
msarett74114382015-03-16 11:55:18 -070044};
45
46/*
msarett4ab9d5f2015-08-06 15:34:42 -070047 * Used to define the input format of the bmp
48 */
49enum BmpInputFormat {
50 kStandard_BmpInputFormat,
51 kRLE_BmpInputFormat,
52 kBitMask_BmpInputFormat,
53 kUnknown_BmpInputFormat
54};
55
56/*
msarett74114382015-03-16 11:55:18 -070057 * Checks the start of the stream to see if the image is a bitmap
msarett74114382015-03-16 11:55:18 -070058 */
scroggodb30be22015-12-08 18:54:13 -080059bool SkBmpCodec::IsBmp(const void* buffer, size_t bytesRead) {
msarett74114382015-03-16 11:55:18 -070060 // TODO: Support "IC", "PT", "CI", "CP", "BA"
msarett74114382015-03-16 11:55:18 -070061 const char bmpSig[] = { 'B', 'M' };
scroggodb30be22015-12-08 18:54:13 -080062 return bytesRead >= sizeof(bmpSig) && !memcmp(buffer, bmpSig, sizeof(bmpSig));
msarett74114382015-03-16 11:55:18 -070063}
64
65/*
msarett74114382015-03-16 11:55:18 -070066 * Assumes IsBmp was called and returned true
msarett9bde9182015-03-25 05:27:48 -070067 * Creates a bmp decoder
msarett74114382015-03-16 11:55:18 -070068 * Reads enough of the stream to determine the image format
msarett74114382015-03-16 11:55:18 -070069 */
70SkCodec* SkBmpCodec::NewFromStream(SkStream* stream) {
msarett9bde9182015-03-25 05:27:48 -070071 return SkBmpCodec::NewFromStream(stream, false);
72}
73
74/*
msarett9bde9182015-03-25 05:27:48 -070075 * Creates a bmp decoder for a bmp embedded in ico
76 * Reads enough of the stream to determine the image format
msarett9bde9182015-03-25 05:27:48 -070077 */
78SkCodec* SkBmpCodec::NewFromIco(SkStream* stream) {
79 return SkBmpCodec::NewFromStream(stream, true);
80}
81
Leon Scroggins III0b24cbd2016-12-15 15:58:22 -050082// Header size constants
83static const uint32_t kBmpHeaderBytes = 14;
84static const uint32_t kBmpHeaderBytesPlusFour = kBmpHeaderBytes + 4;
85static const uint32_t kBmpOS2V1Bytes = 12;
86static const uint32_t kBmpOS2V2Bytes = 64;
87static const uint32_t kBmpInfoBaseBytes = 16;
88static const uint32_t kBmpInfoV1Bytes = 40;
89static const uint32_t kBmpInfoV2Bytes = 52;
90static const uint32_t kBmpInfoV3Bytes = 56;
91static const uint32_t kBmpInfoV4Bytes = 108;
92static const uint32_t kBmpInfoV5Bytes = 124;
93static const uint32_t kBmpMaskBytes = 12;
94
95static BmpHeaderType get_header_type(size_t infoBytes) {
96 if (infoBytes >= kBmpInfoBaseBytes) {
97 // Check the version of the header
98 switch (infoBytes) {
99 case kBmpInfoV1Bytes:
100 return kInfoV1_BmpHeaderType;
101 case kBmpInfoV2Bytes:
102 return kInfoV2_BmpHeaderType;
103 case kBmpInfoV3Bytes:
104 return kInfoV3_BmpHeaderType;
105 case kBmpInfoV4Bytes:
106 return kInfoV4_BmpHeaderType;
107 case kBmpInfoV5Bytes:
108 return kInfoV5_BmpHeaderType;
109 case 16:
110 case 20:
111 case 24:
112 case 28:
113 case 32:
114 case 36:
115 case 42:
116 case 46:
117 case 48:
118 case 60:
119 case kBmpOS2V2Bytes:
120 return kOS2VX_BmpHeaderType;
121 default:
122 SkCodecPrintf("Error: unknown bmp header format.\n");
123 return kUnknown_BmpHeaderType;
124 }
125 } if (infoBytes >= kBmpOS2V1Bytes) {
126 // The OS2V1 is treated separately because it has a unique format
127 return kOS2V1_BmpHeaderType;
128 } else {
129 // There are no valid bmp headers
130 SkCodecPrintf("Error: second bitmap header size is invalid.\n");
131 return kUnknown_BmpHeaderType;
132 }
133}
134
msarett9bde9182015-03-25 05:27:48 -0700135/*
scroggo79e378d2015-04-01 07:39:40 -0700136 * Read enough of the stream to initialize the SkBmpCodec. Returns a bool
137 * representing success or failure. If it returned true, and codecOut was
halcanary96fcdcc2015-08-27 07:41:13 -0700138 * not nullptr, it will be set to a new SkBmpCodec.
scroggo0a7e69c2015-04-03 07:22:22 -0700139 * Does *not* take ownership of the passed in SkStream.
msarett9bde9182015-03-25 05:27:48 -0700140 */
msarett4ab9d5f2015-08-06 15:34:42 -0700141bool SkBmpCodec::ReadHeader(SkStream* stream, bool inIco, SkCodec** codecOut) {
tomhudson7aa846c2015-03-24 13:47:41 -0700142 // The total bytes in the bmp file
msarett9bde9182015-03-25 05:27:48 -0700143 // We only need to use this value for RLE decoding, so we will only
144 // check that it is valid in the RLE case.
145 uint32_t totalBytes;
tomhudson7aa846c2015-03-24 13:47:41 -0700146 // The offset from the start of the file where the pixel data begins
msarett9bde9182015-03-25 05:27:48 -0700147 uint32_t offset;
148 // The size of the second (info) header in bytes
149 uint32_t infoBytes;
150
151 // Bmps embedded in Icos skip the first Bmp header
msarett4ab9d5f2015-08-06 15:34:42 -0700152 if (!inIco) {
msarett9bde9182015-03-25 05:27:48 -0700153 // Read the first header and the size of the second header
Ben Wagner7ecc5962016-11-02 17:07:33 -0400154 std::unique_ptr<uint8_t[]> hBuffer(new uint8_t[kBmpHeaderBytesPlusFour]);
msarett9bde9182015-03-25 05:27:48 -0700155 if (stream->read(hBuffer.get(), kBmpHeaderBytesPlusFour) !=
156 kBmpHeaderBytesPlusFour) {
scroggo230d4ac2015-03-26 07:15:55 -0700157 SkCodecPrintf("Error: unable to read first bitmap header.\n");
scroggo79e378d2015-04-01 07:39:40 -0700158 return false;
msarett9bde9182015-03-25 05:27:48 -0700159 }
160
161 totalBytes = get_int(hBuffer.get(), 2);
162 offset = get_int(hBuffer.get(), 10);
163 if (offset < kBmpHeaderBytes + kBmpOS2V1Bytes) {
scroggo230d4ac2015-03-26 07:15:55 -0700164 SkCodecPrintf("Error: invalid starting location for pixel data\n");
scroggo79e378d2015-04-01 07:39:40 -0700165 return false;
msarett9bde9182015-03-25 05:27:48 -0700166 }
167
168 // The size of the second (info) header in bytes
169 // The size is the first field of the second header, so we have already
170 // read the first four infoBytes.
171 infoBytes = get_int(hBuffer.get(), 14);
172 if (infoBytes < kBmpOS2V1Bytes) {
scroggo230d4ac2015-03-26 07:15:55 -0700173 SkCodecPrintf("Error: invalid second header size.\n");
scroggo79e378d2015-04-01 07:39:40 -0700174 return false;
msarett9bde9182015-03-25 05:27:48 -0700175 }
176 } else {
177 // This value is only used by RLE compression. Bmp in Ico files do not
178 // use RLE. If the compression field is incorrectly signaled as RLE,
179 // we will catch this and signal an error below.
180 totalBytes = 0;
181
182 // Bmps in Ico cannot specify an offset. We will always assume that
183 // pixel data begins immediately after the color table. This value
184 // will be corrected below.
185 offset = 0;
186
187 // Read the size of the second header
Ben Wagner7ecc5962016-11-02 17:07:33 -0400188 std::unique_ptr<uint8_t[]> hBuffer(new uint8_t[4]);
msarett9bde9182015-03-25 05:27:48 -0700189 if (stream->read(hBuffer.get(), 4) != 4) {
scroggo230d4ac2015-03-26 07:15:55 -0700190 SkCodecPrintf("Error: unable to read size of second bitmap header.\n");
scroggo79e378d2015-04-01 07:39:40 -0700191 return false;
msarett9bde9182015-03-25 05:27:48 -0700192 }
193 infoBytes = get_int(hBuffer.get(), 0);
194 if (infoBytes < kBmpOS2V1Bytes) {
scroggo230d4ac2015-03-26 07:15:55 -0700195 SkCodecPrintf("Error: invalid second header size.\n");
scroggo79e378d2015-04-01 07:39:40 -0700196 return false;
msarett9bde9182015-03-25 05:27:48 -0700197 }
tomhudson7aa846c2015-03-24 13:47:41 -0700198 }
199
Leon Scroggins III0b24cbd2016-12-15 15:58:22 -0500200 // Determine image information depending on second header format
201 const BmpHeaderType headerType = get_header_type(infoBytes);
202 if (kUnknown_BmpHeaderType == headerType) {
203 return false;
204 }
205
msarett9bde9182015-03-25 05:27:48 -0700206 // We already read the first four bytes of the info header to get the size
msarett74114382015-03-16 11:55:18 -0700207 const uint32_t infoBytesRemaining = infoBytes - 4;
msarett74114382015-03-16 11:55:18 -0700208
209 // Read the second header
Ben Wagner7ecc5962016-11-02 17:07:33 -0400210 std::unique_ptr<uint8_t[]> iBuffer(new uint8_t[infoBytesRemaining]);
msarett74114382015-03-16 11:55:18 -0700211 if (stream->read(iBuffer.get(), infoBytesRemaining) != infoBytesRemaining) {
scroggo230d4ac2015-03-26 07:15:55 -0700212 SkCodecPrintf("Error: unable to read second bitmap header.\n");
scroggo79e378d2015-04-01 07:39:40 -0700213 return false;
msarett74114382015-03-16 11:55:18 -0700214 }
215
216 // The number of bits used per pixel in the pixel data
217 uint16_t bitsPerPixel;
218
219 // The compression method for the pixel data
msarett4ab9d5f2015-08-06 15:34:42 -0700220 uint32_t compression = kNone_BmpCompressionMethod;
msarett74114382015-03-16 11:55:18 -0700221
222 // Number of colors in the color table, defaults to 0 or max (see below)
223 uint32_t numColors = 0;
224
225 // Bytes per color in the color table, early versions use 3, most use 4
226 uint32_t bytesPerColor;
227
228 // The image width and height
229 int width, height;
230
Leon Scroggins III0b24cbd2016-12-15 15:58:22 -0500231 switch (headerType) {
232 case kInfoV1_BmpHeaderType:
233 case kInfoV2_BmpHeaderType:
234 case kInfoV3_BmpHeaderType:
235 case kInfoV4_BmpHeaderType:
236 case kInfoV5_BmpHeaderType:
237 case kOS2VX_BmpHeaderType:
238 // We check the size of the header before entering the if statement.
239 // We should not reach this point unless the size is large enough for
240 // these required fields.
241 SkASSERT(infoBytesRemaining >= 12);
242 width = get_int(iBuffer.get(), 0);
243 height = get_int(iBuffer.get(), 4);
244 bitsPerPixel = get_short(iBuffer.get(), 10);
msarett74114382015-03-16 11:55:18 -0700245
Leon Scroggins III0b24cbd2016-12-15 15:58:22 -0500246 // Some versions do not have these fields, so we check before
247 // overwriting the default value.
248 if (infoBytesRemaining >= 16) {
249 compression = get_int(iBuffer.get(), 12);
250 if (infoBytesRemaining >= 32) {
251 numColors = get_int(iBuffer.get(), 28);
252 }
msarett74114382015-03-16 11:55:18 -0700253 }
msarett74114382015-03-16 11:55:18 -0700254
Leon Scroggins III0b24cbd2016-12-15 15:58:22 -0500255 // All of the headers that reach this point, store color table entries
256 // using 4 bytes per pixel.
257 bytesPerColor = 4;
258 break;
259 case kOS2V1_BmpHeaderType:
260 // The OS2V1 is treated separately because it has a unique format
261 width = (int) get_short(iBuffer.get(), 0);
262 height = (int) get_short(iBuffer.get(), 2);
263 bitsPerPixel = get_short(iBuffer.get(), 6);
264 bytesPerColor = 3;
265 break;
266 case kUnknown_BmpHeaderType:
267 // We'll exit above in this case.
268 SkASSERT(false);
269 return false;
msarett74114382015-03-16 11:55:18 -0700270 }
271
272 // Check for valid dimensions from header
scroggo46c57472015-09-30 08:57:13 -0700273 SkCodec::SkScanlineOrder rowOrder = SkCodec::kBottomUp_SkScanlineOrder;
msarett74114382015-03-16 11:55:18 -0700274 if (height < 0) {
275 height = -height;
scroggo46c57472015-09-30 08:57:13 -0700276 rowOrder = SkCodec::kTopDown_SkScanlineOrder;
msarett74114382015-03-16 11:55:18 -0700277 }
msarett9bde9182015-03-25 05:27:48 -0700278 // The height field for bmp in ico is double the actual height because they
279 // contain an XOR mask followed by an AND mask
msarett4ab9d5f2015-08-06 15:34:42 -0700280 if (inIco) {
msarett9bde9182015-03-25 05:27:48 -0700281 height /= 2;
282 }
msarett4b17fa32015-04-23 08:53:39 -0700283 if (width <= 0 || height <= 0) {
284 // TODO: Decide if we want to disable really large bmps as well.
285 // https://code.google.com/p/skia/issues/detail?id=3617
scroggo230d4ac2015-03-26 07:15:55 -0700286 SkCodecPrintf("Error: invalid bitmap dimensions.\n");
scroggo79e378d2015-04-01 07:39:40 -0700287 return false;
msarett74114382015-03-16 11:55:18 -0700288 }
289
290 // Create mask struct
291 SkMasks::InputMasks inputMasks;
msaretteed039b2015-03-18 11:11:19 -0700292 memset(&inputMasks, 0, sizeof(SkMasks::InputMasks));
msarett74114382015-03-16 11:55:18 -0700293
294 // Determine the input compression format and set bit masks if necessary
295 uint32_t maskBytes = 0;
msarett4ab9d5f2015-08-06 15:34:42 -0700296 BmpInputFormat inputFormat = kUnknown_BmpInputFormat;
msarett74114382015-03-16 11:55:18 -0700297 switch (compression) {
msarett4ab9d5f2015-08-06 15:34:42 -0700298 case kNone_BmpCompressionMethod:
299 inputFormat = kStandard_BmpInputFormat;
msarett1088db92016-03-22 08:58:35 -0700300
301 // In addition to more standard pixel compression formats, bmp supports
302 // the use of bit masks to determine pixel components. The standard
303 // format for representing 16-bit colors is 555 (XRRRRRGGGGGBBBBB),
304 // which does not map well to any Skia color formats. For this reason,
305 // we will always enable mask mode with 16 bits per pixel.
306 if (16 == bitsPerPixel) {
307 inputMasks.red = 0x7C00;
308 inputMasks.green = 0x03E0;
309 inputMasks.blue = 0x001F;
310 inputFormat = kBitMask_BmpInputFormat;
311 }
msarett74114382015-03-16 11:55:18 -0700312 break;
msarett4ab9d5f2015-08-06 15:34:42 -0700313 case k8BitRLE_BmpCompressionMethod:
msarett74114382015-03-16 11:55:18 -0700314 if (bitsPerPixel != 8) {
scroggo230d4ac2015-03-26 07:15:55 -0700315 SkCodecPrintf("Warning: correcting invalid bitmap format.\n");
msarett74114382015-03-16 11:55:18 -0700316 bitsPerPixel = 8;
317 }
msarett4ab9d5f2015-08-06 15:34:42 -0700318 inputFormat = kRLE_BmpInputFormat;
msarett74114382015-03-16 11:55:18 -0700319 break;
msarett4ab9d5f2015-08-06 15:34:42 -0700320 case k4BitRLE_BmpCompressionMethod:
msarett74114382015-03-16 11:55:18 -0700321 if (bitsPerPixel != 4) {
scroggo230d4ac2015-03-26 07:15:55 -0700322 SkCodecPrintf("Warning: correcting invalid bitmap format.\n");
msarett74114382015-03-16 11:55:18 -0700323 bitsPerPixel = 4;
324 }
msarett4ab9d5f2015-08-06 15:34:42 -0700325 inputFormat = kRLE_BmpInputFormat;
msarett74114382015-03-16 11:55:18 -0700326 break;
msarett4ab9d5f2015-08-06 15:34:42 -0700327 case kAlphaBitMasks_BmpCompressionMethod:
328 case kBitMasks_BmpCompressionMethod:
msarett74114382015-03-16 11:55:18 -0700329 // Load the masks
msarett4ab9d5f2015-08-06 15:34:42 -0700330 inputFormat = kBitMask_BmpInputFormat;
msarett74114382015-03-16 11:55:18 -0700331 switch (headerType) {
msarett4ab9d5f2015-08-06 15:34:42 -0700332 case kInfoV1_BmpHeaderType: {
msarett74114382015-03-16 11:55:18 -0700333 // The V1 header stores the bit masks after the header
Ben Wagner7ecc5962016-11-02 17:07:33 -0400334 std::unique_ptr<uint8_t[]> mBuffer(new uint8_t[kBmpMaskBytes]);
msarett74114382015-03-16 11:55:18 -0700335 if (stream->read(mBuffer.get(), kBmpMaskBytes) !=
336 kBmpMaskBytes) {
scroggo230d4ac2015-03-26 07:15:55 -0700337 SkCodecPrintf("Error: unable to read bit inputMasks.\n");
scroggo79e378d2015-04-01 07:39:40 -0700338 return false;
msarett74114382015-03-16 11:55:18 -0700339 }
340 maskBytes = kBmpMaskBytes;
341 inputMasks.red = get_int(mBuffer.get(), 0);
342 inputMasks.green = get_int(mBuffer.get(), 4);
343 inputMasks.blue = get_int(mBuffer.get(), 8);
344 break;
345 }
msarett4ab9d5f2015-08-06 15:34:42 -0700346 case kInfoV2_BmpHeaderType:
347 case kInfoV3_BmpHeaderType:
348 case kInfoV4_BmpHeaderType:
349 case kInfoV5_BmpHeaderType:
msarett74114382015-03-16 11:55:18 -0700350 // Header types are matched based on size. If the header
351 // is V2+, we are guaranteed to be able to read at least
352 // this size.
353 SkASSERT(infoBytesRemaining >= 48);
354 inputMasks.red = get_int(iBuffer.get(), 36);
355 inputMasks.green = get_int(iBuffer.get(), 40);
356 inputMasks.blue = get_int(iBuffer.get(), 44);
msarett1088db92016-03-22 08:58:35 -0700357
358 if (kInfoV2_BmpHeaderType == headerType ||
359 (kInfoV3_BmpHeaderType == headerType && !inIco)) {
360 break;
361 }
362
363 // V3+ bmp files introduce an alpha mask and allow the creator of the image
364 // to use the alpha channels. However, many of these images leave the
365 // alpha channel blank and expect to be rendered as opaque. This is the
366 // case for almost all V3 images, so we ignore the alpha mask. For V4+
367 // images in kMask mode, we will use the alpha mask. Additionally, V3
368 // bmp-in-ico expect us to use the alpha mask.
369 //
370 // skbug.com/4116: We should perhaps also apply the alpha mask in kStandard
371 // mode. We just haven't seen any images that expect this
372 // behavior.
373 //
374 // Header types are matched based on size. If the header is
375 // V3+, we are guaranteed to be able to read at least this size.
376 SkASSERT(infoBytesRemaining > 52);
377 inputMasks.alpha = get_int(iBuffer.get(), 48);
msarett74114382015-03-16 11:55:18 -0700378 break;
msarett4ab9d5f2015-08-06 15:34:42 -0700379 case kOS2VX_BmpHeaderType:
msarett74114382015-03-16 11:55:18 -0700380 // TODO: Decide if we intend to support this.
381 // It is unsupported in the previous version and
382 // in chromium. I have not come across a test case
383 // that uses this format.
scroggo230d4ac2015-03-26 07:15:55 -0700384 SkCodecPrintf("Error: huffman format unsupported.\n");
scroggo79e378d2015-04-01 07:39:40 -0700385 return false;
msarett74114382015-03-16 11:55:18 -0700386 default:
scroggo230d4ac2015-03-26 07:15:55 -0700387 SkCodecPrintf("Error: invalid bmp bit masks header.\n");
scroggo79e378d2015-04-01 07:39:40 -0700388 return false;
msarett74114382015-03-16 11:55:18 -0700389 }
390 break;
msarett4ab9d5f2015-08-06 15:34:42 -0700391 case kJpeg_BmpCompressionMethod:
msarett74114382015-03-16 11:55:18 -0700392 if (24 == bitsPerPixel) {
msarett4ab9d5f2015-08-06 15:34:42 -0700393 inputFormat = kRLE_BmpInputFormat;
msarett74114382015-03-16 11:55:18 -0700394 break;
395 }
396 // Fall through
msarett4ab9d5f2015-08-06 15:34:42 -0700397 case kPng_BmpCompressionMethod:
msarett74114382015-03-16 11:55:18 -0700398 // TODO: Decide if we intend to support this.
399 // It is unsupported in the previous version and
400 // in chromium. I think it is used mostly for printers.
scroggo230d4ac2015-03-26 07:15:55 -0700401 SkCodecPrintf("Error: compression format not supported.\n");
scroggo79e378d2015-04-01 07:39:40 -0700402 return false;
msarett4ab9d5f2015-08-06 15:34:42 -0700403 case kCMYK_BmpCompressionMethod:
404 case kCMYK8BitRLE_BmpCompressionMethod:
405 case kCMYK4BitRLE_BmpCompressionMethod:
msarett74114382015-03-16 11:55:18 -0700406 // TODO: Same as above.
scroggo230d4ac2015-03-26 07:15:55 -0700407 SkCodecPrintf("Error: CMYK not supported for bitmap decoding.\n");
scroggo79e378d2015-04-01 07:39:40 -0700408 return false;
msarett74114382015-03-16 11:55:18 -0700409 default:
scroggo230d4ac2015-03-26 07:15:55 -0700410 SkCodecPrintf("Error: invalid format for bitmap decoding.\n");
scroggo79e378d2015-04-01 07:39:40 -0700411 return false;
msarett74114382015-03-16 11:55:18 -0700412 }
mtklein852f15d2016-03-17 10:51:27 -0700413 iBuffer.reset();
msarett74114382015-03-16 11:55:18 -0700414
msaretteed039b2015-03-18 11:11:19 -0700415 // Calculate the number of bytes read so far
416 const uint32_t bytesRead = kBmpHeaderBytes + infoBytes + maskBytes;
msarett4ab9d5f2015-08-06 15:34:42 -0700417 if (!inIco && offset < bytesRead) {
msarett9aa32d12015-09-01 14:40:46 -0700418 // TODO (msarett): Do we really want to fail if the offset in the header is invalid?
419 // Seems like we can just assume that the offset is zero and try to decode?
420 // Maybe we don't want to try to decode corrupt images?
scroggo230d4ac2015-03-26 07:15:55 -0700421 SkCodecPrintf("Error: pixel data offset less than header size.\n");
scroggo79e378d2015-04-01 07:39:40 -0700422 return false;
msaretteed039b2015-03-18 11:11:19 -0700423 }
msarett74114382015-03-16 11:55:18 -0700424
msarett9aa32d12015-09-01 14:40:46 -0700425
msarettf4004f92016-02-11 10:49:31 -0800426
msarett1088db92016-03-22 08:58:35 -0700427 switch (inputFormat) {
428 case kStandard_BmpInputFormat: {
msarettc30c4182016-04-20 11:53:35 -0700429 // BMPs are generally opaque, however BMPs-in-ICOs may contain
430 // a transparency mask after the image. Therefore, we mark the
431 // alpha as kBinary if the BMP is contained in an ICO.
432 // We use |isOpaque| to indicate if the BMP itself is opaque.
433 SkEncodedInfo::Alpha alpha = inIco ? SkEncodedInfo::kBinary_Alpha :
434 SkEncodedInfo::kOpaque_Alpha;
msarett1088db92016-03-22 08:58:35 -0700435 bool isOpaque = true;
msarettc30c4182016-04-20 11:53:35 -0700436
437 SkEncodedInfo::Color color;
438 uint8_t bitsPerComponent;
msarett1088db92016-03-22 08:58:35 -0700439 switch (bitsPerPixel) {
440 // Palette formats
441 case 1:
442 case 2:
443 case 4:
444 case 8:
msarettc30c4182016-04-20 11:53:35 -0700445 // In the case of ICO, kBGRA is actually the closest match,
446 // since we will need to apply a transparency mask.
447 if (inIco) {
448 color = SkEncodedInfo::kBGRA_Color;
449 bitsPerComponent = 8;
450 } else {
451 color = SkEncodedInfo::kPalette_Color;
452 bitsPerComponent = (uint8_t) bitsPerPixel;
msarett1088db92016-03-22 08:58:35 -0700453 }
454 break;
455 case 24:
msarett3e375b02016-05-04 13:03:48 -0700456 // In the case of ICO, kBGRA is actually the closest match,
457 // since we will need to apply a transparency mask.
458 color = inIco ? SkEncodedInfo::kBGRA_Color : SkEncodedInfo::kBGR_Color;
msarettc30c4182016-04-20 11:53:35 -0700459 bitsPerComponent = 8;
460 break;
msarett1088db92016-03-22 08:58:35 -0700461 case 32:
462 // 32-bit BMP-in-ICOs actually use the alpha channel in place of a
463 // transparency mask.
464 if (inIco) {
465 isOpaque = false;
msarettc30c4182016-04-20 11:53:35 -0700466 alpha = SkEncodedInfo::kUnpremul_Alpha;
467 color = SkEncodedInfo::kBGRA_Color;
468 } else {
469 color = SkEncodedInfo::kBGRX_Color;
msarett1088db92016-03-22 08:58:35 -0700470 }
msarettc30c4182016-04-20 11:53:35 -0700471 bitsPerComponent = 8;
msarett1088db92016-03-22 08:58:35 -0700472 break;
473 default:
474 SkCodecPrintf("Error: invalid input value for bits per pixel.\n");
475 return false;
476 }
msarett4ab9d5f2015-08-06 15:34:42 -0700477
msarett1088db92016-03-22 08:58:35 -0700478 if (codecOut) {
msarettbe8216a2015-12-04 08:00:50 -0800479 // We require streams to have a memory base for Bmp-in-Ico decodes.
480 SkASSERT(!inIco || nullptr != stream->getMemoryBase());
msarett1088db92016-03-22 08:58:35 -0700481
482 // Set the image info and create a codec.
msarettc30c4182016-04-20 11:53:35 -0700483 const SkEncodedInfo info = SkEncodedInfo::Make(color, alpha, bitsPerComponent);
484 *codecOut = new SkBmpStandardCodec(width, height, info, stream, bitsPerPixel,
485 numColors, bytesPerColor, offset - bytesRead, rowOrder, isOpaque, inIco);
msarett1088db92016-03-22 08:58:35 -0700486 }
487 return true;
488 }
489
490 case kBitMask_BmpInputFormat: {
491 // Bmp-in-Ico must be standard mode
492 if (inIco) {
493 SkCodecPrintf("Error: Icos may not use bit mask format.\n");
494 return false;
495 }
496
497 switch (bitsPerPixel) {
498 case 16:
499 case 24:
500 case 32:
501 break;
502 default:
503 SkCodecPrintf("Error: invalid input value for bits per pixel.\n");
504 return false;
505 }
506
507 // Skip to the start of the pixel array.
508 // We can do this here because there is no color table to read
509 // in bit mask mode.
510 if (stream->skip(offset - bytesRead) != offset - bytesRead) {
511 SkCodecPrintf("Error: unable to skip to image data.\n");
512 return false;
513 }
514
515 if (codecOut) {
516 // Check that input bit masks are valid and create the masks object
Ben Wagner145dbcd2016-11-03 14:40:50 -0400517 std::unique_ptr<SkMasks> masks(SkMasks::CreateMasks(inputMasks, bitsPerPixel));
msarett1088db92016-03-22 08:58:35 -0700518 if (nullptr == masks) {
519 SkCodecPrintf("Error: invalid input masks.\n");
msarett4ab9d5f2015-08-06 15:34:42 -0700520 return false;
521 }
msarett4ab9d5f2015-08-06 15:34:42 -0700522
msarettc30c4182016-04-20 11:53:35 -0700523 // Masked bmps are not a great fit for SkEncodedInfo, since they have
524 // arbitrary component orderings and bits per component. Here we choose
525 // somewhat reasonable values - it's ok that we don't match exactly
526 // because SkBmpMaskCodec has its own mask swizzler anyway.
527 SkEncodedInfo::Color color;
528 SkEncodedInfo::Alpha alpha;
529 if (masks->getAlphaMask()) {
530 color = SkEncodedInfo::kBGRA_Color;
531 alpha = SkEncodedInfo::kUnpremul_Alpha;
532 } else {
533 color = SkEncodedInfo::kBGR_Color;
534 alpha = SkEncodedInfo::kOpaque_Alpha;
535 }
536 const SkEncodedInfo info = SkEncodedInfo::Make(color, alpha, 8);
537 *codecOut = new SkBmpMaskCodec(width, height, info, stream, bitsPerPixel,
538 masks.release(), rowOrder);
msarett1088db92016-03-22 08:58:35 -0700539 }
540 return true;
541 }
542
543 case kRLE_BmpInputFormat: {
544 // We should not reach this point without a valid value of bitsPerPixel.
545 SkASSERT(4 == bitsPerPixel || 8 == bitsPerPixel || 24 == bitsPerPixel);
546
547 // Check for a valid number of total bytes when in RLE mode
548 if (totalBytes <= offset) {
549 SkCodecPrintf("Error: RLE requires valid input size.\n");
550 return false;
551 }
msarett1088db92016-03-22 08:58:35 -0700552
553 // Bmp-in-Ico must be standard mode
554 // When inIco is true, this line cannot be reached, since we
555 // require that RLE Bmps have a valid number of totalBytes, and
556 // Icos skip the header that contains totalBytes.
557 SkASSERT(!inIco);
558
559 if (codecOut) {
560 // RLE inputs may skip pixels, leaving them as transparent. This
561 // is uncommon, but we cannot be certain that an RLE bmp will be
msarettc30c4182016-04-20 11:53:35 -0700562 // opaque or that we will be able to represent it with a palette.
563 // For that reason, we always indicate that we are kBGRA.
564 const SkEncodedInfo info = SkEncodedInfo::Make(SkEncodedInfo::kBGRA_Color,
565 SkEncodedInfo::kBinary_Alpha, 8);
566 *codecOut = new SkBmpRLECodec(width, height, info, stream, bitsPerPixel, numColors,
Leon Scroggins IIIb3b24532017-01-18 12:39:07 -0500567 bytesPerColor, offset - bytesRead, rowOrder);
msarett1088db92016-03-22 08:58:35 -0700568 }
569 return true;
msarett4ab9d5f2015-08-06 15:34:42 -0700570 }
msarett1088db92016-03-22 08:58:35 -0700571 default:
572 SkASSERT(false);
573 return false;
scroggo79e378d2015-04-01 07:39:40 -0700574 }
scroggo79e378d2015-04-01 07:39:40 -0700575}
576
577/*
scroggo79e378d2015-04-01 07:39:40 -0700578 * Creates a bmp decoder
579 * Reads enough of the stream to determine the image format
scroggo79e378d2015-04-01 07:39:40 -0700580 */
msarett4ab9d5f2015-08-06 15:34:42 -0700581SkCodec* SkBmpCodec::NewFromStream(SkStream* stream, bool inIco) {
Ben Wagner145dbcd2016-11-03 14:40:50 -0400582 std::unique_ptr<SkStream> streamDeleter(stream);
halcanary96fcdcc2015-08-27 07:41:13 -0700583 SkCodec* codec = nullptr;
msarett4ab9d5f2015-08-06 15:34:42 -0700584 if (ReadHeader(stream, inIco, &codec)) {
scroggo0a7e69c2015-04-03 07:22:22 -0700585 // codec has taken ownership of stream, so we do not need to
586 // delete it.
587 SkASSERT(codec);
mtklein18300a32016-03-16 13:53:35 -0700588 streamDeleter.release();
scroggo79e378d2015-04-01 07:39:40 -0700589 return codec;
590 }
halcanary96fcdcc2015-08-27 07:41:13 -0700591 return nullptr;
msarett74114382015-03-16 11:55:18 -0700592}
593
msarettc30c4182016-04-20 11:53:35 -0700594SkBmpCodec::SkBmpCodec(int width, int height, const SkEncodedInfo& info, SkStream* stream,
scroggo46c57472015-09-30 08:57:13 -0700595 uint16_t bitsPerPixel, SkCodec::SkScanlineOrder rowOrder)
Matt Sarett7f650bd2016-10-30 21:25:34 -0400596 : INHERITED(width, height, info, stream, SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named))
msarett74114382015-03-16 11:55:18 -0700597 , fBitsPerPixel(bitsPerPixel)
msarett74114382015-03-16 11:55:18 -0700598 , fRowOrder(rowOrder)
msarettc30c4182016-04-20 11:53:35 -0700599 , fSrcRowBytes(SkAlign4(compute_row_bytes(width, fBitsPerPixel)))
Matt Sarett1b96c6f2016-11-03 16:15:20 -0400600 , fXformBuffer(nullptr)
msarett74114382015-03-16 11:55:18 -0700601{}
602
scroggob427db12015-08-12 07:24:13 -0700603bool SkBmpCodec::onRewind() {
halcanary96fcdcc2015-08-27 07:41:13 -0700604 return SkBmpCodec::ReadHeader(this->stream(), this->inIco(), nullptr);
msaretteed039b2015-03-18 11:11:19 -0700605}
606
scroggo46c57472015-09-30 08:57:13 -0700607int32_t SkBmpCodec::getDstRow(int32_t y, int32_t height) const {
608 if (SkCodec::kTopDown_SkScanlineOrder == fRowOrder) {
msarett5406d6f2015-08-31 06:55:13 -0700609 return y;
610 }
scroggo46c57472015-09-30 08:57:13 -0700611 SkASSERT(SkCodec::kBottomUp_SkScanlineOrder == fRowOrder);
msarett5406d6f2015-08-31 06:55:13 -0700612 return height - y - 1;
613}
614
Matt Sarett1b96c6f2016-11-03 16:15:20 -0400615SkCodec::Result SkBmpCodec::prepareToDecode(const SkImageInfo& dstInfo,
scroggo46c57472015-09-30 08:57:13 -0700616 const SkCodec::Options& options, SkPMColor inputColorPtr[], int* inputColorCount) {
Matt Sarett1b96c6f2016-11-03 16:15:20 -0400617 if (!conversion_possible(dstInfo, this->getInfo()) || !this->initializeColorXform(dstInfo)) {
scroggo46c57472015-09-30 08:57:13 -0700618 return kInvalidConversion;
msarett5406d6f2015-08-31 06:55:13 -0700619 }
620
Matt Sarett1b96c6f2016-11-03 16:15:20 -0400621 return this->onPrepareToDecode(dstInfo, options, inputColorPtr, inputColorCount);
622}
623
624SkCodec::Result SkBmpCodec::onStartScanlineDecode(const SkImageInfo& dstInfo,
625 const SkCodec::Options& options, SkPMColor inputColorPtr[], int* inputColorCount) {
scroggo46c57472015-09-30 08:57:13 -0700626 return prepareToDecode(dstInfo, options, inputColorPtr, inputColorCount);
627}
msarett5406d6f2015-08-31 06:55:13 -0700628
msarette6dd0042015-10-09 11:07:34 -0700629int SkBmpCodec::onGetScanlines(void* dst, int count, size_t rowBytes) {
scroggo46c57472015-09-30 08:57:13 -0700630 // Create a new image info representing the portion of the image to decode
631 SkImageInfo rowInfo = this->dstInfo().makeWH(this->dstInfo().width(), count);
msarett5406d6f2015-08-31 06:55:13 -0700632
scroggo46c57472015-09-30 08:57:13 -0700633 // Decode the requested rows
634 return this->decodeRows(rowInfo, dst, rowBytes, this->options());
635}
msarett9b9497e2016-02-11 13:29:36 -0800636
637bool SkBmpCodec::skipRows(int count) {
638 const size_t bytesToSkip = count * fSrcRowBytes;
639 return this->stream()->skip(bytesToSkip) == bytesToSkip;
640}
641
642bool SkBmpCodec::onSkipScanlines(int count) {
643 return this->skipRows(count);
644}
Matt Sarett1b96c6f2016-11-03 16:15:20 -0400645
646void SkBmpCodec::applyColorXform(const SkImageInfo& dstInfo, void* dst, void* src) const {
647 SkColorSpaceXform* xform = this->colorXform();
648 if (xform) {
Matt Sarett562e6812016-11-08 16:13:43 -0500649 const SkColorSpaceXform::ColorFormat dstFormat = select_xform_format(dstInfo.colorType());
650 const SkColorSpaceXform::ColorFormat srcFormat = select_xform_format(kXformSrcColorType);
651 const SkAlphaType alphaType = select_xform_alpha(dstInfo.alphaType(),
652 this->getInfo().alphaType());
Matt Sarett1b96c6f2016-11-03 16:15:20 -0400653 SkAssertResult(xform->apply(dstFormat, dst, srcFormat, src, dstInfo.width(),
654 alphaType));
655 }
656}