Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Static Public Member Functions | Protected Member Functions | Static Protected Member Functions | Static Protected Attributes | Private Member Functions | List of all members
SkBmpCodec Class Referenceabstract

#include <SkBmpCodec.h>

Inheritance diagram for SkBmpCodec:
SkCodec SkNoncopyable SkBmpBaseCodec SkBmpRLECodec SkBmpMaskCodec SkBmpStandardCodec

Static Public Member Functions

static bool IsBmp (const void *, size_t)
 
static std::unique_ptr< SkCodecMakeFromStream (std::unique_ptr< SkStream >, Result *)
 
static std::unique_ptr< SkCodecMakeFromIco (std::unique_ptr< SkStream >, Result *)
 
- Static Public Member Functions inherited from SkCodec
static constexpr size_t MinBufferedBytesNeeded ()
 
static const char * ResultToString (Result)
 
static std::unique_ptr< SkCodecMakeFromStream (std::unique_ptr< SkStream >, SkSpan< const SkCodecs::Decoder > decoders, Result *=nullptr, SkPngChunkReader *=nullptr, SelectionPolicy selectionPolicy=SelectionPolicy::kPreferStillImage)
 
static std::unique_ptr< SkCodecMakeFromStream (std::unique_ptr< SkStream >, Result *=nullptr, SkPngChunkReader *=nullptr, SelectionPolicy selectionPolicy=SelectionPolicy::kPreferStillImage)
 
static std::unique_ptr< SkCodecMakeFromData (sk_sp< SkData >, SkSpan< const SkCodecs::Decoder > decoders, SkPngChunkReader *=nullptr)
 
static std::unique_ptr< SkCodecMakeFromData (sk_sp< SkData >, SkPngChunkReader *=nullptr)
 
static void Register (bool(*peek)(const void *, size_t), std::unique_ptr< SkCodec >(*make)(std::unique_ptr< SkStream >, SkCodec::Result *))
 

Protected Member Functions

 SkBmpCodec (SkEncodedInfo &&info, std::unique_ptr< SkStream >, uint16_t bitsPerPixel, SkCodec::SkScanlineOrder rowOrder)
 
SkEncodedImageFormat onGetEncodedFormat () const override
 
bool onRewind () override
 
bool inIco () const
 
virtual bool onInIco () const
 
int32_t getDstRow (int32_t y, int32_t height) const
 
uint16_t bitsPerPixel () const
 
SkScanlineOrder onGetScanlineOrder () const override
 
size_t srcRowBytes () const
 
virtual SkCodec::Result onPrepareToDecode (const SkImageInfo &dstInfo, const SkCodec::Options &options)=0
 
SkCodec::Result prepareToDecode (const SkImageInfo &dstInfo, const SkCodec::Options &options)
 
uint32_t * xformBuffer () const
 
void resetXformBuffer (int count)
 
- Protected Member Functions inherited from SkCodec
const SkEncodedInfogetEncodedInfo () const
 
 SkCodec (SkEncodedInfo &&, XformFormat srcFormat, std::unique_ptr< SkStream >, SkEncodedOrigin=kTopLeft_SkEncodedOrigin)
 
void setSrcXformFormat (XformFormat pixelFormat)
 
XformFormat getSrcXformFormat () const
 
virtual bool onGetGainmapInfo (SkGainmapInfo *, std::unique_ptr< SkStream > *)
 
virtual SkISize onGetScaledDimensions (float) const
 
virtual bool onDimensionsSupported (const SkISize &)
 
virtual Result onGetPixels (const SkImageInfo &info, void *pixels, size_t rowBytes, const Options &, int *rowsDecoded)=0
 
virtual bool onQueryYUVAInfo (const SkYUVAPixmapInfo::SupportedDataTypes &, SkYUVAPixmapInfo *) const
 
virtual Result onGetYUVAPlanes (const SkYUVAPixmaps &)
 
virtual bool onGetValidSubset (SkIRect *) const
 
bool rewindIfNeeded ()
 
SkStreamstream ()
 
const SkImageInfodstInfo () const
 
const Optionsoptions () const
 
int currScanline () const
 
virtual int onOutputScanline (int inputScanline) const
 
virtual bool conversionSupported (const SkImageInfo &dst, bool srcIsOpaque, bool needsColorXform)
 
virtual bool usesColorXform () const
 
void applyColorXform (void *dst, const void *src, int count) const
 
bool colorXform () const
 
bool xformOnDecode () const
 
virtual int onGetFrameCount ()
 
virtual bool onGetFrameInfo (int, FrameInfo *) const
 
virtual int onGetRepetitionCount ()
 

Static Protected Member Functions

static Result ReadHeader (SkStream *, bool inIco, std::unique_ptr< SkCodec > *codecOut)
 

Static Protected Attributes

static constexpr SkColorType kXformSrcColorType = kBGRA_8888_SkColorType
 
static constexpr auto kXformSrcColorFormat = skcms_PixelFormat_BGRA_8888
 

Private Member Functions

virtual int decodeRows (const SkImageInfo &dstInfo, void *dst, size_t dstRowBytes, const Options &opts)=0
 
virtual bool skipRows (int count)
 
Result onStartScanlineDecode (const SkImageInfo &dstInfo, const SkCodec::Options &) override
 
int onGetScanlines (void *dst, int count, size_t rowBytes) override
 
bool onSkipScanlines (int count) override
 

Additional Inherited Members

- Public Types inherited from SkCodec
enum  Result {
  kSuccess , kIncompleteInput , kErrorInInput , kInvalidConversion ,
  kInvalidScale , kInvalidParameters , kInvalidInput , kCouldNotRewind ,
  kInternalError , kUnimplemented
}
 
enum class  SelectionPolicy { kPreferStillImage , kPreferAnimation }
 
enum  ZeroInitialized { kYes_ZeroInitialized , kNo_ZeroInitialized }
 
enum  SkScanlineOrder { kTopDown_SkScanlineOrder , kBottomUp_SkScanlineOrder }
 
- Public Member Functions inherited from SkCodec
virtual ~SkCodec ()
 
SkImageInfo getInfo () const
 
SkISize dimensions () const
 
SkIRect bounds () const
 
const skcms_ICCProfilegetICCProfile () const
 
SkEncodedOrigin getOrigin () const
 
SkISize getScaledDimensions (float desiredScale) const
 
bool getValidSubset (SkIRect *desiredSubset) const
 
SkEncodedImageFormat getEncodedFormat () const
 
virtual std::unique_ptr< SkStreamgetEncodedData () const
 
Result getPixels (const SkImageInfo &info, void *pixels, size_t rowBytes, const Options *)
 
Result getPixels (const SkImageInfo &info, void *pixels, size_t rowBytes)
 
Result getPixels (const SkPixmap &pm, const Options *opts=nullptr)
 
std::tuple< sk_sp< SkImage >, SkCodec::ResultgetImage (const SkImageInfo &info, const Options *opts=nullptr)
 
std::tuple< sk_sp< SkImage >, SkCodec::ResultgetImage ()
 
bool queryYUVAInfo (const SkYUVAPixmapInfo::SupportedDataTypes &supportedDataTypes, SkYUVAPixmapInfo *yuvaPixmapInfo) const
 
Result getYUVAPlanes (const SkYUVAPixmaps &yuvaPixmaps)
 
Result startIncrementalDecode (const SkImageInfo &dstInfo, void *dst, size_t rowBytes, const Options *)
 
Result startIncrementalDecode (const SkImageInfo &dstInfo, void *dst, size_t rowBytes)
 
Result incrementalDecode (int *rowsDecoded=nullptr)
 
Result startScanlineDecode (const SkImageInfo &dstInfo, const Options *options)
 
Result startScanlineDecode (const SkImageInfo &dstInfo)
 
int getScanlines (void *dst, int countLines, size_t rowBytes)
 
bool skipScanlines (int countLines)
 
SkScanlineOrder getScanlineOrder () const
 
int nextScanline () const
 
int outputScanline (int inputScanline) const
 
int getFrameCount ()
 
bool getFrameInfo (int index, FrameInfo *info) const
 
std::vector< FrameInfogetFrameInfo ()
 
int getRepetitionCount ()
 
- Static Public Attributes inherited from SkCodec
static constexpr int kNoFrame = -1
 
static constexpr int kRepetitionCountInfinite = -1
 
- Protected Types inherited from SkCodec
using XformFormat = skcms_PixelFormat
 

Detailed Description

Definition at line 28 of file SkBmpCodec.h.

Constructor & Destructor Documentation

◆ SkBmpCodec()

SkBmpCodec::SkBmpCodec ( SkEncodedInfo &&  info,
std::unique_ptr< SkStream stream,
uint16_t  bitsPerPixel,
SkCodec::SkScanlineOrder  rowOrder 
)
protected

Definition at line 621 of file SkBmpCodec.cpp.

623 : INHERITED(std::move(info), kXformSrcColorFormat, std::move(stream))
624 , fBitsPerPixel(bitsPerPixel)
625 , fRowOrder(rowOrder)
626 , fSrcRowBytes(SkAlign4(compute_row_bytes(this->dimensions().width(), fBitsPerPixel)))
627 , fXformBuffer(nullptr)
628{}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition DM.cpp:213
static constexpr T SkAlign4(T x)
Definition SkAlign.h:16
static size_t compute_row_bytes(int width, uint32_t bitsPerPixel)
static constexpr auto kXformSrcColorFormat
Definition SkBmpCodec.h:112
uint16_t bitsPerPixel() const
Definition SkBmpCodec.h:87
SkISize dimensions() const
Definition SkCodec.h:230
SkStream * stream()
Definition SkCodec.h:865
int32_t width

Member Function Documentation

◆ bitsPerPixel()

uint16_t SkBmpCodec::bitsPerPixel ( ) const
inlineprotected

Definition at line 87 of file SkBmpCodec.h.

87{ return fBitsPerPixel; }

◆ decodeRows()

virtual int SkBmpCodec::decodeRows ( const SkImageInfo dstInfo,
void *  dst,
size_t  dstRowBytes,
const Options opts 
)
privatepure virtual

◆ getDstRow()

int32_t SkBmpCodec::getDstRow ( int32_t  y,
int32_t  height 
) const
protected

Definition at line 634 of file SkBmpCodec.cpp.

634 {
635 if (SkCodec::kTopDown_SkScanlineOrder == fRowOrder) {
636 return y;
637 }
639 return height - y - 1;
640}
#define SkASSERT(cond)
Definition SkAssert.h:116
@ kBottomUp_SkScanlineOrder
Definition SkCodec.h:604
@ kTopDown_SkScanlineOrder
Definition SkCodec.h:581
double y
int32_t height

◆ inIco()

bool SkBmpCodec::inIco ( ) const
inlineprotected

Definition at line 63 of file SkBmpCodec.h.

63 {
64 return this->onInIco();
65 }
virtual bool onInIco() const
Definition SkBmpCodec.h:67

◆ IsBmp()

bool SkBmpCodec::IsBmp ( const void *  buffer,
size_t  bytesRead 
)
static

Definition at line 71 of file SkBmpCodec.cpp.

71 {
72 // TODO: Support "IC", "PT", "CI", "CP", "BA"
73 const char bmpSig[] = { 'B', 'M' };
74 return bytesRead >= sizeof(bmpSig) && !memcmp(buffer, bmpSig, sizeof(bmpSig));
75}
static const uint8_t buffer[]

◆ MakeFromIco()

std::unique_ptr< SkCodec > SkBmpCodec::MakeFromIco ( std::unique_ptr< SkStream stream,
Result result 
)
static

Definition at line 91 of file SkBmpCodec.cpp.

91 {
92 return SkBmpCodec::MakeFromStream(std::move(stream), result, true);
93}
static std::unique_ptr< SkCodec > MakeFromStream(std::unique_ptr< SkStream >, Result *)
GAsyncResult * result

◆ MakeFromStream()

std::unique_ptr< SkCodec > SkBmpCodec::MakeFromStream ( std::unique_ptr< SkStream stream,
Result result 
)
static

Definition at line 82 of file SkBmpCodec.cpp.

83 {
84 return SkBmpCodec::MakeFromStream(std::move(stream), result, false);
85}

◆ onGetEncodedFormat()

SkEncodedImageFormat SkBmpCodec::onGetEncodedFormat ( ) const
inlineoverrideprotectedvirtual

Implements SkCodec.

Definition at line 50 of file SkBmpCodec.h.

◆ onGetScanlineOrder()

SkScanlineOrder SkBmpCodec::onGetScanlineOrder ( ) const
inlineoverrideprotectedvirtual

The remaining functions revolve around decoding scanlines. Most images types will be kTopDown and will not need to override this function.

Reimplemented from SkCodec.

Definition at line 88 of file SkBmpCodec.h.

88{ return fRowOrder; }

◆ onGetScanlines()

int SkBmpCodec::onGetScanlines ( void *  dst,
int  count,
size_t  rowBytes 
)
overrideprivatevirtual

Reimplemented from SkCodec.

Definition at line 652 of file SkBmpCodec.cpp.

652 {
653 // Create a new image info representing the portion of the image to decode
654 SkImageInfo rowInfo = this->dstInfo().makeWH(this->dstInfo().width(), count);
655
656 // Decode the requested rows
657 return this->decodeRows(rowInfo, dst, rowBytes, this->options());
658}
int count
virtual int decodeRows(const SkImageInfo &dstInfo, void *dst, size_t dstRowBytes, const Options &opts)=0
const SkImageInfo & dstInfo() const
Definition SkCodec.h:878
const Options & options() const
Definition SkCodec.h:880
SkImageInfo makeWH(int newWidth, int newHeight) const

◆ onInIco()

virtual bool SkBmpCodec::onInIco ( ) const
inlineprotectedvirtual

Reimplemented in SkBmpStandardCodec.

Definition at line 67 of file SkBmpCodec.h.

67 {
68 return false;
69 }

◆ onPrepareToDecode()

virtual SkCodec::Result SkBmpCodec::onPrepareToDecode ( const SkImageInfo dstInfo,
const SkCodec::Options options 
)
protectedpure virtual

◆ onRewind()

bool SkBmpCodec::onRewind ( )
overrideprotectedvirtual

Called by rewindIfNeeded, if the stream needed to be rewound.

Subclasses should do any set up needed after a rewind.

Reimplemented from SkCodec.

Definition at line 630 of file SkBmpCodec.cpp.

630 {
631 return SkBmpCodec::ReadHeader(this->stream(), this->inIco(), nullptr) == kSuccess;
632}
static Result ReadHeader(SkStream *, bool inIco, std::unique_ptr< SkCodec > *codecOut)
bool inIco() const
Definition SkBmpCodec.h:63
@ kSuccess
Definition SkCodec.h:80

◆ onSkipScanlines()

bool SkBmpCodec::onSkipScanlines ( int  count)
overrideprivatevirtual

Reimplemented from SkCodec.

Definition at line 665 of file SkBmpCodec.cpp.

665 {
666 return this->skipRows(count);
667}
virtual bool skipRows(int count)

◆ onStartScanlineDecode()

SkCodec::Result SkBmpCodec::onStartScanlineDecode ( const SkImageInfo dstInfo,
const SkCodec::Options options 
)
overrideprivatevirtual

Reimplemented from SkCodec.

Definition at line 647 of file SkBmpCodec.cpp.

648 {
650}
SkCodec::Result prepareToDecode(const SkImageInfo &dstInfo, const SkCodec::Options &options)

◆ prepareToDecode()

SkCodec::Result SkBmpCodec::prepareToDecode ( const SkImageInfo dstInfo,
const SkCodec::Options options 
)
protected

Definition at line 642 of file SkBmpCodec.cpp.

643 {
644 return this->onPrepareToDecode(dstInfo, options);
645}
virtual SkCodec::Result onPrepareToDecode(const SkImageInfo &dstInfo, const SkCodec::Options &options)=0

◆ ReadHeader()

SkCodec::Result SkBmpCodec::ReadHeader ( SkStream stream,
bool  inIco,
std::unique_ptr< SkCodec > *  codecOut 
)
staticprotected

Definition at line 148 of file SkBmpCodec.cpp.

149 {
150 // The total bytes in the bmp file
151 // We only need to use this value for RLE decoding, so we will only
152 // check that it is valid in the RLE case.
153 uint32_t totalBytes;
154 // The offset from the start of the file where the pixel data begins
155 uint32_t offset;
156 // The size of the second (info) header in bytes
157 uint32_t infoBytes;
158
159 // Bmps embedded in Icos skip the first Bmp header
160 if (!inIco) {
161 // Read the first header and the size of the second header
162 uint8_t hBuffer[kBmpHeaderBytesPlusFour];
163 if (stream->read(hBuffer, kBmpHeaderBytesPlusFour) !=
165 SkCodecPrintf("Error: unable to read first bitmap header.\n");
166 return kIncompleteInput;
167 }
168
169 totalBytes = get_int(hBuffer, 2);
170 offset = get_int(hBuffer, 10);
172 SkCodecPrintf("Error: invalid starting location for pixel data\n");
173 return kInvalidInput;
174 }
175
176 // The size of the second (info) header in bytes
177 // The size is the first field of the second header, so we have already
178 // read the first four infoBytes.
179 infoBytes = get_int(hBuffer, 14);
180 if (infoBytes < kBmpOS2V1Bytes) {
181 SkCodecPrintf("Error: invalid second header size.\n");
182 return kInvalidInput;
183 }
184 } else {
185 // This value is only used by RLE compression. Bmp in Ico files do not
186 // use RLE. If the compression field is incorrectly signaled as RLE,
187 // we will catch this and signal an error below.
188 totalBytes = 0;
189
190 // Bmps in Ico cannot specify an offset. We will always assume that
191 // pixel data begins immediately after the color table. This value
192 // will be corrected below.
193 offset = 0;
194
195 // Read the size of the second header
196 uint8_t hBuffer[4];
197 if (stream->read(hBuffer, 4) != 4) {
198 SkCodecPrintf("Error: unable to read size of second bitmap header.\n");
199 return kIncompleteInput;
200 }
201 infoBytes = get_int(hBuffer, 0);
202 if (infoBytes < kBmpOS2V1Bytes) {
203 SkCodecPrintf("Error: invalid second header size.\n");
204 return kInvalidInput;
205 }
206 }
207
208 // Determine image information depending on second header format
209 const BmpHeaderType headerType = get_header_type(infoBytes);
210 if (kUnknown_BmpHeaderType == headerType) {
211 return kInvalidInput;
212 }
213
214 // We already read the first four bytes of the info header to get the size
215 const uint32_t infoBytesRemaining = infoBytes - 4;
216
217 // Read the second header
218 std::unique_ptr<uint8_t[]> iBuffer(new uint8_t[infoBytesRemaining]);
219 if (stream->read(iBuffer.get(), infoBytesRemaining) != infoBytesRemaining) {
220 SkCodecPrintf("Error: unable to read second bitmap header.\n");
221 return kIncompleteInput;
222 }
223
224 // The number of bits used per pixel in the pixel data
225 uint16_t bitsPerPixel;
226
227 // The compression method for the pixel data
228 uint32_t compression = kNone_BmpCompressionMethod;
229
230 // Number of colors in the color table, defaults to 0 or max (see below)
231 uint32_t numColors = 0;
232
233 // Bytes per color in the color table, early versions use 3, most use 4
234 uint32_t bytesPerColor;
235
236 // The image width and height
237 int width, height;
238
239 switch (headerType) {
246 // We check the size of the header before entering the if statement.
247 // We should not reach this point unless the size is large enough for
248 // these required fields.
249 SkASSERT(infoBytesRemaining >= 12);
250 width = get_int(iBuffer.get(), 0);
251 height = get_int(iBuffer.get(), 4);
252 bitsPerPixel = get_short(iBuffer.get(), 10);
253
254 // Some versions do not have these fields, so we check before
255 // overwriting the default value.
256 if (infoBytesRemaining >= 16) {
257 compression = get_int(iBuffer.get(), 12);
258 if (infoBytesRemaining >= 32) {
259 numColors = get_int(iBuffer.get(), 28);
260 }
261 }
262
263 // All of the headers that reach this point, store color table entries
264 // using 4 bytes per pixel.
265 bytesPerColor = 4;
266 break;
268 // The OS2V1 is treated separately because it has a unique format
269 width = (int) get_short(iBuffer.get(), 0);
270 height = (int) get_short(iBuffer.get(), 2);
271 bitsPerPixel = get_short(iBuffer.get(), 6);
272 bytesPerColor = 3;
273 break;
275 // We'll exit above in this case.
276 SkASSERT(false);
277 return kInvalidInput;
278 }
279
280 // Check for valid dimensions from header
282 if (height < 0) {
283 // We can't negate INT32_MIN.
284 if (height == INT32_MIN) {
285 return kInvalidInput;
286 }
287
288 height = -height;
290 }
291 // The height field for bmp in ico is double the actual height because they
292 // contain an XOR mask followed by an AND mask
293 if (inIco) {
294 height /= 2;
295 }
296
297 // Arbitrary maximum. Matches Chromium.
298 constexpr int kMaxDim = 1 << 16;
299 if (width <= 0 || height <= 0 || width >= kMaxDim || height >= kMaxDim) {
300 SkCodecPrintf("Error: invalid bitmap dimensions.\n");
301 return kInvalidInput;
302 }
303
304 // Create mask struct
305 SkMasks::InputMasks inputMasks;
306 memset(&inputMasks, 0, sizeof(SkMasks::InputMasks));
307
308 // Determine the input compression format and set bit masks if necessary
309 uint32_t maskBytes = 0;
311 switch (compression) {
313 inputFormat = kStandard_BmpInputFormat;
314
315 // In addition to more standard pixel compression formats, bmp supports
316 // the use of bit masks to determine pixel components. The standard
317 // format for representing 16-bit colors is 555 (XRRRRRGGGGGBBBBB),
318 // which does not map well to any Skia color formats. For this reason,
319 // we will always enable mask mode with 16 bits per pixel.
320 if (16 == bitsPerPixel) {
321 inputMasks.red = 0x7C00;
322 inputMasks.green = 0x03E0;
323 inputMasks.blue = 0x001F;
324 inputFormat = kBitMask_BmpInputFormat;
325 }
326 break;
328 if (bitsPerPixel != 8) {
329 SkCodecPrintf("Warning: correcting invalid bitmap format.\n");
330 bitsPerPixel = 8;
331 }
332 inputFormat = kRLE_BmpInputFormat;
333 break;
335 if (bitsPerPixel != 4) {
336 SkCodecPrintf("Warning: correcting invalid bitmap format.\n");
337 bitsPerPixel = 4;
338 }
339 inputFormat = kRLE_BmpInputFormat;
340 break;
343 // Load the masks
344 inputFormat = kBitMask_BmpInputFormat;
345 switch (headerType) {
347 // The V1 header stores the bit masks after the header
348 uint8_t buffer[kBmpMaskBytes];
350 SkCodecPrintf("Error: unable to read bit inputMasks.\n");
351 return kIncompleteInput;
352 }
353 maskBytes = kBmpMaskBytes;
354 inputMasks.red = get_int(buffer, 0);
355 inputMasks.green = get_int(buffer, 4);
356 inputMasks.blue = get_int(buffer, 8);
357 break;
358 }
363 // Header types are matched based on size. If the header
364 // is V2+, we are guaranteed to be able to read at least
365 // this size.
366 SkASSERT(infoBytesRemaining >= 48);
367 inputMasks.red = get_int(iBuffer.get(), 36);
368 inputMasks.green = get_int(iBuffer.get(), 40);
369 inputMasks.blue = get_int(iBuffer.get(), 44);
370
371 if (kInfoV2_BmpHeaderType == headerType ||
372 (kInfoV3_BmpHeaderType == headerType && !inIco)) {
373 break;
374 }
375
376 // V3+ bmp files introduce an alpha mask and allow the creator of the image
377 // to use the alpha channels. However, many of these images leave the
378 // alpha channel blank and expect to be rendered as opaque. This is the
379 // case for almost all V3 images, so we ignore the alpha mask. For V4+
380 // images in kMask mode, we will use the alpha mask. Additionally, V3
381 // bmp-in-ico expect us to use the alpha mask.
382 //
383 // skbug.com/4116: We should perhaps also apply the alpha mask in kStandard
384 // mode. We just haven't seen any images that expect this
385 // behavior.
386 //
387 // Header types are matched based on size. If the header is
388 // V3+, we are guaranteed to be able to read at least this size.
389 SkASSERT(infoBytesRemaining >= 52);
390 inputMasks.alpha = get_int(iBuffer.get(), 48);
391 break;
393 // TODO: Decide if we intend to support this.
394 // It is unsupported in the previous version and
395 // in chromium. I have not come across a test case
396 // that uses this format.
397 SkCodecPrintf("Error: huffman format unsupported.\n");
398 return kUnimplemented;
399 default:
400 SkCodecPrintf("Error: invalid bmp bit masks header.\n");
401 return kInvalidInput;
402 }
403 break;
405 if (24 == bitsPerPixel) {
406 inputFormat = kRLE_BmpInputFormat;
407 break;
408 }
409 [[fallthrough]];
411 // TODO: Decide if we intend to support this.
412 // It is unsupported in the previous version and
413 // in chromium. I think it is used mostly for printers.
414 SkCodecPrintf("Error: compression format not supported.\n");
415 return kUnimplemented;
419 // TODO: Same as above.
420 SkCodecPrintf("Error: CMYK not supported for bitmap decoding.\n");
421 return kUnimplemented;
422 default:
423 SkCodecPrintf("Error: invalid format for bitmap decoding.\n");
424 return kInvalidInput;
425 }
426 iBuffer.reset();
427
428 // Calculate the number of bytes read so far
429 const uint32_t bytesRead = kBmpHeaderBytes + infoBytes + maskBytes;
430 if (!inIco && offset < bytesRead) {
431 // TODO (msarett): Do we really want to fail if the offset in the header is invalid?
432 // Seems like we can just assume that the offset is zero and try to decode?
433 // Maybe we don't want to try to decode corrupt images?
434 SkCodecPrintf("Error: pixel data offset less than header size.\n");
435 return kInvalidInput;
436 }
437
438
439
440 switch (inputFormat) {
442 // BMPs are generally opaque, however BMPs-in-ICOs may contain
443 // a transparency mask after the image. Therefore, we mark the
444 // alpha as kBinary if the BMP is contained in an ICO.
445 // We use |isOpaque| to indicate if the BMP itself is opaque.
448 bool isOpaque = true;
449
451 uint8_t bitsPerComponent;
452 switch (bitsPerPixel) {
453 // Palette formats
454 case 1:
455 case 2:
456 case 4:
457 case 8:
458 // In the case of ICO, kBGRA is actually the closest match,
459 // since we will need to apply a transparency mask.
460 if (inIco) {
462 bitsPerComponent = 8;
463 } else {
465 bitsPerComponent = (uint8_t) bitsPerPixel;
466 }
467 break;
468 case 24:
469 // In the case of ICO, kBGRA is actually the closest match,
470 // since we will need to apply a transparency mask.
472 bitsPerComponent = 8;
473 break;
474 case 32:
475 // 32-bit BMP-in-ICOs actually use the alpha channel in place of a
476 // transparency mask.
477 if (inIco) {
478 isOpaque = false;
481 } else {
483 }
484 bitsPerComponent = 8;
485 break;
486 default:
487 SkCodecPrintf("Error: invalid input value for bits per pixel.\n");
488 return kInvalidInput;
489 }
490
491 if (codecOut) {
492 // We require streams to have a memory base for Bmp-in-Ico decodes.
493 SkASSERT(!inIco || nullptr != stream->getMemoryBase());
494
495 // Set the image info and create a codec.
496 auto info = SkEncodedInfo::Make(width, height, color, alpha, bitsPerComponent);
497 *codecOut = std::make_unique<SkBmpStandardCodec>(std::move(info),
498 std::unique_ptr<SkStream>(stream),
499 bitsPerPixel, numColors, bytesPerColor,
500 offset - bytesRead, rowOrder, isOpaque,
501 inIco);
502 return static_cast<SkBmpStandardCodec*>(codecOut->get())->didCreateSrcBuffer()
504 }
505 return kSuccess;
506 }
507
509 // Bmp-in-Ico must be standard mode
510 if (inIco) {
511 SkCodecPrintf("Error: Icos may not use bit mask format.\n");
512 return kInvalidInput;
513 }
514
515 switch (bitsPerPixel) {
516 case 16:
517 case 24:
518 case 32:
519 break;
520 default:
521 SkCodecPrintf("Error: invalid input value for bits per pixel.\n");
522 return kInvalidInput;
523 }
524
525 // Skip to the start of the pixel array.
526 // We can do this here because there is no color table to read
527 // in bit mask mode.
528 if (stream->skip(offset - bytesRead) != offset - bytesRead) {
529 SkCodecPrintf("Error: unable to skip to image data.\n");
530 return kIncompleteInput;
531 }
532
533 if (codecOut) {
534 // Check that input bit masks are valid and create the masks object
535 SkASSERT(bitsPerPixel % 8 == 0);
536 std::unique_ptr<SkMasks> masks(SkMasks::CreateMasks(inputMasks, bitsPerPixel/8));
537 if (nullptr == masks) {
538 SkCodecPrintf("Error: invalid input masks.\n");
539 return kInvalidInput;
540 }
541
542 // Masked bmps are not a great fit for SkEncodedInfo, since they have
543 // arbitrary component orderings and bits per component. Here we choose
544 // somewhat reasonable values - it's ok that we don't match exactly
545 // because SkBmpMaskCodec has its own mask swizzler anyway.
548 if (masks->getAlphaMask()) {
551 } else {
554 }
555 auto info = SkEncodedInfo::Make(width, height, color, alpha, 8);
556 *codecOut = std::make_unique<SkBmpMaskCodec>(std::move(info),
557 std::unique_ptr<SkStream>(stream), bitsPerPixel,
558 masks.release(), rowOrder);
559 return static_cast<SkBmpMaskCodec*>(codecOut->get())->didCreateSrcBuffer()
561 }
562 return kSuccess;
563 }
564
565 case kRLE_BmpInputFormat: {
566 // We should not reach this point without a valid value of bitsPerPixel.
567 SkASSERT(4 == bitsPerPixel || 8 == bitsPerPixel || 24 == bitsPerPixel);
568
569 // Check for a valid number of total bytes when in RLE mode
570 if (totalBytes <= offset) {
571 SkCodecPrintf("Error: RLE requires valid input size.\n");
572 return kInvalidInput;
573 }
574
575 // Bmp-in-Ico must be standard mode
576 // When inIco is true, this line cannot be reached, since we
577 // require that RLE Bmps have a valid number of totalBytes, and
578 // Icos skip the header that contains totalBytes.
579 SkASSERT(!inIco);
580
581 if (codecOut) {
582 // RLE inputs may skip pixels, leaving them as transparent. This
583 // is uncommon, but we cannot be certain that an RLE bmp will be
584 // opaque or that we will be able to represent it with a palette.
585 // For that reason, we always indicate that we are kBGRA.
588 *codecOut = std::make_unique<SkBmpRLECodec>(std::move(info),
589 std::unique_ptr<SkStream>(stream), bitsPerPixel,
590 numColors, bytesPerColor, offset - bytesRead,
591 rowOrder);
592 }
593 return kSuccess;
594 }
595 default:
596 SkASSERT(false);
597 return kInvalidInput;
598 }
599}
SkColor4f color
static constexpr uint32_t kBmpHeaderBytes
static constexpr uint32_t kBmpHeaderBytesPlusFour
static BmpHeaderType get_header_type(size_t infoBytes)
static constexpr uint32_t kBmpOS2V1Bytes
@ kCMYK8BitRLE_BmpCompressionMethod
@ kAlphaBitMasks_BmpCompressionMethod
@ k8BitRLE_BmpCompressionMethod
@ k4BitRLE_BmpCompressionMethod
@ kCMYK_BmpCompressionMethod
@ kBitMasks_BmpCompressionMethod
@ kJpeg_BmpCompressionMethod
@ kNone_BmpCompressionMethod
@ kPng_BmpCompressionMethod
@ kCMYK4BitRLE_BmpCompressionMethod
static constexpr uint32_t kBmpMaskBytes
BmpInputFormat
@ kUnknown_BmpInputFormat
@ kRLE_BmpInputFormat
@ kBitMask_BmpInputFormat
@ kStandard_BmpInputFormat
BmpHeaderType
@ kOS2VX_BmpHeaderType
@ kInfoV1_BmpHeaderType
@ kUnknown_BmpHeaderType
@ kOS2V1_BmpHeaderType
@ kInfoV4_BmpHeaderType
@ kInfoV3_BmpHeaderType
@ kInfoV5_BmpHeaderType
@ kInfoV2_BmpHeaderType
static uint32_t get_int(const uint8_t *buffer, uint32_t i)
#define SkCodecPrintf(...)
Definition SkCodecPriv.h:23
static uint16_t get_short(const uint8_t *buffer, uint32_t i)
Type::kYUV Type::kRGBA() int(0.7 *637)
SkScanlineOrder
Definition SkCodec.h:575
@ kIncompleteInput
Definition SkCodec.h:84
@ kInvalidInput
Definition SkCodec.h:109
@ kUnimplemented
Definition SkCodec.h:123
static SkMasks * CreateMasks(InputMasks masks, int bytesPerPixel)
Definition SkMasks.cpp:126
size_t skip(size_t size)
Definition SkStream.h:51
virtual const void * getMemoryBase()
Definition SkStream.h:141
virtual size_t read(void *buffer, size_t size)=0
Point offset
static SkEncodedInfo Make(int width, int height, Color color, Alpha alpha, int bitsPerComponent)

◆ resetXformBuffer()

void SkBmpCodec::resetXformBuffer ( int  count)
inlineprotected

Definition at line 105 of file SkBmpCodec.h.

105{ fXformBuffer.reset(new uint32_t[count]); }

◆ skipRows()

bool SkBmpCodec::skipRows ( int  count)
privatevirtual

Reimplemented in SkBmpRLECodec.

Definition at line 660 of file SkBmpCodec.cpp.

660 {
661 const size_t bytesToSkip = count * fSrcRowBytes;
662 return this->stream()->skip(bytesToSkip) == bytesToSkip;
663}

◆ srcRowBytes()

size_t SkBmpCodec::srcRowBytes ( ) const
inlineprotected

Definition at line 89 of file SkBmpCodec.h.

89{ return fSrcRowBytes; }

◆ xformBuffer()

uint32_t * SkBmpCodec::xformBuffer ( ) const
inlineprotected

Definition at line 104 of file SkBmpCodec.h.

104{ return fXformBuffer.get(); }

Member Data Documentation

◆ kXformSrcColorFormat

constexpr auto SkBmpCodec::kXformSrcColorFormat = skcms_PixelFormat_BGRA_8888
inlinestaticconstexprprotected

Definition at line 112 of file SkBmpCodec.h.

◆ kXformSrcColorType

constexpr SkColorType SkBmpCodec::kXformSrcColorType = kBGRA_8888_SkColorType
inlinestaticconstexprprotected

Definition at line 111 of file SkBmpCodec.h.


The documentation for this class was generated from the following files: