OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "gm_expectations.h" | 8 #include "gm_expectations.h" |
9 #include "SkBitmap.h" | 9 #include "SkBitmap.h" |
10 #include "SkBitmapHasher.h" | 10 #include "SkBitmapHasher.h" |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
63 | 63 |
64 static SkImageDecoder::Format guess_format_from_suffix(const char suffix[]) { | 64 static SkImageDecoder::Format guess_format_from_suffix(const char suffix[]) { |
65 for (size_t i = 0; i < SK_ARRAY_COUNT(gFormats); i++) { | 65 for (size_t i = 0; i < SK_ARRAY_COUNT(gFormats); i++) { |
66 if (strcmp(suffix, gFormats[i].fSuffix) == 0) { | 66 if (strcmp(suffix, gFormats[i].fSuffix) == 0) { |
67 return gFormats[i].fFormat; | 67 return gFormats[i].fFormat; |
68 } | 68 } |
69 } | 69 } |
70 return SkImageDecoder::kUnknown_Format; | 70 return SkImageDecoder::kUnknown_Format; |
71 } | 71 } |
72 | 72 |
| 73 /** |
| 74 * Return the name of the file, ignoring the directory structure. |
| 75 * Does not create a new string. |
| 76 * @param fullPath Full path to the file. |
| 77 * @return string The basename of the file - anything beyond the final slash, o
r the full name |
| 78 * if there is no slash. |
| 79 * TODO: Might this be useful as a utility function in SkOSFile? Would it be mo
re appropriate to |
| 80 * create a new string? |
| 81 */ |
| 82 static const char* SkBasename(const char* fullPath) { |
| 83 const char* filename = strrchr(fullPath, SkPATH_SEPARATOR); |
| 84 if (NULL == filename || *++filename == '\0') { |
| 85 filename = fullPath; |
| 86 } |
| 87 return filename; |
| 88 } |
| 89 |
73 static void make_outname(SkString* dst, const char outDir[], const char src[], | 90 static void make_outname(SkString* dst, const char outDir[], const char src[], |
74 const char suffix[]) { | 91 const char suffix[]) { |
75 dst->set(outDir); | 92 const char* basename = SkBasename(src); |
76 const char* start = strrchr(src, '/'); | 93 dst->set(skiagm::SkPathJoin(outDir, basename)); |
77 if (start) { | |
78 start += 1; // skip the actual last '/' | |
79 } else { | |
80 start = src; | |
81 } | |
82 dst->append(start); | |
83 if (!dst->endsWith(suffix)) { | 94 if (!dst->endsWith(suffix)) { |
84 const char* cstyleDst = dst->c_str(); | 95 const char* cstyleDst = dst->c_str(); |
85 const char* dot = strrchr(cstyleDst, '.'); | 96 const char* dot = strrchr(cstyleDst, '.'); |
86 if (dot != NULL) { | 97 if (dot != NULL) { |
87 int32_t index = SkToS32(dot - cstyleDst); | 98 int32_t index = SkToS32(dot - cstyleDst); |
88 dst->remove(index, dst->size() - index); | 99 dst->remove(index, dst->size() - index); |
89 } | 100 } |
90 dst->append(suffix); | 101 dst->append(suffix); |
91 } | 102 } |
92 } | 103 } |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
175 static void write_expectations(const SkBitmap& bitmap, const char* filename) { | 186 static void write_expectations(const SkBitmap& bitmap, const char* filename) { |
176 if (!FLAGS_createExpectationsPath.isEmpty()) { | 187 if (!FLAGS_createExpectationsPath.isEmpty()) { |
177 // Creates an Expectations object, and add it to the list to write. | 188 // Creates an Expectations object, and add it to the list to write. |
178 skiagm::Expectations expectation(bitmap); | 189 skiagm::Expectations expectation(bitmap); |
179 Json::Value value = expectation.asJsonValue(); | 190 Json::Value value = expectation.asJsonValue(); |
180 gExpectationsToWrite[filename] = value; | 191 gExpectationsToWrite[filename] = value; |
181 } | 192 } |
182 } | 193 } |
183 | 194 |
184 /** | 195 /** |
185 * Return the name of the file, ignoring the directory structure. | |
186 * Does not create a new string. | |
187 * @param fullPath Full path to the file. | |
188 * @return string The basename of the file - anything beyond the final slash, o
r the full name | |
189 * if there is no slash. | |
190 * TODO: Might this be useful as a utility function in SkOSFile? Would it be mo
re appropriate to | |
191 * create a new string? | |
192 */ | |
193 static const char* SkBasename(const char* fullPath) { | |
194 const char* filename = strrchr(fullPath, SkPATH_SEPARATOR); | |
195 if (NULL == filename || ++filename == '\0') { | |
196 filename = fullPath; | |
197 } | |
198 return filename; | |
199 } | |
200 | |
201 /** | |
202 * Compare against an expectation for this filename, if there is one. | 196 * Compare against an expectation for this filename, if there is one. |
203 * @param bitmap SkBitmap to compare to the expected value. | 197 * @param bitmap SkBitmap to compare to the expected value. |
204 * @param filename String used to find the expected value. | 198 * @param filename String used to find the expected value. |
205 * @return bool True in any of these cases: | 199 * @return bool True in any of these cases: |
206 * - the bitmap matches the expectation. | 200 * - the bitmap matches the expectation. |
207 * - there is no expectations file. | 201 * - there is no expectations file. |
208 * False in any of these cases: | 202 * False in any of these cases: |
209 * - there is an expectations file, but no expectation for this
bitmap. | 203 * - there is an expectations file, but no expectation for this
bitmap. |
210 * - there is an expectation for this bitmap, but it did not ma
tch. | 204 * - there is an expectation for this bitmap, but it did not ma
tch. |
211 * - expectation could not be computed from the bitmap. | 205 * - expectation could not be computed from the bitmap. |
(...skipping 27 matching lines...) Expand all Loading... |
239 } | 233 } |
240 | 234 |
241 if (failureArray != NULL) { | 235 if (failureArray != NULL) { |
242 failureArray->push_back().printf("decoded %s, but the result does not ma
tch " | 236 failureArray->push_back().printf("decoded %s, but the result does not ma
tch " |
243 "expectations.", | 237 "expectations.", |
244 filename); | 238 filename); |
245 } | 239 } |
246 return false; | 240 return false; |
247 } | 241 } |
248 | 242 |
| 243 /** |
| 244 * Helper function to write a bitmap subset to a file. Only called if subsets w
ere created |
| 245 * and a writePath was provided. Creates a subdirectory called 'subsets' and wr
ites a PNG to |
| 246 * that directory. Also creates a subdirectory called 'extracted' and writes a
bitmap created |
| 247 * using extractSubset to a PNG in that directory. Both files will represent th
e same |
| 248 * subrectangle and have the same name for comparison. |
| 249 * @param writePath Parent directory to hold the folders for the PNG files to w
rite. Must |
| 250 * not be NULL. |
| 251 * @param filename Basename of the original file. Used to name the new files. M
ust not be |
| 252 * NULL. |
| 253 * @param subsetDim String representing the dimensions of the subset. Used to n
ame the new |
| 254 * files. Must not be NULL. |
| 255 * @param bitmapFromDecodeSubset Pointer to SkBitmap created by SkImageDecoder:
:DecodeSubset, |
| 256 * using rect as the area to decode. |
| 257 * @param rect Rectangle of the area decoded into bitmapFromDecodeSubset. Used
to call |
| 258 * extractSubset on originalBitmap to create a bitmap with the same dimensi
ons/pixels as |
| 259 * bitmapFromDecodeSubset (assuming decodeSubset worked properly). |
| 260 * @param originalBitmap SkBitmap decoded from the same stream as bitmapFromDec
odeSubset, |
| 261 * using SkImageDecoder::decode to get the entire image. Used to create a P
NG file for |
| 262 * comparison to the PNG created by bitmapFromDecodeSubset. |
| 263 * @return bool Whether the function succeeded at drawing the decoded subset an
d the extracted |
| 264 * subset to files. |
| 265 */ |
| 266 static bool write_subset(const char* writePath, const char* filename, const char
* subsetDim, |
| 267 SkBitmap* bitmapFromDecodeSubset, SkIRect rect, |
| 268 const SkBitmap& originalBitmap) { |
| 269 // All parameters must be valid. |
| 270 SkASSERT(writePath != NULL); |
| 271 SkASSERT(filename != NULL); |
| 272 SkASSERT(subsetDim != NULL); |
| 273 SkASSERT(bitmapFromDecodeSubset != NULL); |
| 274 |
| 275 // Create a subdirectory to hold the results of decodeSubset. |
| 276 // TODO: Move SkPathJoin into SkOSFile.h |
| 277 SkString dir = skiagm::SkPathJoin(writePath, "subsets"); |
| 278 if (!sk_mkdir(dir.c_str())) { |
| 279 gFailedSubsetDecodes.push_back().printf("Successfully decoded %s from %s
, but failed to " |
| 280 "create a directory to write to.
", subsetDim, |
| 281 filename); |
| 282 return false; |
| 283 } |
| 284 |
| 285 // Write the subset to a file whose name includes the dimensions. |
| 286 SkString suffix = SkStringPrintf("_%s.png", subsetDim); |
| 287 SkString outPath; |
| 288 make_outname(&outPath, dir.c_str(), filename, suffix.c_str()); |
| 289 SkAssertResult(write_bitmap(outPath.c_str(), bitmapFromDecodeSubset)); |
| 290 gSuccessfulSubsetDecodes.push_back().printf("\twrote %s", outPath.c_str()); |
| 291 |
| 292 // Also use extractSubset from the original for visual comparison. |
| 293 // Write the result to a file in a separate subdirectory. |
| 294 SkBitmap extractedSubset; |
| 295 if (!originalBitmap.extractSubset(&extractedSubset, rect)) { |
| 296 gFailedSubsetDecodes.push_back().printf("Successfully decoded %s from %s
, but failed to " |
| 297 "extract a similar subset for co
mparison.", |
| 298 subsetDim, filename); |
| 299 return false; |
| 300 } |
| 301 |
| 302 SkString dirExtracted = skiagm::SkPathJoin(writePath, "extracted"); |
| 303 if (!sk_mkdir(dirExtracted.c_str())) { |
| 304 gFailedSubsetDecodes.push_back().printf("Successfully decoded %s from %s
, but failed to " |
| 305 "create a directory for extractS
ubset comparison.", |
| 306 subsetDim, filename); |
| 307 return false; |
| 308 } |
| 309 |
| 310 make_outname(&outPath, dirExtracted.c_str(), filename, suffix.c_str()); |
| 311 SkAssertResult(write_bitmap(outPath.c_str(), &extractedSubset)); |
| 312 return true; |
| 313 } |
| 314 |
249 static void decodeFileAndWrite(const char srcPath[], const SkString* writePath)
{ | 315 static void decodeFileAndWrite(const char srcPath[], const SkString* writePath)
{ |
250 SkBitmap bitmap; | 316 SkBitmap bitmap; |
251 SkFILEStream stream(srcPath); | 317 SkFILEStream stream(srcPath); |
252 if (!stream.isValid()) { | 318 if (!stream.isValid()) { |
253 gInvalidStreams.push_back().set(srcPath); | 319 gInvalidStreams.push_back().set(srcPath); |
254 return; | 320 return; |
255 } | 321 } |
256 | 322 |
257 SkImageDecoder* codec = SkImageDecoder::Factory(&stream); | 323 SkImageDecoder* codec = SkImageDecoder::Factory(&stream); |
258 if (NULL == codec) { | 324 if (NULL == codec) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
298 if (codec->decodeSubset(&bitmapFromDecodeSubset, rect, SkBitmap:
:kNo_Config)) { | 364 if (codec->decodeSubset(&bitmapFromDecodeSubset, rect, SkBitmap:
:kNo_Config)) { |
299 SkString subsetName = SkStringPrintf("%s_%s", filename, subs
etDim.c_str()); | 365 SkString subsetName = SkStringPrintf("%s_%s", filename, subs
etDim.c_str()); |
300 if (compare_to_expectations_if_necessary(bitmapFromDecodeSub
set, | 366 if (compare_to_expectations_if_necessary(bitmapFromDecodeSub
set, |
301 subsetName.c_str(), | 367 subsetName.c_str(), |
302 &gFailedSubsetDecod
es)) { | 368 &gFailedSubsetDecod
es)) { |
303 gSuccessfulSubsetDecodes.push_back().printf("Decoded sub
set %s from %s", | 369 gSuccessfulSubsetDecodes.push_back().printf("Decoded sub
set %s from %s", |
304 subsetDim.c_str(),
srcPath); | 370 subsetDim.c_str(),
srcPath); |
305 } | 371 } |
306 | 372 |
307 write_expectations(bitmapFromDecodeSubset, subsetName.c_str(
)); | 373 write_expectations(bitmapFromDecodeSubset, subsetName.c_str(
)); |
308 | |
309 if (writePath != NULL) { | 374 if (writePath != NULL) { |
310 // Write the region to a file whose name includes the di
mensions. | 375 write_subset(writePath->c_str(), filename, subsetDim.c_s
tr(), |
311 SkString suffix = SkStringPrintf("_%s.png", subsetDim.c_
str()); | 376 &bitmapFromDecodeSubset, rect, bitmap); |
312 SkString outPath; | |
313 make_outname(&outPath, writePath->c_str(), srcPath, suff
ix.c_str()); | |
314 SkDEBUGCODE(bool success =) | |
315 write_bitmap(outPath.c_str(), &bitmapFromDecodeSubset); | |
316 SkASSERT(success); | |
317 gSuccessfulSubsetDecodes.push_back().printf("\twrote %s"
, outPath.c_str()); | |
318 // Also use extractSubset from the original for visual c
omparison. | |
319 SkBitmap extractedSubset; | |
320 if (bitmap.extractSubset(&extractedSubset, rect)) { | |
321 suffix.printf("_%s_extracted.png", subsetDim.c_str()
); | |
322 make_outname(&outPath, writePath->c_str(), srcPath,
suffix.c_str()); | |
323 SkDEBUGCODE(success =) write_bitmap(outPath.c_str(),
&extractedSubset); | |
324 SkASSERT(success); | |
325 } | |
326 } | 377 } |
327 } else { | 378 } else { |
328 gFailedSubsetDecodes.push_back().printf("Failed to decode re
gion %s from %s\n", | 379 gFailedSubsetDecodes.push_back().printf("Failed to decode re
gion %s from %s", |
329 subsetDim.c_str(), s
rcPath); | 380 subsetDim.c_str(), s
rcPath); |
330 } | 381 } |
331 } | 382 } |
332 } | 383 } |
333 } | 384 } |
| 385 |
334 if (FLAGS_reencode) { | 386 if (FLAGS_reencode) { |
335 // Encode to the format the file was originally in, or PNG if the encode
r for the same | 387 // Encode to the format the file was originally in, or PNG if the encode
r for the same |
336 // format is unavailable. | 388 // format is unavailable. |
337 SkImageDecoder::Format format = codec->getFormat(); | 389 SkImageDecoder::Format format = codec->getFormat(); |
338 if (SkImageDecoder::kUnknown_Format == format) { | 390 if (SkImageDecoder::kUnknown_Format == format) { |
339 if (stream.rewind()) { | 391 if (stream.rewind()) { |
340 format = SkImageDecoder::GetStreamFormat(&stream); | 392 format = SkImageDecoder::GetStreamFormat(&stream); |
341 } | 393 } |
342 if (SkImageDecoder::kUnknown_Format == format) { | 394 if (SkImageDecoder::kUnknown_Format == format) { |
343 const char* dot = strrchr(srcPath, '.'); | 395 const char* dot = strrchr(srcPath, '.'); |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
513 } | 565 } |
514 | 566 |
515 return failed ? -1 : 0; | 567 return failed ? -1 : 0; |
516 } | 568 } |
517 | 569 |
518 #if !defined SK_BUILD_FOR_IOS | 570 #if !defined SK_BUILD_FOR_IOS |
519 int main(int argc, char * const argv[]) { | 571 int main(int argc, char * const argv[]) { |
520 return tool_main(argc, (char**) argv); | 572 return tool_main(argc, (char**) argv); |
521 } | 573 } |
522 #endif | 574 #endif |
OLD | NEW |