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

Side by Side Diff: ui/gfx/codec/png_codec.cc

Issue 136453009: Fix for Issue 331895: Make gesturenav screenshot greyscale (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 11 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
« ui/gfx/codec/png_codec.h ('K') | « ui/gfx/codec/png_codec.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "ui/gfx/codec/png_codec.h" 5 #include "ui/gfx/codec/png_codec.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/strings/string_util.h" 8 #include "base/strings/string_util.h"
9 #include "third_party/libpng/png.h" 9 #include "third_party/libpng/png.h"
10 #include "third_party/skia/include/core/SkBitmap.h" 10 #include "third_party/skia/include/core/SkBitmap.h"
11 #include "third_party/skia/include/core/SkColorPriv.h" 11 #include "third_party/skia/include/core/SkColorPriv.h"
12 #include "third_party/skia/include/core/SkUnPreMultiply.h" 12 #include "third_party/skia/include/core/SkUnPreMultiply.h"
13 #include "third_party/zlib/zlib.h" 13 #include "third_party/zlib/zlib.h"
14 #include "ui/gfx/size.h" 14 #include "ui/gfx/size.h"
15 #include "ui/gfx/skia_util.h" 15 #include "ui/gfx/skia_util.h"
16 16
17 namespace gfx { 17 namespace gfx {
18 18
19 namespace { 19 namespace {
20 20
21 // Transform coefficients (expressed in 16.16 fixed-point numbers)
22 // for RGB into grayscale.
23 // Same coefficients as used in png_do_rgb_to_gray() in pngtran.c in libpng
24 static const uint32_t RED_TO_GRAY_COEF = 6969; // .212671 * 32768
sadrul 2014/01/15 21:43:06 two spaces before EOL // comments
25 static const uint32_t GREEN_TO_GRAY_COEF = 23434; // .715160 * 32768
26 static const uint32_t BLUE_TO_GRAY_COEF = 32768 - RED_TO_GRAY_COEF -
27 GREEN_TO_GRAY_COEF;
28
29 static inline unsigned char PixelRgbtoGray(unsigned char r, unsigned char b,
30 unsigned char g) {
31 return (RED_TO_GRAY_COEF * r + GREEN_TO_GRAY_COEF * g +
32 BLUE_TO_GRAY_COEF * b) >> 15;
33 }
34
35
21 // Converts BGRA->RGBA and RGBA->BGRA. 36 // Converts BGRA->RGBA and RGBA->BGRA.
22 void ConvertBetweenBGRAandRGBA(const unsigned char* input, int pixel_width, 37 void ConvertBetweenBGRAandRGBA(const unsigned char* input, int pixel_width,
23 unsigned char* output, bool* is_opaque) { 38 unsigned char* output, bool* is_opaque) {
24 for (int x = 0; x < pixel_width; x++) { 39 for (int x = 0; x < pixel_width; x++) {
25 const unsigned char* pixel_in = &input[x * 4]; 40 const unsigned char* pixel_in = &input[x * 4];
26 unsigned char* pixel_out = &output[x * 4]; 41 unsigned char* pixel_out = &output[x * 4];
27 pixel_out[0] = pixel_in[2]; 42 pixel_out[0] = pixel_in[2];
28 pixel_out[1] = pixel_in[1]; 43 pixel_out[1] = pixel_in[1];
29 pixel_out[2] = pixel_in[0]; 44 pixel_out[2] = pixel_in[0];
30 pixel_out[3] = pixel_in[3]; 45 pixel_out[3] = pixel_in[3];
31 } 46 }
32 } 47 }
33 48
49 void ConvertBGRAtoGray(const unsigned char* bgra, int pixel_width,
50 unsigned char* gray, bool* is_opaque) {
51 for (int x = 0; x < pixel_width; x++) {
52 const unsigned char* pixel_in = &bgra[x * 4];
53 gray[x] = PixelRgbtoGray(pixel_in[2], pixel_in[1], pixel_in[0]);
54 }
55 }
56
57 void ConvertBGRAtoGrayAlpha(const unsigned char* bgra, int pixel_width,
58 unsigned char* grayalpha, bool* is_opaque) {
59 for (int x = 0; x < pixel_width; x++) {
60 const unsigned char* pixel_in = &bgra[x * 4];
61 unsigned char* pixel_out = &grayalpha[x * 2];
62 pixel_out[0] = PixelRgbtoGray(pixel_in[2], pixel_in[1], pixel_in[0]);
63 pixel_out[1] = pixel_in[3]; // alpha
64 }
65 }
66
67 void ConvertRGBtoGray(const unsigned char* rgb, int pixel_width,
68 unsigned char* gray, bool* is_opaque) {
69 for (int x = 0; x < pixel_width; x++) {
70 const unsigned char* pixel_in = &rgb[x * 3];
71 gray[x] = PixelRgbtoGray(pixel_in[0], pixel_in[1], pixel_in[2]);
72 }
73 }
74
34 void ConvertRGBAtoRGB(const unsigned char* rgba, int pixel_width, 75 void ConvertRGBAtoRGB(const unsigned char* rgba, int pixel_width,
35 unsigned char* rgb, bool* is_opaque) { 76 unsigned char* rgb, bool* is_opaque) {
36 for (int x = 0; x < pixel_width; x++) { 77 for (int x = 0; x < pixel_width; x++) {
37 const unsigned char* pixel_in = &rgba[x * 4]; 78 const unsigned char* pixel_in = &rgba[x * 4];
38 unsigned char* pixel_out = &rgb[x * 3]; 79 unsigned char* pixel_out = &rgb[x * 3];
39 pixel_out[0] = pixel_in[0]; 80 pixel_out[0] = pixel_in[0];
40 pixel_out[1] = pixel_in[1]; 81 pixel_out[1] = pixel_in[1];
41 pixel_out[2] = pixel_in[2]; 82 pixel_out[2] = pixel_in[2];
42 } 83 }
43 } 84 }
44 85
86 void ConvertRGBAtoGray(const unsigned char* rgba, int pixel_width,
87 unsigned char* gray, bool* is_opaque) {
88 for (int x = 0; x < pixel_width; x++) {
89 const unsigned char* pixel_in = &rgba[x * 4];
90 gray[x] = PixelRgbtoGray(pixel_in[0], pixel_in[1], pixel_in[2]);
91 }
92 }
93
94 void ConvertRGBAtoGrayAlpha(const unsigned char* rgba, int pixel_width,
95 unsigned char* grayalpha, bool* is_opaque) {
96 for (int x = 0; x < pixel_width; x++) {
97 const unsigned char* pixel_in = &rgba[x * 4];
98 unsigned char* pixel_out = &grayalpha[x * 2];
99 pixel_out[0] = PixelRgbtoGray(pixel_in[0], pixel_in[1], pixel_in[2]);
100 pixel_out[1] = pixel_in[3]; // alpha
101 }
102 }
103
104
45 void ConvertSkiatoRGB(const unsigned char* skia, int pixel_width, 105 void ConvertSkiatoRGB(const unsigned char* skia, int pixel_width,
46 unsigned char* rgb, bool* is_opaque) { 106 unsigned char* rgb, bool* is_opaque) {
47 for (int x = 0; x < pixel_width; x++) { 107 for (int x = 0; x < pixel_width; x++) {
48 const uint32_t pixel_in = *reinterpret_cast<const uint32_t*>(&skia[x * 4]); 108 const uint32_t pixel_in = *reinterpret_cast<const uint32_t*>(&skia[x * 4]);
49 unsigned char* pixel_out = &rgb[x * 3]; 109 unsigned char* pixel_out = &rgb[x * 3];
50 110
51 int alpha = SkGetPackedA32(pixel_in); 111 int alpha = SkGetPackedA32(pixel_in);
52 if (alpha != 0 && alpha != 255) { 112 if (alpha != 0 && alpha != 255) {
53 SkColor unmultiplied = SkUnPreMultiply::PMColorToColor(pixel_in); 113 SkColor unmultiplied = SkUnPreMultiply::PMColorToColor(pixel_in);
54 pixel_out[0] = SkColorGetR(unmultiplied); 114 pixel_out[0] = SkColorGetR(unmultiplied);
55 pixel_out[1] = SkColorGetG(unmultiplied); 115 pixel_out[1] = SkColorGetG(unmultiplied);
56 pixel_out[2] = SkColorGetB(unmultiplied); 116 pixel_out[2] = SkColorGetB(unmultiplied);
57 } else { 117 } else {
58 pixel_out[0] = SkGetPackedR32(pixel_in); 118 pixel_out[0] = SkGetPackedR32(pixel_in);
59 pixel_out[1] = SkGetPackedG32(pixel_in); 119 pixel_out[1] = SkGetPackedG32(pixel_in);
60 pixel_out[2] = SkGetPackedB32(pixel_in); 120 pixel_out[2] = SkGetPackedB32(pixel_in);
61 } 121 }
62 } 122 }
63 } 123 }
64 124
65 void ConvertSkiatoRGBA(const unsigned char* skia, int pixel_width, 125 void ConvertSkiatoRGBA(const unsigned char* skia, int pixel_width,
66 unsigned char* rgba, bool* is_opaque) { 126 unsigned char* rgba, bool* is_opaque) {
67 gfx::ConvertSkiaToRGBA(skia, pixel_width, rgba); 127 gfx::ConvertSkiaToRGBA(skia, pixel_width, rgba);
68 } 128 }
69 129
130 void ConvertSkiatoGray(const unsigned char* skia, int pixel_width,
131 unsigned char* gray, bool* is_opaque) {
132 for (int x = 0; x < pixel_width; x++) {
133 const uint32_t pixel_in = *reinterpret_cast<const uint32_t*>(&skia[x * 4]);
134 unsigned char* pixel_out = &gray[x];
135
136 int alpha = SkGetPackedA32(pixel_in);
137 if (alpha != 0 && alpha != 255) {
138 SkColor unmultiplied = SkUnPreMultiply::PMColorToColor(pixel_in);
139 pixel_out[0] = PixelRgbtoGray(SkColorGetR(unmultiplied),
140 SkColorGetG(unmultiplied),
141 SkColorGetB(unmultiplied));
142 } else {
143 pixel_out[0] = PixelRgbtoGray(SkGetPackedR32(pixel_in),
144 SkGetPackedG32(pixel_in),
145 SkGetPackedB32(pixel_in));
146 }
147 }
148 }
149
150 void ConvertSkiatoGrayAlpha(const unsigned char* skia, int pixel_width,
151 unsigned char* grayalpha, bool* is_opaque) {
152 for (int x = 0; x < pixel_width; x++) {
153 const uint32_t pixel_in = *reinterpret_cast<const uint32_t*>(&skia[x * 4]);
154 unsigned char* pixel_out = &grayalpha[x * 2];
155
156 int alpha = SkGetPackedA32(pixel_in);
157 if (alpha != 0 && alpha != 255) {
158 SkColor unmultiplied = SkUnPreMultiply::PMColorToColor(pixel_in);
159 pixel_out[0] = PixelRgbtoGray(SkColorGetR(unmultiplied),
160 SkColorGetG(unmultiplied),
161 SkColorGetB(unmultiplied));
162 } else {
163 pixel_out[0] = PixelRgbtoGray(SkGetPackedR32(pixel_in),
164 SkGetPackedG32(pixel_in),
165 SkGetPackedB32(pixel_in));
166 }
167 pixel_out[1] = alpha;
168 }
169 }
170
171
70 } // namespace 172 } // namespace
71 173
72 // Decoder -------------------------------------------------------------------- 174 // Decoder --------------------------------------------------------------------
73 // 175 //
74 // This code is based on WebKit libpng interface (PNGImageDecoder), which is 176 // This code is based on WebKit libpng interface (PNGImageDecoder), which is
75 // in turn based on the Mozilla png decoder. 177 // in turn based on the Mozilla png decoder.
76 178
77 namespace { 179 namespace {
78 180
79 // Gamma constants: We assume we're on Windows which uses a gamma of 2.2. 181 // Gamma constants: We assume we're on Windows which uses a gamma of 2.2.
(...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after
628 730
629 png_write_end(png_ptr, info_ptr); 731 png_write_end(png_ptr, info_ptr);
630 return true; 732 return true;
631 } 733 }
632 734
633 bool EncodeWithCompressionLevel(const unsigned char* input, 735 bool EncodeWithCompressionLevel(const unsigned char* input,
634 PNGCodec::ColorFormat format, 736 PNGCodec::ColorFormat format,
635 const Size& size, 737 const Size& size,
636 int row_byte_width, 738 int row_byte_width,
637 bool discard_transparency, 739 bool discard_transparency,
740 bool discard_color,
638 const std::vector<PNGCodec::Comment>& comments, 741 const std::vector<PNGCodec::Comment>& comments,
639 int compression_level, 742 int compression_level,
640 std::vector<unsigned char>* output) { 743 std::vector<unsigned char>* output) {
641 // Run to convert an input row into the output row format, NULL means no 744 // Run to convert an input row into the output row format, NULL means no
642 // conversion is necessary. 745 // conversion is necessary.
643 FormatConverter converter = NULL; 746 FormatConverter converter = NULL;
644 747
645 int input_color_components, output_color_components; 748 int input_color_components, output_color_components;
646 int png_output_color_type; 749 int png_output_color_type;
647 switch (format) { 750 switch (format) {
648 case PNGCodec::FORMAT_RGB: 751 case PNGCodec::FORMAT_RGB:
649 input_color_components = 3; 752 input_color_components = 3;
650 output_color_components = 3; 753 if (discard_color) {
651 png_output_color_type = PNG_COLOR_TYPE_RGB; 754 output_color_components = 1;
755 png_output_color_type = PNG_COLOR_TYPE_GRAY;
756 converter = ConvertRGBtoGray;
757 } else {
758 output_color_components = 3;
759 png_output_color_type = PNG_COLOR_TYPE_RGB;
760 converter = NULL;
761 }
652 break; 762 break;
653 763
654 case PNGCodec::FORMAT_RGBA: 764 case PNGCodec::FORMAT_RGBA:
655 input_color_components = 4; 765 input_color_components = 4;
656 if (discard_transparency) { 766 if (discard_transparency) {
657 output_color_components = 3; 767 if (discard_color) {
658 png_output_color_type = PNG_COLOR_TYPE_RGB; 768 output_color_components = 1;
659 converter = ConvertRGBAtoRGB; 769 png_output_color_type = PNG_COLOR_TYPE_GRAY;
770 converter = ConvertRGBAtoGray;
771 } else {
772 output_color_components = 3;
773 png_output_color_type = PNG_COLOR_TYPE_RGB;
774 converter = ConvertRGBAtoRGB;
775 }
660 } else { 776 } else {
661 output_color_components = 4; 777 if (discard_color) {
662 png_output_color_type = PNG_COLOR_TYPE_RGB_ALPHA; 778 output_color_components = 2;
663 converter = NULL; 779 png_output_color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
780 converter = ConvertRGBAtoGrayAlpha;
781 } else {
782 output_color_components = 4;
783 png_output_color_type = PNG_COLOR_TYPE_RGB_ALPHA;
784 converter = NULL;
785 }
664 } 786 }
665 break; 787 break;
666 788
667 case PNGCodec::FORMAT_BGRA: 789 case PNGCodec::FORMAT_BGRA:
668 input_color_components = 4; 790 input_color_components = 4;
669 if (discard_transparency) { 791 if (discard_transparency) {
670 output_color_components = 3; 792 if (discard_color) {
671 png_output_color_type = PNG_COLOR_TYPE_RGB; 793 output_color_components = 1;
672 converter = ConvertBGRAtoRGB; 794 png_output_color_type = PNG_COLOR_TYPE_GRAY;
795 converter = ConvertBGRAtoGray;
796 } else {
797 output_color_components = 3;
798 png_output_color_type = PNG_COLOR_TYPE_RGB;
799 converter = ConvertBGRAtoRGB;
800 }
673 } else { 801 } else {
674 output_color_components = 4; 802 if (discard_color) {
675 png_output_color_type = PNG_COLOR_TYPE_RGB_ALPHA; 803 output_color_components = 2;
676 converter = ConvertBetweenBGRAandRGBA; 804 png_output_color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
805 converter = ConvertBGRAtoGrayAlpha;
806 } else {
807 output_color_components = 4;
808 png_output_color_type = PNG_COLOR_TYPE_RGB_ALPHA;
809 converter = ConvertBetweenBGRAandRGBA;
810 }
677 } 811 }
678 break; 812 break;
679 813
680 case PNGCodec::FORMAT_SkBitmap: 814 case PNGCodec::FORMAT_SkBitmap:
681 input_color_components = 4; 815 input_color_components = 4;
682 if (discard_transparency) { 816 if (discard_transparency) {
683 output_color_components = 3; 817 if (discard_color) {
684 png_output_color_type = PNG_COLOR_TYPE_RGB; 818 output_color_components = 1;
685 converter = ConvertSkiatoRGB; 819 png_output_color_type = PNG_COLOR_TYPE_GRAY;
820 converter = ConvertSkiatoGray;
821 } else {
822 output_color_components = 3;
823 png_output_color_type = PNG_COLOR_TYPE_RGB;
824 converter = ConvertSkiatoRGB;
825 }
686 } else { 826 } else {
687 output_color_components = 4; 827 if (discard_color) {
688 png_output_color_type = PNG_COLOR_TYPE_RGB_ALPHA; 828 output_color_components = 2;
689 converter = ConvertSkiatoRGBA; 829 png_output_color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
830 converter = ConvertSkiatoGrayAlpha;
831 } else {
832 output_color_components = 4;
833 png_output_color_type = PNG_COLOR_TYPE_RGB_ALPHA;
834 converter = ConvertSkiatoRGBA;
835 }
sadrul 2014/01/15 21:43:06 I wonder if this could somehow be simplified, e.g.
690 } 836 }
691 break; 837 break;
692 838
693 default: 839 default:
694 NOTREACHED() << "Unknown pixel format"; 840 NOTREACHED() << "Unknown pixel format";
695 return false; 841 return false;
696 } 842 }
697 843
698 // Row stride should be at least as long as the length of the data. 844 // Row stride should be at least as long as the length of the data.
699 DCHECK(input_color_components * size.width() <= row_byte_width); 845 DCHECK(input_color_components * size.width() <= row_byte_width);
(...skipping 20 matching lines...) Expand all
720 } 866 }
721 867
722 868
723 } // namespace 869 } // namespace
724 870
725 // static 871 // static
726 bool PNGCodec::Encode(const unsigned char* input, ColorFormat format, 872 bool PNGCodec::Encode(const unsigned char* input, ColorFormat format,
727 const Size& size, int row_byte_width, 873 const Size& size, int row_byte_width,
728 bool discard_transparency, 874 bool discard_transparency,
729 const std::vector<Comment>& comments, 875 const std::vector<Comment>& comments,
730 std::vector<unsigned char>* output) { 876 std::vector<unsigned char>* output,
877 bool discard_color) {
731 return EncodeWithCompressionLevel(input, 878 return EncodeWithCompressionLevel(input,
732 format, 879 format,
733 size, 880 size,
734 row_byte_width, 881 row_byte_width,
735 discard_transparency, 882 discard_transparency,
883 discard_color,
736 comments, 884 comments,
737 Z_DEFAULT_COMPRESSION, 885 Z_DEFAULT_COMPRESSION,
738 output); 886 output);
739 } 887 }
740 888
741 // static 889 // static
742 bool PNGCodec::EncodeBGRASkBitmap(const SkBitmap& input, 890 bool PNGCodec::EncodeBGRASkBitmap(const SkBitmap& input,
743 bool discard_transparency, 891 bool discard_transparency,
744 std::vector<unsigned char>* output) { 892 std::vector<unsigned char>* output,
893 bool discard_color) {
745 static const int bbp = 4; 894 static const int bbp = 4;
746 895
747 if (input.empty()) 896 if (input.empty())
748 return false; 897 return false;
749 DCHECK_EQ(input.bytesPerPixel(), bbp); 898 DCHECK_EQ(input.bytesPerPixel(), bbp);
750 DCHECK_GE(static_cast<int>(input.rowBytes()), input.width() * bbp); 899 DCHECK_GE(static_cast<int>(input.rowBytes()), input.width() * bbp);
751 900
752 SkAutoLockPixels lock_input(input); 901 SkAutoLockPixels lock_input(input);
753 return Encode(reinterpret_cast<unsigned char*>(input.getAddr32(0, 0)), 902 return Encode(reinterpret_cast<unsigned char*>(input.getAddr32(0, 0)),
754 FORMAT_SkBitmap, Size(input.width(), input.height()), 903 FORMAT_SkBitmap, Size(input.width(), input.height()),
755 static_cast<int>(input.rowBytes()), discard_transparency, 904 static_cast<int>(input.rowBytes()), discard_transparency,
756 std::vector<Comment>(), output); 905 std::vector<Comment>(), output, discard_color);
757 } 906 }
758 907
759 // static 908 // static
760 bool PNGCodec::FastEncodeBGRASkBitmap(const SkBitmap& input, 909 bool PNGCodec::FastEncodeBGRASkBitmap(const SkBitmap& input,
761 bool discard_transparency, 910 bool discard_transparency,
762 std::vector<unsigned char>* output) { 911 std::vector<unsigned char>* output,
912 bool discard_color) {
763 static const int bbp = 4; 913 static const int bbp = 4;
764 914
765 if (input.empty()) 915 if (input.empty())
766 return false; 916 return false;
767 DCHECK_EQ(input.bytesPerPixel(), bbp); 917 DCHECK_EQ(input.bytesPerPixel(), bbp);
768 DCHECK_GE(static_cast<int>(input.rowBytes()), input.width() * bbp); 918 DCHECK_GE(static_cast<int>(input.rowBytes()), input.width() * bbp);
769 919
770 SkAutoLockPixels lock_input(input); 920 SkAutoLockPixels lock_input(input);
771 return EncodeWithCompressionLevel( 921 return EncodeWithCompressionLevel(
772 reinterpret_cast<unsigned char*>(input.getAddr32(0, 0)), 922 reinterpret_cast<unsigned char*>(input.getAddr32(0, 0)),
773 FORMAT_SkBitmap, Size(input.width(), input.height()), 923 FORMAT_SkBitmap, Size(input.width(), input.height()),
774 static_cast<int>(input.rowBytes()), discard_transparency, 924 static_cast<int>(input.rowBytes()), discard_transparency,
775 std::vector<Comment>(), Z_BEST_SPEED, output); 925 discard_color, std::vector<Comment>(), Z_BEST_SPEED, output);
776 } 926 }
777 927
778 PNGCodec::Comment::Comment(const std::string& k, const std::string& t) 928 PNGCodec::Comment::Comment(const std::string& k, const std::string& t)
779 : key(k), text(t) { 929 : key(k), text(t) {
780 } 930 }
781 931
782 PNGCodec::Comment::~Comment() { 932 PNGCodec::Comment::~Comment() {
783 } 933 }
784 934
785 } // namespace gfx 935 } // namespace gfx
OLDNEW
« ui/gfx/codec/png_codec.h ('K') | « ui/gfx/codec/png_codec.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698