| Index: experimental/flocking_geese/nacl_app/png_loader.cc
|
| diff --git a/experimental/flocking_geese/nacl_app/png_loader.cc b/experimental/flocking_geese/nacl_app/png_loader.cc
|
| deleted file mode 100644
|
| index 91aec01185a78f92b8ce6e53880ee03adc941f50..0000000000000000000000000000000000000000
|
| --- a/experimental/flocking_geese/nacl_app/png_loader.cc
|
| +++ /dev/null
|
| @@ -1,207 +0,0 @@
|
| -// Copyright (c) 2011 The Native Client Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "nacl_app/png_loader.h"
|
| -
|
| -using url_io::WebResourceLoader;
|
| -
|
| -namespace {
|
| -static const size_t kPngSignatureLength = 8;
|
| -
|
| -const uint32_t kRedBlueMask = 0x00FF00FF;
|
| -const uint32_t kGreenMask = 0x0000FF00;
|
| -const uint32_t kAlphaMask = 0xFF000000;
|
| -const uint32_t kPixelOne = 0xFF;
|
| -const uint32_t kAlphaShift = 24;
|
| -} // namespace
|
| -
|
| -namespace flocking_geese {
|
| -
|
| -// Wrapper function handed to libpng that reads the PNG data.
|
| -void ReadDataFromInputStream(png_structp png_ptr,
|
| - png_bytep out_bytes,
|
| - png_size_t byte_count) {
|
| - if(png_ptr->io_ptr == NULL)
|
| - return;
|
| - flocking_geese::PngLoader* png_loader =
|
| - static_cast<flocking_geese::PngLoader*>(png_ptr->io_ptr);
|
| - const size_t bytes_read = png_loader->ReadPngData(
|
| - static_cast<uint8_t*>(out_bytes),
|
| - static_cast<size_t>(byte_count));
|
| -
|
| - if (static_cast<png_size_t>(bytes_read) != byte_count)
|
| - return;
|
| -}
|
| -
|
| -PngLoader::~PngLoader() {
|
| - ReleaseAndInvalidate();
|
| -}
|
| -
|
| -void PngLoader::ReleaseAndInvalidate() {
|
| - is_valid_ = false;
|
| - if (png_ptr_ && png_info_ptr_) {
|
| - png_destroy_read_struct(&png_ptr_, &png_info_ptr_, NULL);
|
| - } else if (png_ptr_) {
|
| - png_destroy_read_struct(&png_ptr_, NULL, NULL);
|
| - }
|
| - png_ptr_ = NULL;
|
| - png_info_ptr_ = NULL;
|
| - png_image_size_.SetSize(0, 0);
|
| -}
|
| -
|
| -void PngLoader::OnLoaderReceivedResponseInfo(WebResourceLoader* loader) {
|
| - ReleaseAndInvalidate(); // Start with clean data.
|
| - // The content length should be a value greater than 0 or -1 for a
|
| - // continuous stream.
|
| - content_length_ = loader->GetContentLength();
|
| - assert(content_length_ == -1 or content_length_ > 0);
|
| - if (content_length_ == 0 || content_length_ < -1) {
|
| - return;
|
| - }
|
| - // Allocate the internal buffer that will hold all the PNG data. Start
|
| - // reading data into the beginning of this buffer.
|
| - png_data_.reset(new uint8_t[content_length_]);
|
| - url_bytes_read_ = 0;
|
| - loader->set_content_buffer(png_data_.get(), content_length_);
|
| - loader->ReadMoreData();
|
| -}
|
| -
|
| -void PngLoader::OnLoaderReceivedData(WebResourceLoader* loader) {
|
| - // Advance the internal bufer pointer to the end of the current data and
|
| - // issue another read.
|
| - url_bytes_read_ += loader->data_size();
|
| - if (url_bytes_read_ < content_length_) {
|
| - uint8_t* buffer_ptr = &(png_data_[url_bytes_read_]);
|
| - loader->set_content_buffer(buffer_ptr, content_length_);
|
| - } else {
|
| - // This will cause the loader to switch to an internal buffer and protect
|
| - // |png_data_| from possibn=le overruns.
|
| - loader->set_content_buffer(NULL, 0);
|
| - }
|
| - loader->ReadMoreData();
|
| -}
|
| -
|
| -void PngLoader::OnLoaderCompletedDownload(WebResourceLoader* loader) {
|
| - url_bytes_read_ = 0;
|
| - is_valid_ = true;
|
| - png_data_pos_ = 0;
|
| - // Validate the data and initialize the PNG structs.
|
| - uint8_t png_signature[kPngSignatureLength];
|
| - if (ReadPngData(png_signature, kPngSignatureLength) != kPngSignatureLength) {
|
| - ReleaseAndInvalidate();
|
| - return;
|
| - }
|
| - if (!png_check_sig(png_signature, kPngSignatureLength)) {
|
| - ReleaseAndInvalidate();
|
| - return;
|
| - }
|
| - png_ptr_ = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
| - if (png_ptr_ == NULL) {
|
| - ReleaseAndInvalidate();
|
| - return;
|
| - }
|
| - png_info_ptr_ = png_create_info_struct(png_ptr_);
|
| - if (png_info_ptr_ == NULL) {
|
| - ReleaseAndInvalidate();
|
| - return;
|
| - }
|
| - png_set_read_fn(png_ptr_, this, ReadDataFromInputStream);
|
| - // Tell libpng that the signature bytes have been read.
|
| - png_set_sig_bytes(png_ptr_, kPngSignatureLength);
|
| -
|
| - // Try to read and validate the header info.
|
| - png_read_info(png_ptr_, png_info_ptr_);
|
| - png_uint_32 width = 0;
|
| - png_uint_32 height = 0;
|
| - int bits_per_sample;
|
| - int pixel_format;
|
| - png_uint_32 png_error = png_get_IHDR(
|
| - png_ptr_,
|
| - png_info_ptr_,
|
| - &width,
|
| - &height,
|
| - &bits_per_sample,
|
| - &pixel_format,
|
| - NULL, NULL, NULL);
|
| - if (png_error != 1) {
|
| - ReleaseAndInvalidate();
|
| - return;
|
| - }
|
| - png_image_size_.SetSize(width, height);
|
| - // Tell libpng to strip 16 bit/color files down to 8 bits/color.
|
| - png_set_strip_16(png_ptr_);
|
| - switch (pixel_format) {
|
| - case PNG_COLOR_TYPE_PALETTE:
|
| - // Expand paletted colors into true RGB triplets.
|
| - png_set_palette_to_rgb(png_ptr_);
|
| - break;
|
| - case PNG_COLOR_TYPE_GRAY:
|
| - // Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel.
|
| - if (bits_per_sample < 8)
|
| - png_set_expand_gray_1_2_4_to_8(png_ptr_);
|
| - break;
|
| - case PNG_COLOR_TYPE_RGB:
|
| - png_set_expand(png_ptr_);
|
| - break;
|
| - }
|
| - // Expand paletted or RGB images with transparency to full alpha channels
|
| - // so the data will be available as RGBA quartets.
|
| - if (png_get_valid(png_ptr_, png_info_ptr_, PNG_INFO_tRNS))
|
| - png_set_tRNS_to_alpha(png_ptr_);
|
| - // Change RGBA -> ARGB.
|
| - // png_set_swap_alpha(png_ptr_);
|
| -}
|
| -
|
| -void PngLoader::OnLoaderError(int32_t error, WebResourceLoader* loader) {
|
| - ReleaseAndInvalidate();
|
| -}
|
| -
|
| -void PngLoader::OnLoaderDone(WebResourceLoader* loader) {
|
| - loader->CloseAndDeleteSelf();
|
| -}
|
| -
|
| -void PngLoader::FillPixelBuffer(uint32_t* pixel_buffer) {
|
| - if (!is_valid())
|
| - return;
|
| - png_bytep row_pointers[png_image_size_.height()];
|
| - size_t row_bytes = png_get_rowbytes(png_ptr_, png_info_ptr_);
|
| - for (int32_t row = 0; row < png_image_size_.height(); ++row) {
|
| - row_pointers[row] = static_cast<png_bytep>(png_malloc(png_ptr_, row_bytes));
|
| - }
|
| - png_read_image(png_ptr_, row_pointers);
|
| - png_read_end(png_ptr_, png_info_ptr_);
|
| - // Copy the PNG data into the given buffer.
|
| - for (int32_t row = 0; row < png_image_size_.height(); ++row) {
|
| - memcpy(pixel_buffer, row_pointers[row], row_bytes);
|
| - PreMultiplyAlpha(pixel_buffer, png_image_size_.width());
|
| - pixel_buffer += png_image_size_.width();
|
| - png_free(png_ptr_, row_pointers[row]);
|
| - }
|
| -}
|
| -
|
| -void PngLoader::PreMultiplyAlpha(uint32_t* scanline, int32_t line_width) {
|
| - for (int32_t x = 0; x < line_width; ++x) {
|
| - uint32_t src = *scanline;
|
| - uint32_t rb = src & kRedBlueMask;
|
| - uint32_t g = src & kGreenMask;
|
| - uint32_t alpha = (src >> kAlphaShift) & kPixelOne;
|
| - rb *= alpha;
|
| - g *= alpha;
|
| - rb = (rb >> 8) & kRedBlueMask;
|
| - g = (g >> 8) & kGreenMask;
|
| - *scanline++ = (rb | g | (src & kAlphaMask));
|
| - }
|
| -}
|
| -
|
| -size_t PngLoader::ReadPngData(uint8_t* buffer, const size_t byte_count) {
|
| - size_t copy_byte_count = byte_count;
|
| - if (png_data_pos_ + byte_count >= static_cast<size_t>(content_length_))
|
| - copy_byte_count = content_length_ - png_data_pos_; // "end-of-file".
|
| - memcpy(buffer, &(png_data_[png_data_pos_]), copy_byte_count);
|
| - png_data_pos_ += copy_byte_count;
|
| - return copy_byte_count;
|
| -}
|
| -
|
| -} // namespace flocking_geese
|
| -
|
|
|