skia2/tests/BitmapCopyTest.cpp
Brian Osman 6b622963a0 Reland "Stop conflating F16 with linear gamma"
This reverts commit 5f7b5e3624.

Reason for revert: Codec CL has re-landed.

Original change's description:
> Revert "Stop conflating F16 with linear gamma"
> 
> This reverts commit d1589c7213.
> 
> Reason for revert: Depends on skcms CL that's been reverted.
> 
> Original change's description:
> > Stop conflating F16 with linear gamma
> > 
> > Note to self: I debugged this, realized that the codecs
> > need to handle A2B -> XYZ, then realized that I just need
> > to wait for https://skia-review.googlesource.com/c/skia/+/136062
> > 
> > Bug: skia:
> > Change-Id: I594c22076feb3700b8a40c471a541fef5ff4e13e
> > Reviewed-on: https://skia-review.googlesource.com/137587
> > Commit-Queue: Brian Osman <brianosman@google.com>
> > Reviewed-by: Mike Klein <mtklein@google.com>
> 
> TBR=mtklein@google.com,brianosman@google.com
> 
> Change-Id: I6dca583697c8efd2563d30cb7ab9ef505b6903ae
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: skia:
> Reviewed-on: https://skia-review.googlesource.com/148860
> Reviewed-by: Brian Osman <brianosman@google.com>
> Commit-Queue: Brian Osman <brianosman@google.com>

TBR=mtklein@google.com,brianosman@google.com

# Not skipping CQ checks because original CL landed > 1 day ago.

Bug: skia:
Change-Id: Iee66531049843758e7ed4130b99d8df6a553d805
Reviewed-on: https://skia-review.googlesource.com/149700
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
2018-08-28 14:23:27 +00:00

222 lines
7.4 KiB
C++

/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkBitmap.h"
#include "SkColor.h"
#include "SkColorSpace.h"
#include "SkImageInfo.h"
#include "SkPoint.h"
#include "SkRect.h"
#include "SkRefCnt.h"
#include "SkSize.h"
#include "SkTypes.h"
#include "Test.h"
#include "sk_tool_utils.h"
static void init_src(const SkBitmap& bitmap) {
if (bitmap.getPixels()) {
bitmap.eraseColor(SK_ColorWHITE);
}
}
struct Pair {
SkColorType fColorType;
const char* fValid;
};
// Utility functions for copyPixelsTo()/copyPixelsFrom() tests.
// getPixel()
// setPixel()
// getSkConfigName()
// struct Coordinates
// reportCopyVerification()
// writeCoordPixels()
// Helper struct to contain pixel locations, while avoiding need for STL.
struct Coordinates {
const int length;
SkIPoint* const data;
explicit Coordinates(int _length): length(_length)
, data(new SkIPoint[length]) { }
~Coordinates(){
delete [] data;
}
SkIPoint* operator[](int i) const {
// Use with care, no bounds checking.
return data + i;
}
};
static const Pair gPairs[] = {
{ kUnknown_SkColorType, "0000000" },
{ kAlpha_8_SkColorType, "0100000" },
{ kRGB_565_SkColorType, "0101011" },
{ kARGB_4444_SkColorType, "0101111" },
{ kN32_SkColorType, "0101111" },
{ kRGBA_F16_SkColorType, "0101011" },
};
static const int W = 20;
static const int H = 33;
static void setup_src_bitmaps(SkBitmap* srcOpaque, SkBitmap* srcPremul,
SkColorType ct) {
sk_sp<SkColorSpace> colorSpace = nullptr;
if (kRGBA_F16_SkColorType == ct) {
colorSpace = SkColorSpace::MakeSRGB();
}
srcOpaque->allocPixels(SkImageInfo::Make(W, H, ct, kOpaque_SkAlphaType, colorSpace));
srcPremul->allocPixels(SkImageInfo::Make(W, H, ct, kPremul_SkAlphaType, colorSpace));
init_src(*srcOpaque);
init_src(*srcPremul);
}
DEF_TEST(BitmapCopy_extractSubset, reporter) {
for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) {
SkBitmap srcOpaque, srcPremul;
setup_src_bitmaps(&srcOpaque, &srcPremul, gPairs[i].fColorType);
SkBitmap bitmap(srcOpaque);
SkBitmap subset;
SkIRect r;
// Extract a subset which has the same width as the original. This
// catches a bug where we cloned the genID incorrectly.
r.set(0, 1, W, 3);
bitmap.setIsVolatile(true);
// Relies on old behavior of extractSubset failing if colortype is unknown
if (kUnknown_SkColorType != bitmap.colorType() && bitmap.extractSubset(&subset, r)) {
REPORTER_ASSERT(reporter, subset.width() == W);
REPORTER_ASSERT(reporter, subset.height() == 2);
REPORTER_ASSERT(reporter, subset.alphaType() == bitmap.alphaType());
REPORTER_ASSERT(reporter, subset.isVolatile() == true);
// Test copying an extracted subset.
for (size_t j = 0; j < SK_ARRAY_COUNT(gPairs); j++) {
SkBitmap copy;
bool success = sk_tool_utils::copy_to(&copy, gPairs[j].fColorType, subset);
if (!success) {
// Skip checking that success matches fValid, which is redundant
// with the code below.
REPORTER_ASSERT(reporter, gPairs[i].fColorType != gPairs[j].fColorType);
continue;
}
// When performing a copy of an extracted subset, the gen id should
// change.
REPORTER_ASSERT(reporter, copy.getGenerationID() != subset.getGenerationID());
REPORTER_ASSERT(reporter, copy.width() == W);
REPORTER_ASSERT(reporter, copy.height() == 2);
}
}
bitmap = srcPremul;
bitmap.setIsVolatile(false);
if (bitmap.extractSubset(&subset, r)) {
REPORTER_ASSERT(reporter, subset.alphaType() == bitmap.alphaType());
REPORTER_ASSERT(reporter, subset.isVolatile() == false);
}
}
}
#include "SkColorPriv.h"
#include "SkUtils.h"
/**
* Construct 4x4 pixels where we can look at a color and determine where it should be in the grid.
* alpha = 0xFF, blue = 0x80, red = x, green = y
*/
static void fill_4x4_pixels(SkPMColor colors[16]) {
for (int y = 0; y < 4; ++y) {
for (int x = 0; x < 4; ++x) {
colors[y*4+x] = SkPackARGB32(0xFF, x, y, 0x80);
}
}
}
static bool check_4x4_pixel(SkPMColor color, unsigned x, unsigned y) {
SkASSERT(x < 4 && y < 4);
return 0xFF == SkGetPackedA32(color) &&
x == SkGetPackedR32(color) &&
y == SkGetPackedG32(color) &&
0x80 == SkGetPackedB32(color);
}
/**
* Fill with all zeros, which will never match any value from fill_4x4_pixels
*/
static void clear_4x4_pixels(SkPMColor colors[16]) {
sk_memset32(colors, 0, 16);
}
// Much of readPixels is exercised by copyTo testing, since readPixels is the backend for that
// method. Here we explicitly test subset copies.
//
DEF_TEST(BitmapReadPixels, reporter) {
const int W = 4;
const int H = 4;
const size_t rowBytes = W * sizeof(SkPMColor);
const SkImageInfo srcInfo = SkImageInfo::MakeN32Premul(W, H);
SkPMColor srcPixels[16];
fill_4x4_pixels(srcPixels);
SkBitmap srcBM;
srcBM.installPixels(srcInfo, srcPixels, rowBytes);
SkImageInfo dstInfo = SkImageInfo::MakeN32Premul(W, H);
SkPMColor dstPixels[16];
const struct {
bool fExpectedSuccess;
SkIPoint fRequestedSrcLoc;
SkISize fRequestedDstSize;
// If fExpectedSuccess, check these, otherwise ignore
SkIPoint fExpectedDstLoc;
SkIRect fExpectedSrcR;
} gRec[] = {
{ true, { 0, 0 }, { 4, 4 }, { 0, 0 }, { 0, 0, 4, 4 } },
{ true, { 1, 1 }, { 2, 2 }, { 0, 0 }, { 1, 1, 3, 3 } },
{ true, { 2, 2 }, { 4, 4 }, { 0, 0 }, { 2, 2, 4, 4 } },
{ true, {-1,-1 }, { 2, 2 }, { 1, 1 }, { 0, 0, 1, 1 } },
{ false, {-1,-1 }, { 1, 1 }, { 0, 0 }, { 0, 0, 0, 0 } },
};
for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) {
clear_4x4_pixels(dstPixels);
dstInfo = dstInfo.makeWH(gRec[i].fRequestedDstSize.width(),
gRec[i].fRequestedDstSize.height());
bool success = srcBM.readPixels(dstInfo, dstPixels, rowBytes,
gRec[i].fRequestedSrcLoc.x(), gRec[i].fRequestedSrcLoc.y());
REPORTER_ASSERT(reporter, gRec[i].fExpectedSuccess == success);
if (success) {
const SkIRect srcR = gRec[i].fExpectedSrcR;
const int dstX = gRec[i].fExpectedDstLoc.x();
const int dstY = gRec[i].fExpectedDstLoc.y();
// Walk the dst pixels, and check if we got what we expected
for (int y = 0; y < H; ++y) {
for (int x = 0; x < W; ++x) {
SkPMColor dstC = dstPixels[y*4+x];
// get into src coordinates
int sx = x - dstX + srcR.x();
int sy = y - dstY + srcR.y();
if (srcR.contains(sx, sy)) {
REPORTER_ASSERT(reporter, check_4x4_pixel(dstC, sx, sy));
} else {
REPORTER_ASSERT(reporter, 0 == dstC);
}
}
}
}
}
}