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

Side by Side Diff: experimental/flocking_geese/nacl_app/png_loader.cc

Issue 10928195: First round of dead file removal (Closed) Base URL: https://github.com/samclegg/nativeclient-sdk.git@master
Patch Set: Created 8 years, 3 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
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Native Client 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 "nacl_app/png_loader.h"
6
7 using url_io::WebResourceLoader;
8
9 namespace {
10 static const size_t kPngSignatureLength = 8;
11
12 const uint32_t kRedBlueMask = 0x00FF00FF;
13 const uint32_t kGreenMask = 0x0000FF00;
14 const uint32_t kAlphaMask = 0xFF000000;
15 const uint32_t kPixelOne = 0xFF;
16 const uint32_t kAlphaShift = 24;
17 } // namespace
18
19 namespace flocking_geese {
20
21 // Wrapper function handed to libpng that reads the PNG data.
22 void ReadDataFromInputStream(png_structp png_ptr,
23 png_bytep out_bytes,
24 png_size_t byte_count) {
25 if(png_ptr->io_ptr == NULL)
26 return;
27 flocking_geese::PngLoader* png_loader =
28 static_cast<flocking_geese::PngLoader*>(png_ptr->io_ptr);
29 const size_t bytes_read = png_loader->ReadPngData(
30 static_cast<uint8_t*>(out_bytes),
31 static_cast<size_t>(byte_count));
32
33 if (static_cast<png_size_t>(bytes_read) != byte_count)
34 return;
35 }
36
37 PngLoader::~PngLoader() {
38 ReleaseAndInvalidate();
39 }
40
41 void PngLoader::ReleaseAndInvalidate() {
42 is_valid_ = false;
43 if (png_ptr_ && png_info_ptr_) {
44 png_destroy_read_struct(&png_ptr_, &png_info_ptr_, NULL);
45 } else if (png_ptr_) {
46 png_destroy_read_struct(&png_ptr_, NULL, NULL);
47 }
48 png_ptr_ = NULL;
49 png_info_ptr_ = NULL;
50 png_image_size_.SetSize(0, 0);
51 }
52
53 void PngLoader::OnLoaderReceivedResponseInfo(WebResourceLoader* loader) {
54 ReleaseAndInvalidate(); // Start with clean data.
55 // The content length should be a value greater than 0 or -1 for a
56 // continuous stream.
57 content_length_ = loader->GetContentLength();
58 assert(content_length_ == -1 or content_length_ > 0);
59 if (content_length_ == 0 || content_length_ < -1) {
60 return;
61 }
62 // Allocate the internal buffer that will hold all the PNG data. Start
63 // reading data into the beginning of this buffer.
64 png_data_.reset(new uint8_t[content_length_]);
65 url_bytes_read_ = 0;
66 loader->set_content_buffer(png_data_.get(), content_length_);
67 loader->ReadMoreData();
68 }
69
70 void PngLoader::OnLoaderReceivedData(WebResourceLoader* loader) {
71 // Advance the internal bufer pointer to the end of the current data and
72 // issue another read.
73 url_bytes_read_ += loader->data_size();
74 if (url_bytes_read_ < content_length_) {
75 uint8_t* buffer_ptr = &(png_data_[url_bytes_read_]);
76 loader->set_content_buffer(buffer_ptr, content_length_);
77 } else {
78 // This will cause the loader to switch to an internal buffer and protect
79 // |png_data_| from possibn=le overruns.
80 loader->set_content_buffer(NULL, 0);
81 }
82 loader->ReadMoreData();
83 }
84
85 void PngLoader::OnLoaderCompletedDownload(WebResourceLoader* loader) {
86 url_bytes_read_ = 0;
87 is_valid_ = true;
88 png_data_pos_ = 0;
89 // Validate the data and initialize the PNG structs.
90 uint8_t png_signature[kPngSignatureLength];
91 if (ReadPngData(png_signature, kPngSignatureLength) != kPngSignatureLength) {
92 ReleaseAndInvalidate();
93 return;
94 }
95 if (!png_check_sig(png_signature, kPngSignatureLength)) {
96 ReleaseAndInvalidate();
97 return;
98 }
99 png_ptr_ = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
100 if (png_ptr_ == NULL) {
101 ReleaseAndInvalidate();
102 return;
103 }
104 png_info_ptr_ = png_create_info_struct(png_ptr_);
105 if (png_info_ptr_ == NULL) {
106 ReleaseAndInvalidate();
107 return;
108 }
109 png_set_read_fn(png_ptr_, this, ReadDataFromInputStream);
110 // Tell libpng that the signature bytes have been read.
111 png_set_sig_bytes(png_ptr_, kPngSignatureLength);
112
113 // Try to read and validate the header info.
114 png_read_info(png_ptr_, png_info_ptr_);
115 png_uint_32 width = 0;
116 png_uint_32 height = 0;
117 int bits_per_sample;
118 int pixel_format;
119 png_uint_32 png_error = png_get_IHDR(
120 png_ptr_,
121 png_info_ptr_,
122 &width,
123 &height,
124 &bits_per_sample,
125 &pixel_format,
126 NULL, NULL, NULL);
127 if (png_error != 1) {
128 ReleaseAndInvalidate();
129 return;
130 }
131 png_image_size_.SetSize(width, height);
132 // Tell libpng to strip 16 bit/color files down to 8 bits/color.
133 png_set_strip_16(png_ptr_);
134 switch (pixel_format) {
135 case PNG_COLOR_TYPE_PALETTE:
136 // Expand paletted colors into true RGB triplets.
137 png_set_palette_to_rgb(png_ptr_);
138 break;
139 case PNG_COLOR_TYPE_GRAY:
140 // Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel.
141 if (bits_per_sample < 8)
142 png_set_expand_gray_1_2_4_to_8(png_ptr_);
143 break;
144 case PNG_COLOR_TYPE_RGB:
145 png_set_expand(png_ptr_);
146 break;
147 }
148 // Expand paletted or RGB images with transparency to full alpha channels
149 // so the data will be available as RGBA quartets.
150 if (png_get_valid(png_ptr_, png_info_ptr_, PNG_INFO_tRNS))
151 png_set_tRNS_to_alpha(png_ptr_);
152 // Change RGBA -> ARGB.
153 // png_set_swap_alpha(png_ptr_);
154 }
155
156 void PngLoader::OnLoaderError(int32_t error, WebResourceLoader* loader) {
157 ReleaseAndInvalidate();
158 }
159
160 void PngLoader::OnLoaderDone(WebResourceLoader* loader) {
161 loader->CloseAndDeleteSelf();
162 }
163
164 void PngLoader::FillPixelBuffer(uint32_t* pixel_buffer) {
165 if (!is_valid())
166 return;
167 png_bytep row_pointers[png_image_size_.height()];
168 size_t row_bytes = png_get_rowbytes(png_ptr_, png_info_ptr_);
169 for (int32_t row = 0; row < png_image_size_.height(); ++row) {
170 row_pointers[row] = static_cast<png_bytep>(png_malloc(png_ptr_, row_bytes));
171 }
172 png_read_image(png_ptr_, row_pointers);
173 png_read_end(png_ptr_, png_info_ptr_);
174 // Copy the PNG data into the given buffer.
175 for (int32_t row = 0; row < png_image_size_.height(); ++row) {
176 memcpy(pixel_buffer, row_pointers[row], row_bytes);
177 PreMultiplyAlpha(pixel_buffer, png_image_size_.width());
178 pixel_buffer += png_image_size_.width();
179 png_free(png_ptr_, row_pointers[row]);
180 }
181 }
182
183 void PngLoader::PreMultiplyAlpha(uint32_t* scanline, int32_t line_width) {
184 for (int32_t x = 0; x < line_width; ++x) {
185 uint32_t src = *scanline;
186 uint32_t rb = src & kRedBlueMask;
187 uint32_t g = src & kGreenMask;
188 uint32_t alpha = (src >> kAlphaShift) & kPixelOne;
189 rb *= alpha;
190 g *= alpha;
191 rb = (rb >> 8) & kRedBlueMask;
192 g = (g >> 8) & kGreenMask;
193 *scanline++ = (rb | g | (src & kAlphaMask));
194 }
195 }
196
197 size_t PngLoader::ReadPngData(uint8_t* buffer, const size_t byte_count) {
198 size_t copy_byte_count = byte_count;
199 if (png_data_pos_ + byte_count >= static_cast<size_t>(content_length_))
200 copy_byte_count = content_length_ - png_data_pos_; // "end-of-file".
201 memcpy(buffer, &(png_data_[png_data_pos_]), copy_byte_count);
202 png_data_pos_ += copy_byte_count;
203 return copy_byte_count;
204 }
205
206 } // namespace flocking_geese
207
OLDNEW
« no previous file with comments | « experimental/flocking_geese/nacl_app/png_loader.h ('k') | experimental/flocking_geese/nacl_app/scoped_pixel_lock.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698