YUV scale fix
There was a scaling mistake visible in some JPEG images because the ratio between Y, U and V planes were assumed to be the same ratios as the ratio between texture sizes, which was wrong because texture have a minimum size of 16 and are rounded up to the next POT. Since the ratios between Y and UV planes are generally 1, 2 or 4, rounding up to the next POT would generally preserve this ratio, so that this bug was not very visible, apart from very small jpeg images of 8 or less pixels in either width or height. BUG=457954 Committed: https://skia.googlesource.com/skia/+/e6eddf7dd85add7da41f22f2643bdd573ad1f1cf Review URL: https://codereview.chromium.org/922273002
This commit is contained in:
parent
db0f9516ae
commit
4ccce7ea61
@ -19,6 +19,10 @@
|
|||||||
#include "SkGr.h"
|
#include "SkGr.h"
|
||||||
#include "SkGradientShader.h"
|
#include "SkGradientShader.h"
|
||||||
|
|
||||||
|
#define YSIZE 8
|
||||||
|
#define USIZE 4
|
||||||
|
#define VSIZE 4
|
||||||
|
|
||||||
namespace skiagm {
|
namespace skiagm {
|
||||||
/**
|
/**
|
||||||
* This GM directly exercises GrYUVtoRGBEffect.
|
* This GM directly exercises GrYUVtoRGBEffect.
|
||||||
@ -35,14 +39,16 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
SkISize onISize() SK_OVERRIDE {
|
SkISize onISize() SK_OVERRIDE {
|
||||||
return SkISize::Make(334, 128);
|
return SkISize::Make(238, 84);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onOnceBeforeDraw() SK_OVERRIDE {
|
void onOnceBeforeDraw() SK_OVERRIDE {
|
||||||
SkImageInfo info = SkImageInfo::MakeA8(24, 24);
|
SkImageInfo yinfo = SkImageInfo::MakeA8(YSIZE, YSIZE);
|
||||||
fBmp[0].allocPixels(info);
|
fBmp[0].allocPixels(yinfo);
|
||||||
fBmp[1].allocPixels(info);
|
SkImageInfo uinfo = SkImageInfo::MakeA8(USIZE, USIZE);
|
||||||
fBmp[2].allocPixels(info);
|
fBmp[1].allocPixels(uinfo);
|
||||||
|
SkImageInfo vinfo = SkImageInfo::MakeA8(VSIZE, VSIZE);
|
||||||
|
fBmp[2].allocPixels(vinfo);
|
||||||
unsigned char* pixels[3];
|
unsigned char* pixels[3];
|
||||||
for (int i = 0; i < 3; ++i) {
|
for (int i = 0; i < 3; ++i) {
|
||||||
pixels[i] = (unsigned char*)fBmp[i].getPixels();
|
pixels[i] = (unsigned char*)fBmp[i].getPixels();
|
||||||
@ -51,8 +57,9 @@ protected:
|
|||||||
const int limit[] = {255, 0, 255};
|
const int limit[] = {255, 0, 255};
|
||||||
const int invl[] = {0, 255, 0};
|
const int invl[] = {0, 255, 0};
|
||||||
const int inc[] = {1, -1, 1};
|
const int inc[] = {1, -1, 1};
|
||||||
for (int j = 0; j < 576; ++j) {
|
for (int i = 0; i < 3; ++i) {
|
||||||
for (int i = 0; i < 3; ++i) {
|
const size_t nbBytes = fBmp[i].rowBytes() * fBmp[i].height();
|
||||||
|
for (size_t j = 0; j < nbBytes; ++j) {
|
||||||
pixels[i][j] = (unsigned char)color[i];
|
pixels[i][j] = (unsigned char)color[i];
|
||||||
color[i] = (color[i] == limit[i]) ? invl[i] : color[i] + inc[i];
|
color[i] = (color[i] == limit[i]) ? invl[i] : color[i] + inc[i];
|
||||||
}
|
}
|
||||||
@ -88,7 +95,8 @@ protected:
|
|||||||
|
|
||||||
static const SkScalar kDrawPad = 10.f;
|
static const SkScalar kDrawPad = 10.f;
|
||||||
static const SkScalar kTestPad = 10.f;
|
static const SkScalar kTestPad = 10.f;
|
||||||
static const SkScalar kColorSpaceOffset = 64.f;
|
static const SkScalar kColorSpaceOffset = 36.f;
|
||||||
|
SkISize sizes[3] = {{YSIZE, YSIZE}, {USIZE, USIZE}, {VSIZE, VSIZE}};
|
||||||
|
|
||||||
for (int space = kJPEG_SkYUVColorSpace; space <= kLastEnum_SkYUVColorSpace;
|
for (int space = kJPEG_SkYUVColorSpace; space <= kLastEnum_SkYUVColorSpace;
|
||||||
++space) {
|
++space) {
|
||||||
@ -105,9 +113,10 @@ protected:
|
|||||||
for (int i = 0; i < 6; ++i) {
|
for (int i = 0; i < 6; ++i) {
|
||||||
SkAutoTUnref<GrFragmentProcessor> fp(
|
SkAutoTUnref<GrFragmentProcessor> fp(
|
||||||
GrYUVtoRGBEffect::Create(texture[indices[i][0]],
|
GrYUVtoRGBEffect::Create(texture[indices[i][0]],
|
||||||
texture[indices[i][1]],
|
texture[indices[i][1]],
|
||||||
texture[indices[i][2]],
|
texture[indices[i][2]],
|
||||||
static_cast<SkYUVColorSpace>(space)));
|
sizes,
|
||||||
|
static_cast<SkYUVColorSpace>(space)));
|
||||||
if (fp) {
|
if (fp) {
|
||||||
SkMatrix viewMatrix;
|
SkMatrix viewMatrix;
|
||||||
viewMatrix.setTranslate(x, y);
|
viewMatrix.setTranslate(x, y);
|
||||||
|
@ -391,7 +391,7 @@ static GrTexture* load_yuv_texture(GrContext* ctx, const GrContentKey& optionalK
|
|||||||
|
|
||||||
SkAutoTUnref<GrFragmentProcessor>
|
SkAutoTUnref<GrFragmentProcessor>
|
||||||
yuvToRgbProcessor(GrYUVtoRGBEffect::Create(yuvTextures[0], yuvTextures[1], yuvTextures[2],
|
yuvToRgbProcessor(GrYUVtoRGBEffect::Create(yuvTextures[0], yuvTextures[1], yuvTextures[2],
|
||||||
yuvInfo.fColorSpace));
|
yuvInfo.fSize, yuvInfo.fColorSpace));
|
||||||
GrPaint paint;
|
GrPaint paint;
|
||||||
paint.addColorProcessor(yuvToRgbProcessor);
|
paint.addColorProcessor(yuvToRgbProcessor);
|
||||||
SkRect r = SkRect::MakeWH(SkIntToScalar(yuvInfo.fSize[0].fWidth),
|
SkRect r = SkRect::MakeWH(SkIntToScalar(yuvInfo.fSize[0].fWidth),
|
||||||
|
@ -18,8 +18,22 @@ namespace {
|
|||||||
class YUVtoRGBEffect : public GrFragmentProcessor {
|
class YUVtoRGBEffect : public GrFragmentProcessor {
|
||||||
public:
|
public:
|
||||||
static GrFragmentProcessor* Create(GrTexture* yTexture, GrTexture* uTexture,
|
static GrFragmentProcessor* Create(GrTexture* yTexture, GrTexture* uTexture,
|
||||||
GrTexture* vTexture, SkYUVColorSpace colorSpace) {
|
GrTexture* vTexture, SkISize sizes[3],
|
||||||
return SkNEW_ARGS(YUVtoRGBEffect, (yTexture, uTexture, vTexture, colorSpace));
|
SkYUVColorSpace colorSpace) {
|
||||||
|
SkScalar w[3], h[3];
|
||||||
|
w[0] = SkIntToScalar(sizes[0].fWidth) / SkIntToScalar(yTexture->width());
|
||||||
|
h[0] = SkIntToScalar(sizes[0].fHeight) / SkIntToScalar(yTexture->height());
|
||||||
|
w[1] = SkIntToScalar(sizes[1].fWidth) / SkIntToScalar(uTexture->width());
|
||||||
|
h[1] = SkIntToScalar(sizes[1].fHeight) / SkIntToScalar(uTexture->height());
|
||||||
|
w[2] = SkIntToScalar(sizes[2].fWidth) / SkIntToScalar(vTexture->width());
|
||||||
|
h[2] = SkIntToScalar(sizes[2].fHeight) / SkIntToScalar(vTexture->height());
|
||||||
|
SkMatrix yuvMatrix[3];
|
||||||
|
yuvMatrix[0] = GrCoordTransform::MakeDivByTextureWHMatrix(yTexture);
|
||||||
|
yuvMatrix[1] = yuvMatrix[0];
|
||||||
|
yuvMatrix[1].preScale(w[1] / w[0], h[1] / h[0]);
|
||||||
|
yuvMatrix[2] = yuvMatrix[0];
|
||||||
|
yuvMatrix[2].preScale(w[2] / w[0], h[2] / h[0]);
|
||||||
|
return SkNEW_ARGS(YUVtoRGBEffect, (yTexture, uTexture, vTexture, yuvMatrix, colorSpace));
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* name() const SK_OVERRIDE { return "YUV to RGB"; }
|
const char* name() const SK_OVERRIDE { return "YUV to RGB"; }
|
||||||
@ -53,9 +67,9 @@ public:
|
|||||||
fsBuilder->codeAppendf("\t%s = vec4(\n\t\t", outputColor);
|
fsBuilder->codeAppendf("\t%s = vec4(\n\t\t", outputColor);
|
||||||
fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].getType());
|
fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].getType());
|
||||||
fsBuilder->codeAppend(".r,\n\t\t");
|
fsBuilder->codeAppend(".r,\n\t\t");
|
||||||
fsBuilder->appendTextureLookup(samplers[1], coords[0].c_str(), coords[0].getType());
|
fsBuilder->appendTextureLookup(samplers[1], coords[1].c_str(), coords[1].getType());
|
||||||
fsBuilder->codeAppend(".r,\n\t\t");
|
fsBuilder->codeAppend(".r,\n\t\t");
|
||||||
fsBuilder->appendTextureLookup(samplers[2], coords[0].c_str(), coords[0].getType());
|
fsBuilder->appendTextureLookup(samplers[2], coords[2].c_str(), coords[2].getType());
|
||||||
fsBuilder->codeAppendf(".r,\n\t\t1.0) * %s;\n", yuvMatrix);
|
fsBuilder->codeAppendf(".r,\n\t\t1.0) * %s;\n", yuvMatrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,18 +103,20 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
YUVtoRGBEffect(GrTexture* yTexture, GrTexture* uTexture, GrTexture* vTexture,
|
YUVtoRGBEffect(GrTexture* yTexture, GrTexture* uTexture, GrTexture* vTexture,
|
||||||
SkYUVColorSpace colorSpace)
|
SkMatrix yuvMatrix[3], SkYUVColorSpace colorSpace)
|
||||||
: fCoordTransform(kLocal_GrCoordSet,
|
: fYTransform(kLocal_GrCoordSet, yuvMatrix[0], yTexture, GrTextureParams::kNone_FilterMode)
|
||||||
GrCoordTransform::MakeDivByTextureWHMatrix(yTexture),
|
|
||||||
yTexture, GrTextureParams::kNone_FilterMode)
|
|
||||||
, fYAccess(yTexture)
|
, fYAccess(yTexture)
|
||||||
|
, fUTransform(kLocal_GrCoordSet, yuvMatrix[1], uTexture, GrTextureParams::kNone_FilterMode)
|
||||||
, fUAccess(uTexture)
|
, fUAccess(uTexture)
|
||||||
|
, fVTransform(kLocal_GrCoordSet, yuvMatrix[2], vTexture, GrTextureParams::kNone_FilterMode)
|
||||||
, fVAccess(vTexture)
|
, fVAccess(vTexture)
|
||||||
, fColorSpace(colorSpace) {
|
, fColorSpace(colorSpace) {
|
||||||
this->initClassID<YUVtoRGBEffect>();
|
this->initClassID<YUVtoRGBEffect>();
|
||||||
this->addCoordTransform(&fCoordTransform);
|
this->addCoordTransform(&fYTransform);
|
||||||
this->addTextureAccess(&fYAccess);
|
this->addTextureAccess(&fYAccess);
|
||||||
|
this->addCoordTransform(&fUTransform);
|
||||||
this->addTextureAccess(&fUAccess);
|
this->addTextureAccess(&fUAccess);
|
||||||
|
this->addCoordTransform(&fVTransform);
|
||||||
this->addTextureAccess(&fVAccess);
|
this->addTextureAccess(&fVAccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,9 +131,11 @@ private:
|
|||||||
GrInvariantOutput::kWillNot_ReadInput);
|
GrInvariantOutput::kWillNot_ReadInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
GrCoordTransform fCoordTransform;
|
GrCoordTransform fYTransform;
|
||||||
GrTextureAccess fYAccess;
|
GrTextureAccess fYAccess;
|
||||||
|
GrCoordTransform fUTransform;
|
||||||
GrTextureAccess fUAccess;
|
GrTextureAccess fUAccess;
|
||||||
|
GrCoordTransform fVTransform;
|
||||||
GrTextureAccess fVAccess;
|
GrTextureAccess fVAccess;
|
||||||
SkYUVColorSpace fColorSpace;
|
SkYUVColorSpace fColorSpace;
|
||||||
|
|
||||||
@ -140,6 +158,7 @@ const GrGLfloat YUVtoRGBEffect::GLProcessor::kRec601ConversionMatrix[16] = {
|
|||||||
|
|
||||||
GrFragmentProcessor*
|
GrFragmentProcessor*
|
||||||
GrYUVtoRGBEffect::Create(GrTexture* yTexture, GrTexture* uTexture, GrTexture* vTexture,
|
GrYUVtoRGBEffect::Create(GrTexture* yTexture, GrTexture* uTexture, GrTexture* vTexture,
|
||||||
SkYUVColorSpace colorSpace) {
|
SkISize sizes[3], SkYUVColorSpace colorSpace) {
|
||||||
return YUVtoRGBEffect::Create(yTexture, uTexture, vTexture, colorSpace);
|
SkASSERT(yTexture && uTexture && vTexture && sizes);
|
||||||
|
return YUVtoRGBEffect::Create(yTexture, uTexture, vTexture, sizes, colorSpace);
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ namespace GrYUVtoRGBEffect {
|
|||||||
* Creates an effect that performs color conversion from YUV to RGB
|
* Creates an effect that performs color conversion from YUV to RGB
|
||||||
*/
|
*/
|
||||||
GrFragmentProcessor* Create(GrTexture* yTexture, GrTexture* uTexture, GrTexture* vTexture,
|
GrFragmentProcessor* Create(GrTexture* yTexture, GrTexture* uTexture, GrTexture* vTexture,
|
||||||
SkYUVColorSpace colorSpace);
|
SkISize sizes[3], SkYUVColorSpace colorSpace);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user