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

Side by Side Diff: base/gfx/png_encoder.cc

Issue 243076: Move the JPEG and PNG codecs from base/gfx to app/gfx/codec. Move the classes... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 2 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/basictypes.h"
6 #include "base/gfx/png_encoder.h"
7 #include "base/logging.h"
8 #include "base/scoped_ptr.h"
9 #include "third_party/skia/include/core/SkBitmap.h"
10 #include "third_party/skia/include/core/SkUnPreMultiply.h"
11
12 extern "C" {
13 #if defined(USE_SYSTEM_LIBPNG)
14 #include <png.h>
15 #else
16 #include "third_party/libpng/png.h"
17 #endif
18 }
19
20 namespace {
21
22 // Converts BGRA->RGBA and RGBA->BGRA.
23 void ConvertBetweenBGRAandRGBA(const unsigned char* input, int pixel_width,
24 unsigned char* output) {
25 for (int x = 0; x < pixel_width; x++) {
26 const unsigned char* pixel_in = &input[x * 4];
27 unsigned char* pixel_out = &output[x * 4];
28 pixel_out[0] = pixel_in[2];
29 pixel_out[1] = pixel_in[1];
30 pixel_out[2] = pixel_in[0];
31 pixel_out[3] = pixel_in[3];
32 }
33 }
34
35 void ConvertRGBAtoRGB(const unsigned char* rgba, int pixel_width,
36 unsigned char* rgb) {
37 for (int x = 0; x < pixel_width; x++) {
38 const unsigned char* pixel_in = &rgba[x * 4];
39 unsigned char* pixel_out = &rgb[x * 3];
40 pixel_out[0] = pixel_in[0];
41 pixel_out[1] = pixel_in[1];
42 pixel_out[2] = pixel_in[2];
43 }
44 }
45
46 } // namespace
47
48 // Encoder --------------------------------------------------------------------
49 //
50 // This section of the code is based on nsPNGEncoder.cpp in Mozilla
51 // (Copyright 2005 Google Inc.)
52
53 namespace {
54
55 // Passed around as the io_ptr in the png structs so our callbacks know where
56 // to write data.
57 struct PngEncoderState {
58 PngEncoderState(std::vector<unsigned char>* o) : out(o) {}
59 std::vector<unsigned char>* out;
60 };
61
62 // Called by libpng to flush its internal buffer to ours.
63 void EncoderWriteCallback(png_structp png, png_bytep data, png_size_t size) {
64 PngEncoderState* state = static_cast<PngEncoderState*>(png_get_io_ptr(png));
65 DCHECK(state->out);
66
67 size_t old_size = state->out->size();
68 state->out->resize(old_size + size);
69 memcpy(&(*state->out)[old_size], data, size);
70 }
71
72 void ConvertBGRAtoRGB(const unsigned char* bgra, int pixel_width,
73 unsigned char* rgb) {
74 for (int x = 0; x < pixel_width; x++) {
75 const unsigned char* pixel_in = &bgra[x * 4];
76 unsigned char* pixel_out = &rgb[x * 3];
77 pixel_out[0] = pixel_in[2];
78 pixel_out[1] = pixel_in[1];
79 pixel_out[2] = pixel_in[0];
80 }
81 }
82
83 // Automatically destroys the given write structs on destruction to make
84 // cleanup and error handling code cleaner.
85 class PngWriteStructDestroyer {
86 public:
87 PngWriteStructDestroyer(png_struct** ps, png_info** pi) : ps_(ps), pi_(pi) {
88 }
89 ~PngWriteStructDestroyer() {
90 png_destroy_write_struct(ps_, pi_);
91 }
92 private:
93 png_struct** ps_;
94 png_info** pi_;
95
96 DISALLOW_EVIL_CONSTRUCTORS(PngWriteStructDestroyer);
97 };
98
99 } // namespace
100
101 // static
102 bool PNGEncoder::Encode(const unsigned char* input, ColorFormat format,
103 int w, int h, int row_byte_width,
104 bool discard_transparency,
105 std::vector<unsigned char>* output) {
106 // Run to convert an input row into the output row format, NULL means no
107 // conversion is necessary.
108 void (*converter)(const unsigned char* in, int w, unsigned char* out) = NULL;
109
110 int input_color_components, output_color_components;
111 int png_output_color_type;
112 switch (format) {
113 case FORMAT_RGB:
114 input_color_components = 3;
115 output_color_components = 3;
116 png_output_color_type = PNG_COLOR_TYPE_RGB;
117 discard_transparency = false;
118 break;
119
120 case FORMAT_RGBA:
121 input_color_components = 4;
122 if (discard_transparency) {
123 output_color_components = 3;
124 png_output_color_type = PNG_COLOR_TYPE_RGB;
125 converter = ConvertRGBAtoRGB;
126 } else {
127 output_color_components = 4;
128 png_output_color_type = PNG_COLOR_TYPE_RGB_ALPHA;
129 converter = NULL;
130 }
131 break;
132
133 case FORMAT_BGRA:
134 input_color_components = 4;
135 if (discard_transparency) {
136 output_color_components = 3;
137 png_output_color_type = PNG_COLOR_TYPE_RGB;
138 converter = ConvertBGRAtoRGB;
139 } else {
140 output_color_components = 4;
141 png_output_color_type = PNG_COLOR_TYPE_RGB_ALPHA;
142 converter = ConvertBetweenBGRAandRGBA;
143 }
144 break;
145
146 default:
147 NOTREACHED() << "Unknown pixel format";
148 return false;
149 }
150
151 // Row stride should be at least as long as the length of the data.
152 DCHECK(input_color_components * w <= row_byte_width);
153
154 png_struct* png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
155 png_voidp_NULL,
156 png_error_ptr_NULL,
157 png_error_ptr_NULL);
158 if (!png_ptr)
159 return false;
160 png_info* info_ptr = png_create_info_struct(png_ptr);
161 if (!info_ptr) {
162 png_destroy_write_struct(&png_ptr, NULL);
163 return false;
164 }
165 PngWriteStructDestroyer destroyer(&png_ptr, &info_ptr);
166
167 if (setjmp(png_jmpbuf(png_ptr))) {
168 // The destroyer will ensure that the structures are cleaned up in this
169 // case, even though we may get here as a jump from random parts of the
170 // PNG library called below.
171 return false;
172 }
173
174 // Set our callback for libpng to give us the data.
175 PngEncoderState state(output);
176 png_set_write_fn(png_ptr, &state, EncoderWriteCallback, NULL);
177
178 png_set_IHDR(png_ptr, info_ptr, w, h, 8, png_output_color_type,
179 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
180 PNG_FILTER_TYPE_DEFAULT);
181 png_write_info(png_ptr, info_ptr);
182
183 if (!converter) {
184 // No conversion needed, give the data directly to libpng.
185 for (int y = 0; y < h; y ++)
186 png_write_row(png_ptr,
187 const_cast<unsigned char*>(&input[y * row_byte_width]));
188 } else {
189 // Needs conversion using a separate buffer.
190 unsigned char* row = new unsigned char[w * output_color_components];
191 for (int y = 0; y < h; y ++) {
192 converter(&input[y * row_byte_width], w, row);
193 png_write_row(png_ptr, row);
194 }
195 delete[] row;
196 }
197
198 png_write_end(png_ptr, info_ptr);
199 return true;
200 }
201
202 // static
203 bool PNGEncoder::EncodeBGRASkBitmap(const SkBitmap& input,
204 bool discard_transparency,
205 std::vector<unsigned char>* output) {
206 static const int bbp = 4;
207
208 SkAutoLockPixels lock_input(input);
209 DCHECK(input.empty() || input.bytesPerPixel() == bbp);
210
211 // SkBitmaps are premultiplied, we need to unpremultiply them.
212 scoped_array<unsigned char> divided(
213 new unsigned char[input.width() * input.height() * bbp]);
214
215 int i = 0;
216 for (int y = 0; y < input.height(); y++) {
217 for (int x = 0; x < input.width(); x++) {
218 uint32 pixel = input.getAddr32(0, y)[x];
219
220 int alpha = SkColorGetA(pixel);
221 if (alpha != 0 && alpha != 255) {
222 SkColor unmultiplied = SkUnPreMultiply::PMColorToColor(pixel);
223 divided[i + 0] = SkColorGetR(unmultiplied);
224 divided[i + 1] = SkColorGetG(unmultiplied);
225 divided[i + 2] = SkColorGetB(unmultiplied);
226 divided[i + 3] = alpha;
227 } else {
228 divided[i + 0] = SkColorGetR(pixel);
229 divided[i + 1] = SkColorGetG(pixel);
230 divided[i + 2] = SkColorGetB(pixel);
231 divided[i + 3] = alpha;
232 }
233 i += bbp;
234 }
235 }
236
237 return Encode(divided.get(),
238 PNGEncoder::FORMAT_RGBA, input.width(), input.height(),
239 input.width() * bbp, discard_transparency, output);
240 }
OLDNEW
« no previous file with comments | « base/gfx/png_encoder.h ('k') | build/common.gypi » ('j') | build/common.gypi » ('J')

Powered by Google App Engine
This is Rietveld 408576698