apply codec origin in generator
Bug: skia: Change-Id: I383dacb49b1e3c88467ccdbf3288764bb1bbf01a Reviewed-on: https://skia-review.googlesource.com/58600 Reviewed-by: Leon Scroggins <scroggo@google.com> Commit-Queue: Mike Reed <reed@google.com>
This commit is contained in:
parent
d28a79d495
commit
fa15877f48
@ -48,3 +48,29 @@ private:
|
|||||||
|
|
||||||
DEF_GM( return new EncodeGM; )
|
DEF_GM( return new EncodeGM; )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
DEF_SIMPLE_GM(jpeg_orientation, canvas, 1000, 1000) {
|
||||||
|
static sk_sp<SkImage> imgs[8];
|
||||||
|
if (!imgs[0]) {
|
||||||
|
for (int i = 0; i < 8; ++i) {
|
||||||
|
SkString path;
|
||||||
|
path.printf("/skia/orientation/Landscape_%d.jpg", i + 1);
|
||||||
|
auto stream = SkStream::MakeFromFile(path.c_str());
|
||||||
|
auto data = SkData::MakeFromStream(stream.get(), stream->getLength());
|
||||||
|
imgs[i] = SkImage::MakeFromEncoded(data, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
canvas->scale(0.25, 0.25);
|
||||||
|
for (int i = 0; i < 8; ++i) {
|
||||||
|
SkImage* img = imgs[i].get();
|
||||||
|
canvas->drawImage(img, 0, 0, nullptr);
|
||||||
|
canvas->translate(0, img->height());
|
||||||
|
if (i == 3) {
|
||||||
|
canvas->translate(img->width(), -4*img->height());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "SkEncodedImageFormat.h"
|
#include "SkEncodedImageFormat.h"
|
||||||
#include "SkEncodedInfo.h"
|
#include "SkEncodedInfo.h"
|
||||||
#include "SkImageInfo.h"
|
#include "SkImageInfo.h"
|
||||||
|
#include "SkPixmap.h"
|
||||||
#include "SkSize.h"
|
#include "SkSize.h"
|
||||||
#include "SkStream.h"
|
#include "SkStream.h"
|
||||||
#include "SkTypes.h"
|
#include "SkTypes.h"
|
||||||
@ -355,6 +356,10 @@ public:
|
|||||||
return this->getPixels(info, pixels, rowBytes, nullptr);
|
return this->getPixels(info, pixels, rowBytes, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result getPixels(const SkPixmap& pm, const Options* opts = nullptr) {
|
||||||
|
return this->getPixels(pm.info(), pm.writable_addr(), pm.rowBytes(), opts);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If decoding to YUV is supported, this returns true. Otherwise, this
|
* If decoding to YUV is supported, this returns true. Otherwise, this
|
||||||
* returns false and does not modify any of the parameters.
|
* returns false and does not modify any of the parameters.
|
||||||
|
@ -5,8 +5,41 @@
|
|||||||
* found in the LICENSE file.
|
* found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "SkAutoPixmapStorage.h"
|
||||||
#include "SkCodecImageGenerator.h"
|
#include "SkCodecImageGenerator.h"
|
||||||
#include "SkMakeUnique.h"
|
#include "SkMakeUnique.h"
|
||||||
|
#include "SkPixmapPriv.h"
|
||||||
|
|
||||||
|
#define kMirrorX SkPixmapPriv::kMirrorX
|
||||||
|
#define kMirrorY SkPixmapPriv::kMirrorY
|
||||||
|
#define kSwapXY SkPixmapPriv::kSwapXY
|
||||||
|
|
||||||
|
const uint8_t gOrientationFlags[] = {
|
||||||
|
0, // kTopLeft_Origin
|
||||||
|
kMirrorX, // kTopRight_Origin
|
||||||
|
kMirrorX | kMirrorY, // kBottomRight_Origin
|
||||||
|
kMirrorY, // kBottomLeft_Origin
|
||||||
|
kSwapXY, // kLeftTop_Origin
|
||||||
|
kMirrorX | kSwapXY, // kRightTop_Origin
|
||||||
|
kMirrorX | kMirrorY | kSwapXY, // kRightBottom_Origin
|
||||||
|
kMirrorY | kSwapXY, // kLeftBottom_Origin
|
||||||
|
};
|
||||||
|
|
||||||
|
SkPixmapPriv::OrientFlags SkPixmapPriv::OriginToOrient(SkCodec::Origin o) {
|
||||||
|
unsigned io = static_cast<int>(o) - 1;
|
||||||
|
SkASSERT(io < SK_ARRAY_COUNT(gOrientationFlags));
|
||||||
|
return static_cast<SkPixmapPriv::OrientFlags>(gOrientationFlags[io]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool should_swap_width_height(SkCodec::Origin o) {
|
||||||
|
return SkToBool(SkPixmapPriv::OriginToOrient(o) & kSwapXY);
|
||||||
|
}
|
||||||
|
|
||||||
|
static SkImageInfo swap_width_height(SkImageInfo info) {
|
||||||
|
return info.makeWH(info.height(), info.width());
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
std::unique_ptr<SkImageGenerator> SkCodecImageGenerator::MakeFromEncodedCodec(sk_sp<SkData> data) {
|
std::unique_ptr<SkImageGenerator> SkCodecImageGenerator::MakeFromEncodedCodec(sk_sp<SkData> data) {
|
||||||
auto codec = SkCodec::MakeFromData(data);
|
auto codec = SkCodec::MakeFromData(data);
|
||||||
@ -17,16 +50,19 @@ std::unique_ptr<SkImageGenerator> SkCodecImageGenerator::MakeFromEncodedCodec(sk
|
|||||||
return std::unique_ptr<SkImageGenerator>(new SkCodecImageGenerator(std::move(codec), data));
|
return std::unique_ptr<SkImageGenerator>(new SkCodecImageGenerator(std::move(codec), data));
|
||||||
}
|
}
|
||||||
|
|
||||||
static SkImageInfo adjust_info(const SkImageInfo& info) {
|
static SkImageInfo adjust_info(SkCodec* codec) {
|
||||||
SkImageInfo newInfo = info;
|
SkImageInfo info = codec->getInfo();
|
||||||
if (kUnpremul_SkAlphaType == info.alphaType()) {
|
if (kUnpremul_SkAlphaType == info.alphaType()) {
|
||||||
newInfo = newInfo.makeAlphaType(kPremul_SkAlphaType);
|
info = info.makeAlphaType(kPremul_SkAlphaType);
|
||||||
}
|
}
|
||||||
return newInfo;
|
if (should_swap_width_height(codec->getOrigin())) {
|
||||||
|
info = swap_width_height(info);
|
||||||
|
}
|
||||||
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
SkCodecImageGenerator::SkCodecImageGenerator(std::unique_ptr<SkCodec> codec, sk_sp<SkData> data)
|
SkCodecImageGenerator::SkCodecImageGenerator(std::unique_ptr<SkCodec> codec, sk_sp<SkData> data)
|
||||||
: INHERITED(adjust_info(codec->getInfo()))
|
: INHERITED(adjust_info(codec.get()))
|
||||||
, fCodec(std::move(codec))
|
, fCodec(std::move(codec))
|
||||||
, fData(std::move(data))
|
, fData(std::move(data))
|
||||||
{}
|
{}
|
||||||
@ -35,13 +71,35 @@ SkData* SkCodecImageGenerator::onRefEncodedData() {
|
|||||||
return SkRef(fData.get());
|
return SkRef(fData.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SkCodecImageGenerator::onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
|
bool SkCodecImageGenerator::onGetPixels(const SkImageInfo& requestInfo, void* requestPixels,
|
||||||
const Options& opts) {
|
size_t requestRowBytes, const Options& opts) {
|
||||||
|
const SkCodec::Origin origin = fCodec->getOrigin();
|
||||||
|
const SkPixmap request(requestInfo, requestPixels, requestRowBytes);
|
||||||
|
const SkPixmap* codecMap = &request;
|
||||||
|
SkAutoPixmapStorage storage; // used if we have to post-orient the output from the codec
|
||||||
|
|
||||||
|
if (origin != SkCodec::kTopLeft_Origin) {
|
||||||
|
SkImageInfo info = requestInfo;
|
||||||
|
if (should_swap_width_height(origin)) {
|
||||||
|
info = swap_width_height(info);
|
||||||
|
}
|
||||||
|
// need a tmp buffer to receive the pixels, so we can post-orient them
|
||||||
|
if (!storage.tryAlloc(info)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
codecMap = &storage;
|
||||||
|
}
|
||||||
|
|
||||||
SkCodec::Options codecOpts;
|
SkCodec::Options codecOpts;
|
||||||
codecOpts.fPremulBehavior = opts.fBehavior;
|
codecOpts.fPremulBehavior = opts.fBehavior;
|
||||||
SkCodec::Result result = fCodec->getPixels(info, pixels, rowBytes, &codecOpts);
|
SkCodec::Result result = fCodec->getPixels(*codecMap, &codecOpts);
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case SkCodec::kSuccess:
|
case SkCodec::kSuccess:
|
||||||
|
if (codecMap != &request) {
|
||||||
|
return SkPixmapPriv::Orient(request, *codecMap,
|
||||||
|
SkPixmapPriv::OriginToOrient(origin));
|
||||||
|
}
|
||||||
|
// fall through
|
||||||
case SkCodec::kIncompleteInput:
|
case SkCodec::kIncompleteInput:
|
||||||
case SkCodec::kErrorInInput:
|
case SkCodec::kErrorInInput:
|
||||||
return true;
|
return true;
|
||||||
|
@ -15,9 +15,10 @@
|
|||||||
#include "SkMask.h"
|
#include "SkMask.h"
|
||||||
#include "SkNx.h"
|
#include "SkNx.h"
|
||||||
#include "SkPM4f.h"
|
#include "SkPM4f.h"
|
||||||
#include "SkPixmap.h"
|
#include "SkPixmapPriv.h"
|
||||||
#include "SkReadPixelsRec.h"
|
#include "SkReadPixelsRec.h"
|
||||||
#include "SkSurface.h"
|
#include "SkSurface.h"
|
||||||
|
#include "SkTemplates.h"
|
||||||
#include "SkUtils.h"
|
#include "SkUtils.h"
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -381,3 +382,82 @@ bool SkPixmap::computeIsOpaque() const {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <typename T, typename F>
|
||||||
|
void apply(const SkPixmap& dst, const SkPixmap& src, unsigned flags, F getAddr) {
|
||||||
|
const int maxX = dst.width() - 1;
|
||||||
|
const int maxY = dst.height() - 1;
|
||||||
|
T* dstRow = (T*)dst.writable_addr();
|
||||||
|
for (int dy = 0; dy < dst.height(); ++dy) {
|
||||||
|
for (int dx = 0; dx < dst.width(); ++dx) {
|
||||||
|
int sx = dx;
|
||||||
|
int sy = dy;
|
||||||
|
if (flags & SkPixmapPriv::kMirrorX) {
|
||||||
|
sx = maxX - sx;
|
||||||
|
}
|
||||||
|
if (flags & SkPixmapPriv::kMirrorY) {
|
||||||
|
sy = maxY - sy;
|
||||||
|
}
|
||||||
|
if (flags & SkPixmapPriv::kSwapXY) {
|
||||||
|
SkTSwap<int>(sx, sy);
|
||||||
|
}
|
||||||
|
dstRow[dx] = getAddr(src, sx, sy);
|
||||||
|
}
|
||||||
|
dstRow = SkTAddOffset<T>(dstRow, dst.rowBytes());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool apply_orientation(const SkPixmap& dst, const SkPixmap& src, unsigned flags) {
|
||||||
|
SkASSERT(dst.colorType() == src.colorType());
|
||||||
|
|
||||||
|
switch (dst.info().bytesPerPixel()) {
|
||||||
|
case 1:
|
||||||
|
apply<uint8_t>(dst, src, flags, [](const SkPixmap& pm, int x, int y) {
|
||||||
|
return *pm.addr8(x, y);
|
||||||
|
}); break;
|
||||||
|
case 2:
|
||||||
|
apply<uint16_t>(dst, src, flags, [](const SkPixmap& pm, int x, int y) {
|
||||||
|
return *pm.addr16(x, y);
|
||||||
|
}); break;
|
||||||
|
case 4:
|
||||||
|
apply<uint32_t>(dst, src, flags, [](const SkPixmap& pm, int x, int y) {
|
||||||
|
return *pm.addr32(x, y);
|
||||||
|
}); break;
|
||||||
|
case 8:
|
||||||
|
apply<uint64_t>(dst, src, flags, [](const SkPixmap& pm, int x, int y) {
|
||||||
|
return *pm.addr64(x, y);
|
||||||
|
}); break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SkPixmapPriv::Orient(const SkPixmap& dst, const SkPixmap& src, OrientFlags flags) {
|
||||||
|
SkASSERT((flags & ~(kMirrorX | kMirrorY | kSwapXY)) == 0);
|
||||||
|
if (src.colorType() != dst.colorType()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// note: we just ignore alphaType and colorSpace for this transformation
|
||||||
|
|
||||||
|
int w = src.width();
|
||||||
|
int h = src.height();
|
||||||
|
if (flags & kSwapXY) {
|
||||||
|
SkTSwap(w, h);
|
||||||
|
}
|
||||||
|
if (dst.width() != w || dst.height() != h) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (w == 0 || h == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for aliasing to self
|
||||||
|
if (src.addr() == dst.addr()) {
|
||||||
|
return flags == 0;
|
||||||
|
}
|
||||||
|
return apply_orientation(dst, src, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
33
src/core/SkPixmapPriv.h
Normal file
33
src/core/SkPixmapPriv.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015 Google Inc.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
|
* found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SkPixmapPriv_DEFINED
|
||||||
|
#define SkPixmapPriv_DEFINED
|
||||||
|
|
||||||
|
#include "SkPixmap.h"
|
||||||
|
#include "SkCodec.h"
|
||||||
|
|
||||||
|
class SkPixmapPriv {
|
||||||
|
public:
|
||||||
|
// These flag are applied in this order (swap is applied last)
|
||||||
|
enum OrientFlags {
|
||||||
|
kMirrorX = 1 << 0,
|
||||||
|
kMirrorY = 1 << 1,
|
||||||
|
kSwapXY = 1 << 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
static OrientFlags OriginToOrient(SkCodec::Origin);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the pixels in this pixmap into dst, applying the orientation transformations specified
|
||||||
|
* by the flags. If the inputs are invalid, this returns false and no copy is made.
|
||||||
|
*/
|
||||||
|
static bool Orient(const SkPixmap& dst, const SkPixmap& src, OrientFlags);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue
Block a user