1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2015 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "src/codec/SkWbmpCodec.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/codec/SkCodec.h" 11cb93a386Sopenharmony_ci#include "include/core/SkData.h" 12cb93a386Sopenharmony_ci#include "include/core/SkStream.h" 13cb93a386Sopenharmony_ci#include "include/private/SkColorData.h" 14cb93a386Sopenharmony_ci#include "include/private/SkTo.h" 15cb93a386Sopenharmony_ci#include "src/codec/SkCodecPriv.h" 16cb93a386Sopenharmony_ci#include "src/codec/SkColorTable.h" 17cb93a386Sopenharmony_ci 18cb93a386Sopenharmony_ci// Each bit represents a pixel, so width is actually a number of bits. 19cb93a386Sopenharmony_ci// A row will always be stored in bytes, so we round width up to the 20cb93a386Sopenharmony_ci// nearest multiple of 8 to get the number of bits actually in the row. 21cb93a386Sopenharmony_ci// We then divide by 8 to convert to bytes. 22cb93a386Sopenharmony_cistatic inline size_t get_src_row_bytes(int width) { 23cb93a386Sopenharmony_ci return SkAlign8(width) >> 3; 24cb93a386Sopenharmony_ci} 25cb93a386Sopenharmony_ci 26cb93a386Sopenharmony_cistatic inline bool valid_color_type(const SkImageInfo& dstInfo) { 27cb93a386Sopenharmony_ci switch (dstInfo.colorType()) { 28cb93a386Sopenharmony_ci case kRGBA_8888_SkColorType: 29cb93a386Sopenharmony_ci case kBGRA_8888_SkColorType: 30cb93a386Sopenharmony_ci case kGray_8_SkColorType: 31cb93a386Sopenharmony_ci case kRGB_565_SkColorType: 32cb93a386Sopenharmony_ci return true; 33cb93a386Sopenharmony_ci case kRGBA_F16_SkColorType: 34cb93a386Sopenharmony_ci return dstInfo.colorSpace(); 35cb93a386Sopenharmony_ci default: 36cb93a386Sopenharmony_ci return false; 37cb93a386Sopenharmony_ci } 38cb93a386Sopenharmony_ci} 39cb93a386Sopenharmony_ci 40cb93a386Sopenharmony_cistatic bool read_byte(SkStream* stream, uint8_t* data) 41cb93a386Sopenharmony_ci{ 42cb93a386Sopenharmony_ci return stream->read(data, 1) == 1; 43cb93a386Sopenharmony_ci} 44cb93a386Sopenharmony_ci 45cb93a386Sopenharmony_ci// http://en.wikipedia.org/wiki/Variable-length_quantity 46cb93a386Sopenharmony_cistatic bool read_mbf(SkStream* stream, uint64_t* value) { 47cb93a386Sopenharmony_ci uint64_t n = 0; 48cb93a386Sopenharmony_ci uint8_t data; 49cb93a386Sopenharmony_ci const uint64_t kLimit = 0xFE00000000000000; 50cb93a386Sopenharmony_ci SkASSERT(kLimit == ~((~static_cast<uint64_t>(0)) >> 7)); 51cb93a386Sopenharmony_ci do { 52cb93a386Sopenharmony_ci if (n & kLimit) { // Will overflow on shift by 7. 53cb93a386Sopenharmony_ci return false; 54cb93a386Sopenharmony_ci } 55cb93a386Sopenharmony_ci if (stream->read(&data, 1) != 1) { 56cb93a386Sopenharmony_ci return false; 57cb93a386Sopenharmony_ci } 58cb93a386Sopenharmony_ci n = (n << 7) | (data & 0x7F); 59cb93a386Sopenharmony_ci } while (data & 0x80); 60cb93a386Sopenharmony_ci *value = n; 61cb93a386Sopenharmony_ci return true; 62cb93a386Sopenharmony_ci} 63cb93a386Sopenharmony_ci 64cb93a386Sopenharmony_cistatic bool read_header(SkStream* stream, SkISize* size) { 65cb93a386Sopenharmony_ci { 66cb93a386Sopenharmony_ci uint8_t data; 67cb93a386Sopenharmony_ci if (!read_byte(stream, &data) || data != 0) { // unknown type 68cb93a386Sopenharmony_ci return false; 69cb93a386Sopenharmony_ci } 70cb93a386Sopenharmony_ci if (!read_byte(stream, &data) || (data & 0x9F)) { // skip fixed header 71cb93a386Sopenharmony_ci return false; 72cb93a386Sopenharmony_ci } 73cb93a386Sopenharmony_ci } 74cb93a386Sopenharmony_ci 75cb93a386Sopenharmony_ci uint64_t width, height; 76cb93a386Sopenharmony_ci if (!read_mbf(stream, &width) || width > 0xFFFF || !width) { 77cb93a386Sopenharmony_ci return false; 78cb93a386Sopenharmony_ci } 79cb93a386Sopenharmony_ci if (!read_mbf(stream, &height) || height > 0xFFFF || !height) { 80cb93a386Sopenharmony_ci return false; 81cb93a386Sopenharmony_ci } 82cb93a386Sopenharmony_ci if (size) { 83cb93a386Sopenharmony_ci *size = SkISize::Make(SkToS32(width), SkToS32(height)); 84cb93a386Sopenharmony_ci } 85cb93a386Sopenharmony_ci return true; 86cb93a386Sopenharmony_ci} 87cb93a386Sopenharmony_ci 88cb93a386Sopenharmony_cibool SkWbmpCodec::onRewind() { 89cb93a386Sopenharmony_ci return read_header(this->stream(), nullptr); 90cb93a386Sopenharmony_ci} 91cb93a386Sopenharmony_ci 92cb93a386Sopenharmony_cibool SkWbmpCodec::readRow(uint8_t* row) { 93cb93a386Sopenharmony_ci return this->stream()->read(row, fSrcRowBytes) == fSrcRowBytes; 94cb93a386Sopenharmony_ci} 95cb93a386Sopenharmony_ci 96cb93a386Sopenharmony_ciSkWbmpCodec::SkWbmpCodec(SkEncodedInfo&& info, std::unique_ptr<SkStream> stream) 97cb93a386Sopenharmony_ci // Wbmp does not need a colorXform, so choose an arbitrary srcFormat. 98cb93a386Sopenharmony_ci : INHERITED(std::move(info), skcms_PixelFormat(), 99cb93a386Sopenharmony_ci std::move(stream)) 100cb93a386Sopenharmony_ci , fSrcRowBytes(get_src_row_bytes(this->dimensions().width())) 101cb93a386Sopenharmony_ci , fSwizzler(nullptr) 102cb93a386Sopenharmony_ci{} 103cb93a386Sopenharmony_ci 104cb93a386Sopenharmony_ciSkEncodedImageFormat SkWbmpCodec::onGetEncodedFormat() const { 105cb93a386Sopenharmony_ci return SkEncodedImageFormat::kWBMP; 106cb93a386Sopenharmony_ci} 107cb93a386Sopenharmony_ci 108cb93a386Sopenharmony_cibool SkWbmpCodec::conversionSupported(const SkImageInfo& dst, bool srcIsOpaque, 109cb93a386Sopenharmony_ci bool /*needsColorXform*/) { 110cb93a386Sopenharmony_ci return valid_color_type(dst) && valid_alpha(dst.alphaType(), srcIsOpaque); 111cb93a386Sopenharmony_ci} 112cb93a386Sopenharmony_ci 113cb93a386Sopenharmony_ciSkCodec::Result SkWbmpCodec::onGetPixels(const SkImageInfo& info, 114cb93a386Sopenharmony_ci void* dst, 115cb93a386Sopenharmony_ci size_t rowBytes, 116cb93a386Sopenharmony_ci const Options& options, 117cb93a386Sopenharmony_ci int* rowsDecoded) { 118cb93a386Sopenharmony_ci if (options.fSubset) { 119cb93a386Sopenharmony_ci // Subsets are not supported. 120cb93a386Sopenharmony_ci return kUnimplemented; 121cb93a386Sopenharmony_ci } 122cb93a386Sopenharmony_ci 123cb93a386Sopenharmony_ci // Initialize the swizzler 124cb93a386Sopenharmony_ci std::unique_ptr<SkSwizzler> swizzler = SkSwizzler::Make(this->getEncodedInfo(), nullptr, info, 125cb93a386Sopenharmony_ci options); 126cb93a386Sopenharmony_ci SkASSERT(swizzler); 127cb93a386Sopenharmony_ci 128cb93a386Sopenharmony_ci // Perform the decode 129cb93a386Sopenharmony_ci SkISize size = info.dimensions(); 130cb93a386Sopenharmony_ci SkAutoTMalloc<uint8_t> src(fSrcRowBytes); 131cb93a386Sopenharmony_ci void* dstRow = dst; 132cb93a386Sopenharmony_ci for (int y = 0; y < size.height(); ++y) { 133cb93a386Sopenharmony_ci if (!this->readRow(src.get())) { 134cb93a386Sopenharmony_ci *rowsDecoded = y; 135cb93a386Sopenharmony_ci return kIncompleteInput; 136cb93a386Sopenharmony_ci } 137cb93a386Sopenharmony_ci swizzler->swizzle(dstRow, src.get()); 138cb93a386Sopenharmony_ci dstRow = SkTAddOffset<void>(dstRow, rowBytes); 139cb93a386Sopenharmony_ci } 140cb93a386Sopenharmony_ci return kSuccess; 141cb93a386Sopenharmony_ci} 142cb93a386Sopenharmony_ci 143cb93a386Sopenharmony_cibool SkWbmpCodec::IsWbmp(const void* buffer, size_t bytesRead) { 144cb93a386Sopenharmony_ci SkMemoryStream stream(buffer, bytesRead, false); 145cb93a386Sopenharmony_ci return read_header(&stream, nullptr); 146cb93a386Sopenharmony_ci} 147cb93a386Sopenharmony_ci 148cb93a386Sopenharmony_cistd::unique_ptr<SkCodec> SkWbmpCodec::MakeFromStream(std::unique_ptr<SkStream> stream, 149cb93a386Sopenharmony_ci Result* result) { 150cb93a386Sopenharmony_ci SkISize size; 151cb93a386Sopenharmony_ci if (!read_header(stream.get(), &size)) { 152cb93a386Sopenharmony_ci // This already succeeded in IsWbmp, so this stream was corrupted in/ 153cb93a386Sopenharmony_ci // after rewind. 154cb93a386Sopenharmony_ci *result = kCouldNotRewind; 155cb93a386Sopenharmony_ci return nullptr; 156cb93a386Sopenharmony_ci } 157cb93a386Sopenharmony_ci *result = kSuccess; 158cb93a386Sopenharmony_ci auto info = SkEncodedInfo::Make(size.width(), size.height(), SkEncodedInfo::kGray_Color, 159cb93a386Sopenharmony_ci SkEncodedInfo::kOpaque_Alpha, 1); 160cb93a386Sopenharmony_ci return std::unique_ptr<SkCodec>(new SkWbmpCodec(std::move(info), std::move(stream))); 161cb93a386Sopenharmony_ci} 162cb93a386Sopenharmony_ci 163cb93a386Sopenharmony_ciint SkWbmpCodec::onGetScanlines(void* dst, int count, size_t dstRowBytes) { 164cb93a386Sopenharmony_ci void* dstRow = dst; 165cb93a386Sopenharmony_ci for (int y = 0; y < count; ++y) { 166cb93a386Sopenharmony_ci if (!this->readRow(fSrcBuffer.get())) { 167cb93a386Sopenharmony_ci return y; 168cb93a386Sopenharmony_ci } 169cb93a386Sopenharmony_ci fSwizzler->swizzle(dstRow, fSrcBuffer.get()); 170cb93a386Sopenharmony_ci dstRow = SkTAddOffset<void>(dstRow, dstRowBytes); 171cb93a386Sopenharmony_ci } 172cb93a386Sopenharmony_ci return count; 173cb93a386Sopenharmony_ci} 174cb93a386Sopenharmony_ci 175cb93a386Sopenharmony_cibool SkWbmpCodec::onSkipScanlines(int count) { 176cb93a386Sopenharmony_ci const size_t bytesToSkip = count * fSrcRowBytes; 177cb93a386Sopenharmony_ci return this->stream()->skip(bytesToSkip) == bytesToSkip; 178cb93a386Sopenharmony_ci} 179cb93a386Sopenharmony_ci 180cb93a386Sopenharmony_ciSkCodec::Result SkWbmpCodec::onStartScanlineDecode(const SkImageInfo& dstInfo, 181cb93a386Sopenharmony_ci const Options& options) { 182cb93a386Sopenharmony_ci if (options.fSubset) { 183cb93a386Sopenharmony_ci // Subsets are not supported. 184cb93a386Sopenharmony_ci return kUnimplemented; 185cb93a386Sopenharmony_ci } 186cb93a386Sopenharmony_ci 187cb93a386Sopenharmony_ci fSwizzler = SkSwizzler::Make(this->getEncodedInfo(), nullptr, dstInfo, options); 188cb93a386Sopenharmony_ci SkASSERT(fSwizzler); 189cb93a386Sopenharmony_ci 190cb93a386Sopenharmony_ci fSrcBuffer.reset(fSrcRowBytes); 191cb93a386Sopenharmony_ci 192cb93a386Sopenharmony_ci return kSuccess; 193cb93a386Sopenharmony_ci} 194