OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "build/build_config.h" | 5 #include "tools/imagediff/image_diff_png.h" |
6 #include "webkit/support/webkit_support_gfx.h" | |
7 | 6 |
8 #include <stdlib.h> | 7 #include <stdlib.h> |
9 #include <string.h> | 8 #include <string.h> |
10 | 9 |
| 10 #include "base/logging.h" |
| 11 #include "build/build_config.h" |
11 #include "third_party/libpng/png.h" | 12 #include "third_party/libpng/png.h" |
12 #include "third_party/zlib/zlib.h" | 13 #include "third_party/zlib/zlib.h" |
13 | 14 |
14 namespace webkit_support { | 15 namespace image_diff_png { |
15 | 16 |
16 // Define macro here to make webkit_support_gfx independent of target base. | 17 // This is a duplicate of ui/gfx/codec/png_codec.cc, after removing code related |
17 // Note that the NOTREACHED() macro will result in a crash. This is preferable | 18 // to Skia, that we can use when running layout tests with minimal dependencies. |
18 // to calling exit() / abort(), since the latter may not surfce the problem as | |
19 // crash reports, making it hard to tell where the problem is. | |
20 #define NOTREACHED(msg) *((volatile int*)0) = 3 | |
21 #define DCHECK(condition) \ | |
22 if (!(condition)) fprintf(stderr, "DCHECK failed: " #condition ".") | |
23 | |
24 // The new webkit_support_gfx, used by DumpRenderTree and ImageDiff, | |
25 // doesn't depend on most other parts of chromium. This could make building | |
26 // the individual target of ImageDiff fast. It's implemented by duplicating | |
27 // most code in ui/gfx/codec/png_codec.cc, after removing code related to | |
28 // Skia. | |
29 namespace { | 19 namespace { |
30 | 20 |
31 enum ColorFormat { | 21 enum ColorFormat { |
32 // 3 bytes per pixel (packed), in RGB order regardless of endianness. | 22 // 3 bytes per pixel (packed), in RGB order regardless of endianness. |
33 // This is the native JPEG format. | 23 // This is the native JPEG format. |
34 FORMAT_RGB, | 24 FORMAT_RGB, |
35 | 25 |
36 // 4 bytes per pixel, in RGBA order in memory regardless of endianness. | 26 // 4 bytes per pixel, in RGBA order in memory regardless of endianness. |
37 FORMAT_RGBA, | 27 FORMAT_RGBA, |
38 | 28 |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
228 break; | 218 break; |
229 case FORMAT_RGBA: | 219 case FORMAT_RGBA: |
230 state->row_converter = &ConvertRGBtoRGBA; | 220 state->row_converter = &ConvertRGBtoRGBA; |
231 state->output_channels = 4; | 221 state->output_channels = 4; |
232 break; | 222 break; |
233 case FORMAT_BGRA: | 223 case FORMAT_BGRA: |
234 state->row_converter = &ConvertRGBtoBGRA; | 224 state->row_converter = &ConvertRGBtoBGRA; |
235 state->output_channels = 4; | 225 state->output_channels = 4; |
236 break; | 226 break; |
237 default: | 227 default: |
238 NOTREACHED("Unknown output format"); | 228 NOTREACHED() << "Unknown output format"; |
239 break; | 229 break; |
240 } | 230 } |
241 } else if (channels == 4) { | 231 } else if (channels == 4) { |
242 switch (state->output_format) { | 232 switch (state->output_format) { |
243 case FORMAT_RGB: | 233 case FORMAT_RGB: |
244 state->row_converter = &ConvertRGBAtoRGB; | 234 state->row_converter = &ConvertRGBAtoRGB; |
245 state->output_channels = 3; | 235 state->output_channels = 3; |
246 break; | 236 break; |
247 case FORMAT_RGBA: | 237 case FORMAT_RGBA: |
248 state->row_converter = NULL; // no conversion necessary | 238 state->row_converter = NULL; // no conversion necessary |
249 state->output_channels = 4; | 239 state->output_channels = 4; |
250 break; | 240 break; |
251 case FORMAT_BGRA: | 241 case FORMAT_BGRA: |
252 state->row_converter = &ConvertBetweenBGRAandRGBA; | 242 state->row_converter = &ConvertBetweenBGRAandRGBA; |
253 state->output_channels = 4; | 243 state->output_channels = 4; |
254 break; | 244 break; |
255 default: | 245 default: |
256 NOTREACHED("Unknown output format"); | 246 NOTREACHED() << "Unknown output format"; |
257 break; | 247 break; |
258 } | 248 } |
259 } else { | 249 } else { |
260 NOTREACHED("Unknown input channels"); | 250 NOTREACHED() << "Unknown input channels"; |
261 longjmp(png_jmpbuf(png_ptr), 1); | 251 longjmp(png_jmpbuf(png_ptr), 1); |
262 } | 252 } |
263 | 253 |
264 state->output->resize( | 254 state->output->resize( |
265 state->width * state->output_channels * state->height); | 255 state->width * state->output_channels * state->height); |
266 } | 256 } |
267 | 257 |
268 void DecodeRowCallback(png_struct* png_ptr, png_byte* new_row, | 258 void DecodeRowCallback(png_struct* png_ptr, png_byte* new_row, |
269 png_uint_32 row_num, int pass) { | 259 png_uint_32 row_num, int pass) { |
270 PngDecoderState* state = static_cast<PngDecoderState*>( | 260 PngDecoderState* state = static_cast<PngDecoderState*>( |
271 png_get_progressive_ptr(png_ptr)); | 261 png_get_progressive_ptr(png_ptr)); |
272 | 262 |
273 DCHECK(pass == 0); | 263 DCHECK(pass == 0); |
274 if (static_cast<int>(row_num) > state->height) { | 264 if (static_cast<int>(row_num) > state->height) { |
275 NOTREACHED("Invalid row"); | 265 NOTREACHED() << "Invalid row"; |
276 return; | 266 return; |
277 } | 267 } |
278 | 268 |
279 unsigned char* base = NULL; | 269 unsigned char* base = NULL; |
280 base = &state->output->front(); | 270 base = &state->output->front(); |
281 | 271 |
282 unsigned char* dest = &base[state->width * state->output_channels * row_num]; | 272 unsigned char* dest = &base[state->width * state->output_channels * row_num]; |
283 if (state->row_converter) | 273 if (state->row_converter) |
284 state->row_converter(new_row, state->width, dest, &state->is_opaque); | 274 state->row_converter(new_row, state->width, dest, &state->is_opaque); |
285 else | 275 else |
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
580 png_output_color_type = PNG_COLOR_TYPE_RGB; | 570 png_output_color_type = PNG_COLOR_TYPE_RGB; |
581 converter = ConvertBGRAtoRGB; | 571 converter = ConvertBGRAtoRGB; |
582 } else { | 572 } else { |
583 output_color_components = 4; | 573 output_color_components = 4; |
584 png_output_color_type = PNG_COLOR_TYPE_RGB_ALPHA; | 574 png_output_color_type = PNG_COLOR_TYPE_RGB_ALPHA; |
585 converter = ConvertBetweenBGRAandRGBA; | 575 converter = ConvertBetweenBGRAandRGBA; |
586 } | 576 } |
587 break; | 577 break; |
588 | 578 |
589 default: | 579 default: |
590 NOTREACHED("Unknown pixel format"); | 580 NOTREACHED() << "Unknown pixel format"; |
591 return false; | 581 return false; |
592 } | 582 } |
593 | 583 |
594 // Row stride should be at least as long as the length of the data. | 584 // Row stride should be at least as long as the length of the data. |
595 DCHECK(input_color_components * width <= row_byte_width); | 585 DCHECK(input_color_components * width <= row_byte_width); |
596 | 586 |
597 png_struct* png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, | 587 png_struct* png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, |
598 NULL, NULL, NULL); | 588 NULL, NULL, NULL); |
599 if (!png_ptr) | 589 if (!png_ptr) |
600 return false; | 590 return false; |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
650 int width, | 640 int width, |
651 int height, | 641 int height, |
652 int row_byte_width, | 642 int row_byte_width, |
653 bool discard_transparency, | 643 bool discard_transparency, |
654 std::vector<unsigned char>* output) { | 644 std::vector<unsigned char>* output) { |
655 return Encode(input, FORMAT_BGRA, | 645 return Encode(input, FORMAT_BGRA, |
656 width, height, row_byte_width, discard_transparency, | 646 width, height, row_byte_width, discard_transparency, |
657 std::vector<Comment>(), output); | 647 std::vector<Comment>(), output); |
658 } | 648 } |
659 | 649 |
660 bool EncodeBGRAPNGWithChecksum(const unsigned char* input, | 650 } // image_diff_png |
661 int width, | |
662 int height, | |
663 int row_byte_width, | |
664 bool discard_transparency, | |
665 const std::string& checksum, | |
666 std::vector<unsigned char>* output) { | |
667 std::vector<Comment> comments; | |
668 comments.push_back(Comment("checksum", checksum)); | |
669 return Encode(input, FORMAT_BGRA, | |
670 width, height, row_byte_width, discard_transparency, | |
671 comments, output); | |
672 } | |
673 | |
674 } // namespace webkit_support | |
OLD | NEW |