Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(33)

Side by Side Diff: dm/DMWriteTask.cpp

Issue 185263012: DM: read image files without an extra copy (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: three-lnies Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | include/core/SkStream.h » ('j') | include/core/SkStream.h » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #include "DMWriteTask.h" 1 #include "DMWriteTask.h"
2 2
3 #include "DMUtil.h" 3 #include "DMUtil.h"
4 #include "SkColorPriv.h" 4 #include "SkColorPriv.h"
5 #include "SkCommandLineFlags.h" 5 #include "SkCommandLineFlags.h"
6 #include "SkImageEncoder.h" 6 #include "SkImageEncoder.h"
7 #include "SkMallocPixelRef.h"
8 #include "SkStream.h"
7 #include "SkString.h" 9 #include "SkString.h"
8 #include "SkStream.h"
9 10
10 DEFINE_string2(writePath, w, "", "If set, write GMs here as .pngs."); 11 DEFINE_string2(writePath, w, "", "If set, write GMs here as .pngs.");
11 12
12 namespace DM { 13 namespace DM {
13 14
14 // Splits off the last N suffixes of name (splitting on _) and appends them to o ut. 15 // Splits off the last N suffixes of name (splitting on _) and appends them to o ut.
15 // Returns the total number of characters consumed. 16 // Returns the total number of characters consumed.
16 static int split_suffixes(int N, const char* name, SkTArray<SkString>* out) { 17 static int split_suffixes(int N, const char* name, SkTArray<SkString>* out) {
17 SkTArray<SkString> split; 18 SkTArray<SkString> split;
18 SkStrSplit(name, "_", &split); 19 SkStrSplit(name, "_", &split);
(...skipping 12 matching lines...) Expand all
31 const int totalSuffixLength = split_suffixes(suffixes, name.c_str(), &fSuffi xes); 32 const int totalSuffixLength = split_suffixes(suffixes, name.c_str(), &fSuffi xes);
32 fGmName.set(name.c_str(), name.size()-totalSuffixLength); 33 fGmName.set(name.c_str(), name.size()-totalSuffixLength);
33 } 34 }
34 35
35 void WriteTask::makeDirOrFail(SkString dir) { 36 void WriteTask::makeDirOrFail(SkString dir) {
36 if (!sk_mkdir(dir.c_str())) { 37 if (!sk_mkdir(dir.c_str())) {
37 this->fail(); 38 this->fail();
38 } 39 }
39 } 40 }
40 41
42 namespace {
43
41 // One file that first contains a .png of an SkBitmap, then its raw pixels. 44 // One file that first contains a .png of an SkBitmap, then its raw pixels.
42 // We use this custom format to avoid premultiplied/unpremultiplied pixel conver sions. 45 // We use this custom format to avoid premultiplied/unpremultiplied pixel conver sions.
43 struct PngAndRaw { 46 struct PngAndRaw {
44 static bool Encode(SkBitmap bitmap, const char* path) { 47 static bool Encode(SkBitmap bitmap, const char* path) {
45 SkFILEWStream stream(path); 48 SkFILEWStream stream(path);
46 if (!stream.isValid()) { 49 if (!stream.isValid()) {
47 SkDebugf("Can't write %s.\n", path); 50 SkDebugf("Can't write %s.\n", path);
48 return false; 51 return false;
49 } 52 }
50 53
51 // Write a PNG first for humans and other tools to look at. 54 // Write a PNG first for humans and other tools to look at.
52 if (!SkImageEncoder::EncodeStream(&stream, bitmap, SkImageEncoder::kPNG_ Type, 100)) { 55 if (!SkImageEncoder::EncodeStream(&stream, bitmap, SkImageEncoder::kPNG_ Type, 100)) {
53 SkDebugf("Can't encode a PNG.\n"); 56 SkDebugf("Can't encode a PNG.\n");
54 return false; 57 return false;
55 } 58 }
56 59
60 // Pad out so the raw pixels start 4-byte aligned.
61 const uint32_t maxPadding = 0;
62 const size_t pos = stream.bytesWritten();
63 stream.write(&maxPadding, SkAlign4(pos) - pos);
64
57 // Then write our secret raw pixels that only DM reads. 65 // Then write our secret raw pixels that only DM reads.
58 SkAutoLockPixels lock(bitmap); 66 SkAutoLockPixels lock(bitmap);
59 return stream.write(bitmap.getPixels(), bitmap.getSize()); 67 return stream.write(bitmap.getPixels(), bitmap.getSize());
60 } 68 }
61 69
62 // This assumes bitmap already has allocated pixels of the correct size. 70 // This assumes bitmap already has allocated pixels of the correct size.
63 static bool Decode(const char* path, SkBitmap* bitmap) { 71 static bool Decode(const char* path, SkImageInfo info, SkBitmap* bitmap) {
64 SkAutoTUnref<SkStreamRewindable> stream(SkStream::NewFromFile(path)); 72 SkAutoTUnref<SkData> data(SkData::NewFromFileName(path));
65 if (NULL == stream.get()) { 73 if (!data) {
66 SkDebugf("Can't read %s.\n", path); 74 SkDebugf("Can't read %s.\n", path);
67 return false; 75 return false;
68 } 76 }
69 77
70 // The raw pixels are at the end of the stream. Seek ahead to skip beyo nd the encoded PNG. 78 // The raw pixels are at the end of the file. We'll skip the encoded PN G at the front.
71 const size_t bitmapBytes = bitmap->getSize(); 79 const size_t rowBytes = info.minRowBytes(); // Assume densely packed.
72 if (stream->getLength() < bitmapBytes) { 80 const size_t bitmapBytes = info.getSafeSize(rowBytes);
81 if (data->size() < bitmapBytes) {
73 SkDebugf("%s is too small to contain the bitmap we're looking for.\n ", path); 82 SkDebugf("%s is too small to contain the bitmap we're looking for.\n ", path);
74 return false; 83 return false;
75 } 84 }
76 SkAssertResult(stream->seek(stream->getLength() - bitmapBytes));
77 85
78 // Read the raw pixels. 86 const size_t offset = data->size() - bitmapBytes;
79 // TODO(mtklein): can we install a pixelref that just hangs onto the str eam instead of 87 SkAutoTUnref<SkPixelRef> pixels(
80 // copying into a malloc'd buffer? 88 SkMallocPixelRef::NewWithData(info, rowBytes, NULL/*ctable*/, data, offset));
81 SkAutoLockPixels lock(*bitmap); 89 SkASSERT(pixels);
82 if (bitmapBytes != stream->read(bitmap->getPixels(), bitmapBytes)) {
83 SkDebugf("Couldn't read raw bitmap from %s at %lu of %lu.\n",
84 path, stream->getPosition(), stream->getLength());
85 return false;
86 }
87 90
88 SkASSERT(stream->isAtEnd()); 91 bitmap->setConfig(info, rowBytes);
92 bitmap->setPixelRef(pixels);
89 return true; 93 return true;
90 } 94 }
91 }; 95 };
92 96
97 } // namespace
98
93 void WriteTask::draw() { 99 void WriteTask::draw() {
94 SkString dir(FLAGS_writePath[0]); 100 SkString dir(FLAGS_writePath[0]);
95 this->makeDirOrFail(dir); 101 this->makeDirOrFail(dir);
96 for (int i = 0; i < fSuffixes.count(); i++) { 102 for (int i = 0; i < fSuffixes.count(); i++) {
97 dir = SkOSPath::SkPathJoin(dir.c_str(), fSuffixes[i].c_str()); 103 dir = SkOSPath::SkPathJoin(dir.c_str(), fSuffixes[i].c_str());
98 this->makeDirOrFail(dir); 104 this->makeDirOrFail(dir);
99 } 105 }
100 SkString path = SkOSPath::SkPathJoin(dir.c_str(), fGmName.c_str()); 106 SkString path = SkOSPath::SkPathJoin(dir.c_str(), fGmName.c_str());
101 path.append(".png"); 107 path.append(".png");
102 if (!PngAndRaw::Encode(fBitmap, path.c_str())) { 108 if (!PngAndRaw::Encode(fBitmap, path.c_str())) {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 } 143 }
138 144
139 bool WriteTask::Expectations::check(const Task& task, SkBitmap bitmap) const { 145 bool WriteTask::Expectations::check(const Task& task, SkBitmap bitmap) const {
140 if (!FLAGS_writePath.isEmpty() && 0 == strcmp(FLAGS_writePath[0], fRoot)) { 146 if (!FLAGS_writePath.isEmpty() && 0 == strcmp(FLAGS_writePath[0], fRoot)) {
141 SkDebugf("We seem to be reading and writing %s concurrently. This won't work.\n", fRoot); 147 SkDebugf("We seem to be reading and writing %s concurrently. This won't work.\n", fRoot);
142 return false; 148 return false;
143 } 149 }
144 150
145 const SkString path = path_to_expected_image(fRoot, task); 151 const SkString path = path_to_expected_image(fRoot, task);
146 SkBitmap expected; 152 SkBitmap expected;
147 expected.allocPixels(bitmap.info()); 153 if (!PngAndRaw::Decode(path.c_str(), bitmap.info(), &expected)) {
148 if (!PngAndRaw::Decode(path.c_str(), &expected)) {
149 return false; 154 return false;
150 } 155 }
151 156
152 return BitmapsEqual(expected, bitmap); 157 return BitmapsEqual(expected, bitmap);
153 } 158 }
154 159
155 } // namespace DM 160 } // namespace DM
OLDNEW
« no previous file with comments | « no previous file | include/core/SkStream.h » ('j') | include/core/SkStream.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698