/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkCodecImageGenerator.h"
#include "SkMakeUnique.h"
#include "SkPixmapPriv.h"
#include "SkYUVAIndex.h"
std::unique_ptr<SkImageGenerator> SkCodecImageGenerator::MakeFromEncodedCodec(sk_sp<SkData> data) {
auto codec = SkCodec::MakeFromData(data);
if (nullptr == codec) {
return nullptr;
}
return std::unique_ptr<SkImageGenerator>(new SkCodecImageGenerator(std::move(codec), data));
}
std::unique_ptr<SkImageGenerator>
SkCodecImageGenerator::MakeFromCodec(std::unique_ptr<SkCodec> codec) {
return codec
? std::unique_ptr<SkImageGenerator>(new SkCodecImageGenerator(std::move(codec), nullptr))
: nullptr;
}
static SkImageInfo adjust_info(SkCodec* codec) {
SkImageInfo info = codec->getInfo();
if (kUnpremul_SkAlphaType == info.alphaType()) {
info = info.makeAlphaType(kPremul_SkAlphaType);
}
if (SkPixmapPriv::ShouldSwapWidthHeight(codec->getOrigin())) {
info = SkPixmapPriv::SwapWidthHeight(info);
}
return info;
}
SkCodecImageGenerator::SkCodecImageGenerator(std::unique_ptr<SkCodec> codec, sk_sp<SkData> data)
: INHERITED(adjust_info(codec.get()))
, fCodec(std::move(codec))
, fData(std::move(data))
{}
sk_sp<SkData> SkCodecImageGenerator::onRefEncodedData() {
return fData;
}
bool SkCodecImageGenerator::onGetPixels(const SkImageInfo& requestInfo, void* requestPixels,
size_t requestRowBytes, const Options&) {
SkPixmap dst(requestInfo, requestPixels, requestRowBytes);
auto decode = [this](const SkPixmap& pm) {
SkCodec::Result result = fCodec->getPixels(pm);
switch (result) {
case SkCodec::kSuccess:
case SkCodec::kIncompleteInput:
case SkCodec::kErrorInInput:
return true;
default:
return false;
}
};
return SkPixmapPriv::Orient(dst, fCodec->getOrigin(), decode);
}
bool SkCodecImageGenerator::onQueryYUVA8(SkYUVASizeInfo* sizeInfo,
SkYUVAIndex yuvaIndices[SkYUVAIndex::kIndexCount],
SkYUVColorSpace* colorSpace) const {
// This image generator always returns 3 separate non-interleaved planes
yuvaIndices[SkYUVAIndex::kY_Index].fIndex = 0;
yuvaIndices[SkYUVAIndex::kY_Index].fChannel = SkColorChannel::kR;
yuvaIndices[SkYUVAIndex::kU_Index].fIndex = 1;
yuvaIndices[SkYUVAIndex::kU_Index].fChannel = SkColorChannel::kR;
yuvaIndices[SkYUVAIndex::kV_Index].fIndex = 2;
yuvaIndices[SkYUVAIndex::kV_Index].fChannel = SkColorChannel::kR;
yuvaIndices[SkYUVAIndex::kA_Index].fIndex = -1;
yuvaIndices[SkYUVAIndex::kA_Index].fChannel = SkColorChannel::kR;
return fCodec->queryYUV8(sizeInfo, colorSpace);
}
bool SkCodecImageGenerator::onGetYUVA8Planes(const SkYUVASizeInfo& sizeInfo,
const SkYUVAIndex indices[SkYUVAIndex::kIndexCount],
void* planes[]) {
SkCodec::Result result = fCodec->getYUV8Planes(sizeInfo, planes);
// TODO: check indices
switch (result) {
case SkCodec::kSuccess:
case SkCodec::kIncompleteInput:
case SkCodec::kErrorInInput:
return true;
default:
return false;
}
}