aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--dm/DMWriteTask.cpp111
1 files changed, 56 insertions, 55 deletions
diff --git a/dm/DMWriteTask.cpp b/dm/DMWriteTask.cpp
index e30cbdbf85..04479e94fb 100644
--- a/dm/DMWriteTask.cpp
+++ b/dm/DMWriteTask.cpp
@@ -3,10 +3,9 @@
#include "DMUtil.h"
#include "SkColorPriv.h"
#include "SkCommandLineFlags.h"
-#include "SkImageDecoder.h"
#include "SkImageEncoder.h"
#include "SkString.h"
-#include "SkUnPreMultiply.h"
+#include "SkStream.h"
DEFINE_string2(writePath, w, "", "If set, write GMs here as .pngs.");
@@ -39,6 +38,58 @@ void WriteTask::makeDirOrFail(SkString dir) {
}
}
+// One file that first contains a .png of an SkBitmap, then its raw pixels.
+// We use this custom format to avoid premultiplied/unpremultiplied pixel conversions.
+struct PngAndRaw {
+ static bool Encode(SkBitmap bitmap, const char* path) {
+ SkFILEWStream stream(path);
+ if (!stream.isValid()) {
+ SkDebugf("Can't write %s.\n", path);
+ return false;
+ }
+
+ // Write a PNG first for humans and other tools to look at.
+ if (!SkImageEncoder::EncodeStream(&stream, bitmap, SkImageEncoder::kPNG_Type, 100)) {
+ SkDebugf("Can't encode a PNG.\n");
+ return false;
+ }
+
+ // Then write our secret raw pixels that only DM reads.
+ SkAutoLockPixels lock(bitmap);
+ return stream.write(bitmap.getPixels(), bitmap.getSize());
+ }
+
+ // This assumes bitmap already has allocated pixels of the correct size.
+ static bool Decode(const char* path, SkBitmap* bitmap) {
+ SkAutoTUnref<SkStreamRewindable> stream(SkStream::NewFromFile(path));
+ if (NULL == stream.get()) {
+ SkDebugf("Can't read %s.\n", path);
+ return false;
+ }
+
+ // The raw pixels are at the end of the stream. Seek ahead to skip beyond the encoded PNG.
+ const size_t bitmapBytes = bitmap->getSize();
+ if (stream->getLength() < bitmapBytes) {
+ SkDebugf("%s is too small to contain the bitmap we're looking for.\n", path);
+ return false;
+ }
+ SkAssertResult(stream->seek(stream->getLength() - bitmapBytes));
+
+ // Read the raw pixels.
+ // TODO(mtklein): can we install a pixelref that just hangs onto the stream instead of
+ // copying into a malloc'd buffer?
+ SkAutoLockPixels lock(*bitmap);
+ if (bitmapBytes != stream->read(bitmap->getPixels(), bitmapBytes)) {
+ SkDebugf("Couldn't read raw bitmap from %s at %lu of %lu.\n",
+ path, stream->getPosition(), stream->getLength());
+ return false;
+ }
+
+ SkASSERT(stream->isAtEnd());
+ return true;
+ }
+};
+
void WriteTask::draw() {
SkString dir(FLAGS_writePath[0]);
this->makeDirOrFail(dir);
@@ -48,10 +99,7 @@ void WriteTask::draw() {
}
SkString path = SkOSPath::SkPathJoin(dir.c_str(), fGmName.c_str());
path.append(".png");
- if (!SkImageEncoder::EncodeFile(path.c_str(),
- fBitmap,
- SkImageEncoder::kPNG_Type,
- 100/*quality*/)) {
+ if (!PngAndRaw::Encode(fBitmap, path.c_str())) {
this->fail();
}
}
@@ -85,8 +133,6 @@ static SkString path_to_expected_image(const char* root, const Task& task) {
filename.remove(filename.size() - suffixLength, suffixLength);
filename.append(".png");
- //SkDebugf("dir %s, filename %s\n", dir.c_str(), filename.c_str());
-
return SkOSPath::SkPathJoin(dir.c_str(), filename.c_str());
}
@@ -96,58 +142,13 @@ bool WriteTask::Expectations::check(const Task& task, SkBitmap bitmap) const {
return false;
}
- // PNG is stored unpremultiplied, and going from premul to unpremul to premul is lossy. To
- // skirt this problem, we decode the PNG into an unpremul bitmap, convert our bitmap to unpremul
- // if needed, and compare those. Each image goes once from premul to unpremul, never back.
const SkString path = path_to_expected_image(fRoot, task);
-
- SkAutoTUnref<SkStreamRewindable> stream(SkStream::NewFromFile(path.c_str()));
- if (NULL == stream.get()) {
- SkDebugf("Could not read %s.\n", path.c_str());
- return false;
- }
-
- SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(stream));
- if (NULL == decoder.get()) {
- SkDebugf("Could not find a decoder for %s.\n", path.c_str());
- return false;
- }
-
- const SkImageInfo info = bitmap.info();
-
SkBitmap expected;
- expected.allocPixels(info);
-
- // expected will be unpremultiplied.
- decoder->setRequireUnpremultipliedColors(true);
- if (!decoder->decode(stream, &expected, SkImageDecoder::kDecodePixels_Mode)) {
- SkDebugf("Could not decode %s.\n", path.c_str());
+ expected.allocPixels(bitmap.info());
+ if (!PngAndRaw::Decode(path.c_str(), &expected)) {
return false;
}
- // We always seem to decode to 8888. This puts 565 back in 565.
- if (expected.colorType() != bitmap.colorType()) {
- SkBitmap converted;
- SkAssertResult(expected.copyTo(&converted, bitmap.colorType()));
- expected.swap(converted);
- }
- SkASSERT(expected.config() == bitmap.config());
-
- // Manually unpremultiply 8888 bitmaps to match expected.
- // Their pixels are shared, concurrently even, so we must copy them.
- if (info.colorType() == kPMColor_SkColorType) {
- SkBitmap unpremul;
- unpremul.allocPixels(info);
-
- SkAutoLockPixels lockSrc(bitmap), lockDst(unpremul);
- const SkPMColor* src = (SkPMColor*)bitmap.getPixels();
- uint32_t* dst = (uint32_t*)unpremul.getPixels();
- for (size_t i = 0; i < bitmap.getSize()/4; i++) {
- dst[i] = SkUnPreMultiply::UnPreMultiplyPreservingByteOrder(src[i]);
- }
- bitmap.swap(unpremul);
- }
-
return BitmapsEqual(expected, bitmap);
}