Commit bb1c5656 authored by kbr@google.com's avatar kbr@google.com

2011-01-28 Kenneth Russell <kbr@google.com>

        Reviewed by Chris Marrin.

        WebGL shows PNG Textures with indexed colors too dark
        https://bugs.webkit.org/show_bug.cgi?id=47477

        Added test case for upload of indexed PNG images to
        gl-teximage.html in the Khronos WebGL conformance tests.
        Synchronized this test with the Khronos repository.

        * fast/canvas/webgl/gl-teximage-expected.txt:
        * fast/canvas/webgl/gl-teximage.html:
        * fast/canvas/webgl/resources/red-indexed.png: Added.
2011-01-28  Kenneth Russell  <kbr@google.com>

        Reviewed by Chris Marrin.

        WebGL shows PNG Textures with indexed colors too dark
        https://bugs.webkit.org/show_bug.cgi?id=47477

        Properly handle indexed PNG images by re-rendering them as RGBA
        images before upload. Verified with this layout test and the test
        cases from bugs 47477 and 53269.

        * platform/graphics/cg/GraphicsContext3DCG.cpp:
        (WebCore::GraphicsContext3D::getImageData):


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@77108 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 45c6a5f4
2011-01-28 Kenneth Russell <kbr@google.com>
Reviewed by Chris Marrin.
WebGL shows PNG Textures with indexed colors too dark
https://bugs.webkit.org/show_bug.cgi?id=47477
Added test case for upload of indexed PNG images to
gl-teximage.html in the Khronos WebGL conformance tests.
Synchronized this test with the Khronos repository.
* fast/canvas/webgl/gl-teximage-expected.txt:
* fast/canvas/webgl/gl-teximage.html:
* fast/canvas/webgl/resources/red-indexed.png: Added.
2011-01-23 MORITA Hajime <morrita@google.com>
Reviewed by Eric Seidel.
......@@ -48,6 +48,13 @@ PASS pixels should be same regardless of gamma settings.
check pixels are UN pre-multiplied
PASS getError was expected value: NO_ERROR : Should be no errors from setup.
PASS Half the pixels in channel 0 should be >= 128,128,128. found 49%
PASS Half the pixels in channel 0 should be < 128,128,128. found 51%
PASS Half the pixels in channel 1 should be >= 128,128,128. found 49%
PASS Half the pixels in channel 1 should be < 128,128,128. found 51%
PASS Half the pixels in channel 2 should be >= 128,128,128. found 49%
PASS Half the pixels in channel 2 should be < 128,128,128. found 51%
PASS getError was expected value: NO_ERROR : Should be no errors from setup.
PASS Half the pixels in channel 0 should be >= 128,128,128. found 50%
PASS Half the pixels in channel 0 should be < 128,128,128. found 50%
PASS Half the pixels in channel 1 should be >= 128,128,128. found 50%
......@@ -55,6 +62,14 @@ PASS Half the pixels in channel 1 should be < 128,128,128. found 50%
PASS Half the pixels in channel 2 should be >= 128,128,128. found 50%
PASS Half the pixels in channel 2 should be < 128,128,128. found 50%
check canvas pixels are UN pre-multiplied
PASS getError was expected value: NO_ERROR : Should be no errors from setup.
PASS pixel 0, 0 should be within 4 units of 255, 255, 255, 127 was 255, 255, 255, 127
check canvas pixels are pre-multiplied
PASS getError was expected value: NO_ERROR : Should be no errors from setup.
PASS pixel 0, 0 should be within 4 units of 127, 127, 127, 127 was 127, 127, 127, 127
check pixels are pre-multiplied
PASS getError was expected value: NO_ERROR : Should be no errors from setup
PASS pixels should all be 0.
......@@ -102,6 +117,10 @@ PASS getError was expected value: NO_ERROR : Should be no errors from setup
PASS getError was expected value: NO_ERROR : Should be no errors
PASS uploading PNGs with same data but various ICC profiles should generate the same results
check uploading of indexed PNG images
PASS getError was expected value: NO_ERROR : Should be no errors from setup
PASS pixel 128, 8 should be within 10 units of 255, 0, 0, 255 was 253, 0, 0, 255
PASS successfullyParsed is true
TEST COMPLETE
......
......@@ -34,6 +34,7 @@ var imgURLs = [
'resources/zero-alpha.png',
'resources/3x3.png',
'resources/blue-1x1.jpg',
'resources/red-indexed.png',
'resources/green-2x2-16bit.png',
'resources/small-square-with-colorspin-profile.jpg',
'resources/small-square-with-colorspin-profile.png',
......@@ -43,10 +44,10 @@ var imgURLs = [
'resources/small-square-with-smpte-c-profile.png',
'resources/small-square-with-srgb-iec61966-2.1-profile.png'];
wtu.loadImagesAsync(imgURLs, runTests);
function runTests(imgs) {
var loc = gl.getUniformLocation(program, "tex");
gl.uniform1i(loc, 0);
......@@ -202,44 +203,72 @@ function runTests(imgs) {
debug("");
debug("check pixels are UN pre-multiplied");
for (var ii = 0; ii < 2; ++ii) {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
if (ii == 0) {
var canvas2d = document.createElement("canvas");
canvas2d.width = 256;
canvas2d.height = 1;
var ctx = canvas2d.getContext("2d");
ctx.drawImage(imgs['resources/gray-ramp-256-with-128-alpha.png'], 0, 0);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, canvas2d);
} else {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
imgs['resources/gray-ramp-256-with-128-alpha.png']);
}
glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
wtu.drawQuad(gl);
var buf = new Uint8Array(width * height * 4);
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
var lt128Count = [0, 0, 0];
var ge128Count = [0, 0, 0];
for (var jj = 0; jj < width; ++jj) {
var off = jj * 4;
for (var cc = 0; cc < 3; ++cc) {
if (buf[off + cc] < 128) {
++lt128Count[cc];
} else {
++ge128Count[cc];
}
}
}
// Not sure the exact count here because gamma does effect drawing into the
// canvas but it should be close to 50% so I'll pass 45%
for (var jj = 0; jj < 3; ++jj) {
assertMsg(ge128Count[jj] > 256 * 0.45,
"Half the pixels in channel " + jj +
" should be >= 128,128,128. found " +
((ge128Count[jj] / 256) * 100).toFixed() + "%");
assertMsg(lt128Count[jj] > 256 * 0.45,
"Half the pixels in channel " + jj +
" should be < 128,128,128. found " +
((lt128Count[jj] / 256) * 100).toFixed() + "%");
}
}
debug("");
debug("check canvas pixels are UN pre-multiplied");
var canvas2d = document.createElement("canvas");
canvas2d.width = 256;
canvas2d.width = 1;
canvas2d.height = 1;
//canvas2d.style.height = "40px";
//var description = document.getElementById("description");
//description.appendChild(canvas2d);
var ctx = canvas2d.getContext("2d");
ctx.fillStyle ="rgba(255,255,255,0.5)";
ctx.fillRect(0, 0, 256, 1);
ctx.drawImage(imgs['resources/gray-ramp-256-with-128-alpha.png'], 0, 0);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, canvas2d);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas2d);
wtu.drawQuad(gl);
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
checkPixelRange(buf, 0, 0, [255, 255, 255, 127], 4);
debug("");
debug("check canvas pixels are pre-multiplied");
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas2d);
wtu.drawQuad(gl);
var ref = new Uint8Array(width * height * 4);
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, ref);
var lt128Count = [0, 0, 0];
var ge128Count = [0, 0, 0];
for (var jj = 0; jj < width; ++jj) {
var off = jj * 4;
for (var cc = 0; cc < 3; ++cc) {
if (buf[off + cc] < 128) {
++lt128Count[cc];
} else {
++ge128Count[cc];
}
}
}
// Not sure the exact count here because gamma does effect drawing into the
// canvas but it should be close to 50% so I'll pass 45%
for (var jj = 0; jj < 3; ++jj) {
assertMsg(ge128Count[jj] > 256 * 0.45,
"Half the pixels in channel " + jj +
" should be >= 128,128,128. found " +
((ge128Count[jj] / 256) * 100).toFixed() + "%");
assertMsg(lt128Count[jj] > 256 * 0.45,
"Half the pixels in channel " + jj +
" should be < 128,128,128. found " +
((lt128Count[jj] / 256) * 100).toFixed() + "%");
}
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
checkPixelRange(buf, 0, 0, [127, 127, 127, 127], 4);
debug("");
debug("check pixels are pre-multiplied");
......@@ -350,6 +379,16 @@ function runTests(imgs) {
assertMsg(same, "uploading PNGs with same data but various ICC profiles should generate the same results");
}
debug("");
debug("check uploading of indexed PNG images");
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
imgs['resources/red-indexed.png']);
glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
wtu.drawQuad(gl);
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
// The image should be red.
checkPixelRange(buf, middle, center, [ 255, 0, 0, 255 ], 10);
debug("");
successfullyParsed = true;
shouldBeTrue("successfullyParsed");
......
2011-01-28 Kenneth Russell <kbr@google.com>
Reviewed by Chris Marrin.
WebGL shows PNG Textures with indexed colors too dark
https://bugs.webkit.org/show_bug.cgi?id=47477
Properly handle indexed PNG images by re-rendering them as RGBA
images before upload. Verified with this layout test and the test
cases from bugs 47477 and 53269.
* platform/graphics/cg/GraphicsContext3DCG.cpp:
(WebCore::GraphicsContext3D::getImageData):
2011-01-27 MORITA Hajime <morrita@google.com>
Reviewed by Dimitri Glazkov.
......@@ -116,6 +116,35 @@ bool GraphicsContext3D::getImageData(Image* image,
size_t height = CGImageGetHeight(cgImage);
if (!width || !height)
return false;
// See whether the image is using an indexed color space, and if
// so, re-render it into an RGB color space. The image re-packing
// code requires color data, not color table indices, for the
// image data.
RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGImageGetColorSpace(cgImage));
CGColorSpaceModel model = CGColorSpaceGetModel(colorSpace.get());
RetainPtr<CGContextRef> bitmapContext;
if (model == kCGColorSpaceModelIndexed) {
RetainPtr<CGColorSpaceRef> baseColorSpace(CGColorSpaceGetBaseColorSpace(colorSpace.get()));
// FIXME: we should probably manually convert the image by indexing into
// the color table, which would allow us to avoid premultiplying the
// alpha channel. Creation of a bitmap context with an alpha channel
// doesn't seem to work unless it's premultiplied.
bitmapContext.adoptCF(CGBitmapContextCreate(0, width, height, 8, width * 4,
deviceRGBColorSpaceRef(),
kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host));
if (!bitmapContext)
return false;
CGContextSetBlendMode(bitmapContext.get(), kCGBlendModeCopy);
CGContextSetInterpolationQuality(bitmapContext.get(), kCGInterpolationNone);
CGContextDrawImage(bitmapContext.get(), CGRectMake(0, 0, width, height), cgImage);
// Now discard the original CG image and replace it with a copy from the bitmap context.
decodedImage.adoptCF(CGBitmapContextCreateImage(bitmapContext.get()));
cgImage = decodedImage.get();
}
size_t bitsPerComponent = CGImageGetBitsPerComponent(cgImage);
size_t bitsPerPixel = CGImageGetBitsPerPixel(cgImage);
if (bitsPerComponent != 8 && bitsPerComponent != 16)
......@@ -168,10 +197,11 @@ bool GraphicsContext3D::getImageData(Image* image,
AlphaFormat alphaFormat = AlphaFormatNone;
switch (CGImageGetAlphaInfo(cgImage)) {
case kCGImageAlphaPremultipliedFirst:
// This path is only accessible for MacOS earlier than 10.6.4.
// This is a special case for texImage2D with HTMLCanvasElement input,
// in which case image->data() should be null.
ASSERT(!image->data());
// in which case image->data() should be null, or indexed color models,
// where we need premultiplied alpha to create the bitmap context
// successfully.
ASSERT(!image->data() || model == kCGColorSpaceModelIndexed);
if (!premultiplyAlpha)
neededAlphaOp = AlphaDoUnmultiply;
alphaFormat = AlphaFormatFirst;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment