diff options
author | commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2014-03-05 15:37:11 +0000 |
---|---|---|
committer | commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2014-03-05 15:37:11 +0000 |
commit | eef834f2be2f8f97410fd1d897e9bb11597c6a40 (patch) | |
tree | d1269d0cd5ee4f5d9058cad32a2e0b406e05affd /dm | |
parent | c4b3e75a7b5fd2f31e5573914e8344fc1b0bf17a (diff) |
DM: read image files without an extra copy
BUG=skia:
R=halcanary@google.com, reed@google.com, bsalomon@google.com, mtklein@google.com
Author: mtklein@chromium.org
Review URL: https://codereview.chromium.org/185263012
git-svn-id: http://skia.googlecode.com/svn/trunk@13669 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'dm')
-rw-r--r-- | dm/DMWriteTask.cpp | 47 |
1 files changed, 26 insertions, 21 deletions
diff --git a/dm/DMWriteTask.cpp b/dm/DMWriteTask.cpp index 04479e94fb..890a4bb052 100644 --- a/dm/DMWriteTask.cpp +++ b/dm/DMWriteTask.cpp @@ -4,8 +4,9 @@ #include "SkColorPriv.h" #include "SkCommandLineFlags.h" #include "SkImageEncoder.h" -#include "SkString.h" +#include "SkMallocPixelRef.h" #include "SkStream.h" +#include "SkString.h" DEFINE_string2(writePath, w, "", "If set, write GMs here as .pngs."); @@ -38,6 +39,8 @@ void WriteTask::makeDirOrFail(SkString dir) { } } +namespace { + // 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 { @@ -54,42 +57,45 @@ struct PngAndRaw { return false; } + // Pad out so the raw pixels start 4-byte aligned. + const uint32_t maxPadding = 0; + const size_t pos = stream.bytesWritten(); + stream.write(&maxPadding, SkAlign4(pos) - pos); + // 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()) { + static bool Decode(const char* path, SkImageInfo info, SkBitmap* bitmap) { + SkAutoTUnref<SkData> data(SkData::NewFromFileName(path)); + if (!data) { 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) { + // The raw pixels are at the end of the file. We'll skip the encoded PNG at the front. + const size_t rowBytes = info.minRowBytes(); // Assume densely packed. + const size_t bitmapBytes = info.getSafeSize(rowBytes); + if (data->size() < 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()); + const size_t offset = data->size() - bitmapBytes; + SkAutoTUnref<SkPixelRef> pixels( + SkMallocPixelRef::NewWithData(info, rowBytes, NULL/*ctable*/, data, offset)); + SkASSERT(pixels); + + bitmap->setConfig(info, rowBytes); + bitmap->setPixelRef(pixels); return true; } }; +} // namespace + void WriteTask::draw() { SkString dir(FLAGS_writePath[0]); this->makeDirOrFail(dir); @@ -144,8 +150,7 @@ bool WriteTask::Expectations::check(const Task& task, SkBitmap bitmap) const { const SkString path = path_to_expected_image(fRoot, task); SkBitmap expected; - expected.allocPixels(bitmap.info()); - if (!PngAndRaw::Decode(path.c_str(), &expected)) { + if (!PngAndRaw::Decode(path.c_str(), bitmap.info(), &expected)) { return false; } |