73 const char bmpSig[] = {
'B',
'M' };
74 return bytesRead >=
sizeof(bmpSig) && !memcmp(
buffer, bmpSig,
sizeof(bmpSig));
143 SkCodecPrintf(
"Error: second bitmap header size is invalid.\n");
149 std::unique_ptr<SkCodec>* codecOut) {
165 SkCodecPrintf(
"Error: unable to read first bitmap header.\n");
169 totalBytes =
get_int(hBuffer, 2);
172 SkCodecPrintf(
"Error: invalid starting location for pixel data\n");
179 infoBytes =
get_int(hBuffer, 14);
198 SkCodecPrintf(
"Error: unable to read size of second bitmap header.\n");
201 infoBytes =
get_int(hBuffer, 0);
215 const uint32_t infoBytesRemaining = infoBytes - 4;
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");
231 uint32_t numColors = 0;
234 uint32_t bytesPerColor;
239 switch (headerType) {
256 if (infoBytesRemaining >= 16) {
257 compression =
get_int(iBuffer.get(), 12);
258 if (infoBytesRemaining >= 32) {
259 numColors =
get_int(iBuffer.get(), 28);
284 if (
height == INT32_MIN) {
298 constexpr int kMaxDim = 1 << 16;
299 if (
width <= 0 || height <= 0 || width >= kMaxDim ||
height >= kMaxDim) {
309 uint32_t maskBytes = 0;
311 switch (compression) {
321 inputMasks.
red = 0x7C00;
322 inputMasks.
green = 0x03E0;
323 inputMasks.
blue = 0x001F;
329 SkCodecPrintf(
"Warning: correcting invalid bitmap format.\n");
336 SkCodecPrintf(
"Warning: correcting invalid bitmap format.\n");
345 switch (headerType) {
420 SkCodecPrintf(
"Error: CMYK not supported for bitmap decoding.\n");
423 SkCodecPrintf(
"Error: invalid format for bitmap decoding.\n");
434 SkCodecPrintf(
"Error: pixel data offset less than header size.\n");
440 switch (inputFormat) {
448 bool isOpaque =
true;
451 uint8_t bitsPerComponent;
462 bitsPerComponent = 8;
472 bitsPerComponent = 8;
484 bitsPerComponent = 8;
487 SkCodecPrintf(
"Error: invalid input value for bits per pixel.\n");
497 *codecOut = std::make_unique<SkBmpStandardCodec>(std::move(
info),
498 std::unique_ptr<SkStream>(
stream),
500 offset - bytesRead, rowOrder, isOpaque,
521 SkCodecPrintf(
"Error: invalid input value for bits per pixel.\n");
537 if (
nullptr == masks) {
548 if (masks->getAlphaMask()) {
556 *codecOut = std::make_unique<SkBmpMaskCodec>(std::move(
info),
558 masks.release(), rowOrder);
559 return static_cast<SkBmpMaskCodec*
>(codecOut->get())->didCreateSrcBuffer()
570 if (totalBytes <=
offset) {
588 *codecOut = std::make_unique<SkBmpRLECodec>(std::move(
info),
590 numColors, bytesPerColor,
offset - bytesRead,
606 Result*
result,
bool inIco) {
612 std::unique_ptr<SkCodec> codec;
624 , fBitsPerPixel(bitsPerPixel)
625 , fRowOrder(rowOrder)
627 , fXformBuffer(nullptr)
661 const size_t bytesToSkip =
count * fSrcRowBytes;
662 return this->
stream()->
skip(bytesToSkip) == bytesToSkip;
670bool IsBmp(
const void* data,
size_t len) {
674std::unique_ptr<SkCodec>
Decode(std::unique_ptr<SkStream> stream,
676 SkCodecs::DecodeContext) {
679 outResult = &resultStorage;
686 SkCodecs::DecodeContext) {
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
static constexpr T SkAlign4(T x)
static constexpr uint32_t kBmpHeaderBytes
static constexpr uint32_t kBmpHeaderBytesPlusFour
static BmpHeaderType get_header_type(size_t infoBytes)
static constexpr uint32_t kBmpInfoV2Bytes
static constexpr uint32_t kBmpInfoV3Bytes
static constexpr uint32_t kBmpOS2V1Bytes
static constexpr uint32_t kBmpInfoBaseBytes
static constexpr uint32_t kBmpOS2V2Bytes
static constexpr uint32_t kBmpInfoV4Bytes
static constexpr uint32_t kBmpInfoV5Bytes
static constexpr uint32_t kBmpInfoV1Bytes
@ 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
@ kUnknown_BmpInputFormat
@ kBitMask_BmpInputFormat
@ kStandard_BmpInputFormat
static size_t compute_row_bytes(int width, uint32_t bitsPerPixel)
static uint32_t get_int(const uint8_t *buffer, uint32_t i)
#define SkCodecPrintf(...)
static uint16_t get_short(const uint8_t *buffer, uint32_t i)
Type::kYUV Type::kRGBA() int(0.7 *637)
bool onSkipScanlines(int count) override
virtual int decodeRows(const SkImageInfo &dstInfo, void *dst, size_t dstRowBytes, const Options &opts)=0
static std::unique_ptr< SkCodec > MakeFromIco(std::unique_ptr< SkStream >, Result *)
static std::unique_ptr< SkCodec > MakeFromStream(std::unique_ptr< SkStream >, Result *)
SkBmpCodec(SkEncodedInfo &&info, std::unique_ptr< SkStream >, uint16_t bitsPerPixel, SkCodec::SkScanlineOrder rowOrder)
virtual SkCodec::Result onPrepareToDecode(const SkImageInfo &dstInfo, const SkCodec::Options &options)=0
virtual bool skipRows(int count)
int32_t getDstRow(int32_t y, int32_t height) const
SkCodec::Result prepareToDecode(const SkImageInfo &dstInfo, const SkCodec::Options &options)
Result onStartScanlineDecode(const SkImageInfo &dstInfo, const SkCodec::Options &) override
static bool IsBmp(const void *, size_t)
uint16_t bitsPerPixel() const
static Result ReadHeader(SkStream *, bool inIco, std::unique_ptr< SkCodec > *codecOut)
int onGetScanlines(void *dst, int count, size_t rowBytes) override
const SkImageInfo & dstInfo() const
@ kBottomUp_SkScanlineOrder
@ kTopDown_SkScanlineOrder
const Options & options() const
static SkMasks * CreateMasks(InputMasks masks, int bytesPerPixel)
static std::unique_ptr< SkMemoryStream > Make(sk_sp< SkData > data)
virtual const void * getMemoryBase()
virtual size_t read(void *buffer, size_t size)=0
static const uint8_t buffer[]
SK_API bool IsBmp(const void *, size_t)
SK_API std::unique_ptr< SkCodec > Decode(std::unique_ptr< SkStream >, SkCodec::Result *, SkCodecs::DecodeContext=nullptr)
static SkEncodedInfo Make(int width, int height, Color color, Alpha alpha, int bitsPerComponent)
SkImageInfo makeWH(int newWidth, int newHeight) const