class SkPngNormalCodec : public SkPngCodec {
public:
- SkPngNormalCodec(int width, int height, const SkEncodedInfo& info, SkStream* stream,
- SkPngChunkReader* chunkReader, png_structp png_ptr, png_infop info_ptr, int bitDepth,
- sk_sp<SkColorSpace> colorSpace)
- : INHERITED(width, height, info, stream, chunkReader, png_ptr, info_ptr, bitDepth, 1,
- colorSpace)
+ SkPngNormalCodec(const SkEncodedInfo& encodedInfo, const SkImageInfo& imageInfo,
+ SkStream* stream, SkPngChunkReader* chunkReader, png_structp png_ptr,
+ png_infop info_ptr, int bitDepth)
+ : INHERITED(encodedInfo, imageInfo, stream, chunkReader, png_ptr, info_ptr, bitDepth, 1)
{}
Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& options,
class SkPngInterlacedCodec : public SkPngCodec {
public:
- SkPngInterlacedCodec(int width, int height, const SkEncodedInfo& info,
+ SkPngInterlacedCodec(const SkEncodedInfo& encodedInfo, const SkImageInfo& imageInfo,
SkStream* stream, SkPngChunkReader* chunkReader, png_structp png_ptr,
- png_infop info_ptr, int bitDepth, int numberPasses, sk_sp<SkColorSpace> colorSpace)
- : INHERITED(width, height, info, stream, chunkReader, png_ptr, info_ptr, bitDepth,
- numberPasses, colorSpace)
+ png_infop info_ptr, int bitDepth, int numberPasses)
+ : INHERITED(encodedInfo, imageInfo, stream, chunkReader, png_ptr, info_ptr, bitDepth,
+ numberPasses)
, fCanSkipRewind(false)
{
SkASSERT(numberPasses != 1);
colorSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
}
- SkEncodedInfo info = SkEncodedInfo::Make(color, alpha, 8);
+ SkEncodedInfo encodedInfo = SkEncodedInfo::Make(color, alpha, 8);
+ SkImageInfo imageInfo = encodedInfo.makeImageInfo(origWidth, origHeight, colorSpace);
+
+ if (SkEncodedInfo::kOpaque_Alpha == alpha) {
+ png_color_8p sigBits;
+ if (png_get_sBIT(png_ptr, info_ptr, &sigBits)) {
+ if (5 == sigBits->red && 6 == sigBits->green && 5 == sigBits->blue) {
+ // Recommend a decode to 565 if the sBIT indicates 565.
+ imageInfo = imageInfo.makeColorType(kRGB_565_SkColorType);
+ }
+ }
+ }
if (1 == numberPasses) {
- *outCodec = new SkPngNormalCodec(origWidth, origHeight, info, stream,
- chunkReader, png_ptr, info_ptr, bitDepth, colorSpace);
+ *outCodec = new SkPngNormalCodec(encodedInfo, imageInfo, stream,
+ chunkReader, png_ptr, info_ptr, bitDepth);
} else {
- *outCodec = new SkPngInterlacedCodec(origWidth, origHeight, info, stream,
- chunkReader, png_ptr, info_ptr, bitDepth, numberPasses, colorSpace);
+ *outCodec = new SkPngInterlacedCodec(encodedInfo, imageInfo, stream,
+ chunkReader, png_ptr, info_ptr, bitDepth, numberPasses);
}
}
return true;
}
-SkPngCodec::SkPngCodec(int width, int height, const SkEncodedInfo& info, SkStream* stream,
- SkPngChunkReader* chunkReader, png_structp png_ptr, png_infop info_ptr,
- int bitDepth, int numberPasses, sk_sp<SkColorSpace> colorSpace)
- : INHERITED(width, height, info, stream, colorSpace)
+SkPngCodec::SkPngCodec(const SkEncodedInfo& encodedInfo, const SkImageInfo& imageInfo,
+ SkStream* stream, SkPngChunkReader* chunkReader, png_structp png_ptr,
+ png_infop info_ptr, int bitDepth, int numberPasses)
+ : INHERITED(encodedInfo, imageInfo, stream)
, fPngChunkReader(SkSafeRef(chunkReader))
, fPng_ptr(png_ptr)
, fInfo_ptr(info_ptr)
, fSwizzlerSrcRow(nullptr)
, fColorXformSrcRow(nullptr)
- , fSrcRowBytes(width * (bytes_per_pixel(this->getEncodedInfo().bitsPerPixel())))
+ , fSrcRowBytes(imageInfo.width() * (bytes_per_pixel(this->getEncodedInfo().bitsPerPixel())))
, fNumberPasses(numberPasses)
, fBitDepth(bitDepth)
{}
#include "SkCodec.h"
#include "SkCodecImageGenerator.h"
#include "SkData.h"
+#include "SkImageEncoder.h"
#include "SkFrontBufferedStream.h"
#include "SkMD5.h"
#include "SkRandom.h"
SkCodec::Result result = codec->getPixels(codec->getInfo(), pixelStorage.get(), rowBytes);
REPORTER_ASSERT(r, SkCodec::kSuccess == result);
}
+
+DEF_TEST(Codec_Png565, r) {
+ // Create an arbitrary 565 bitmap.
+ const char* path = "mandrill_512_q075.jpg";
+ SkAutoTDelete<SkStream> stream(resource(path));
+ SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.release()));
+ SkImageInfo info565 = codec->getInfo().makeColorType(kRGB_565_SkColorType);
+ SkBitmap bm1;
+ bm1.allocPixels(info565);
+ SkCodec::Result result = codec->getPixels(info565, bm1.getPixels(), bm1.rowBytes());
+ REPORTER_ASSERT(r, SkCodec::kSuccess == result);
+
+ // Encode the image to png.
+ sk_sp<SkData> data =
+ sk_sp<SkData>(SkImageEncoder::EncodeData(bm1, SkImageEncoder::kPNG_Type, 100));
+
+ // Prepare to decode. The codec should recognize that the PNG is 565.
+ codec.reset(SkCodec::NewFromData(data.get()));
+ REPORTER_ASSERT(r, kRGB_565_SkColorType == codec->getInfo().colorType());
+ REPORTER_ASSERT(r, kOpaque_SkAlphaType == codec->getInfo().alphaType());
+
+ SkBitmap bm2;
+ bm2.allocPixels(codec->getInfo());
+ result = codec->getPixels(codec->getInfo(), bm2.getPixels(), bm2.rowBytes());
+ REPORTER_ASSERT(r, SkCodec::kSuccess == result);
+
+ SkMD5::Digest d1, d2;
+ md5(bm1, &d1);
+ md5(bm2, &d2);
+ REPORTER_ASSERT(r, d1 == d2);
+}