summaryrefslogtreecommitdiffstats
path: root/o3d/core
diff options
context:
space:
mode:
authoryux@google.com <yux@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-15 01:07:36 +0000
committeryux@google.com <yux@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-15 01:07:36 +0000
commit128ff759facb55e3c0c1326e97c00b325ac3f484 (patch)
tree868fda83a815ac414abac1466091faced5bc3eb1 /o3d/core
parent267088ffb702c649bfd2c1123f1f9c3f391b69d2 (diff)
downloadchromium_src-128ff759facb55e3c0c1326e97c00b325ac3f484.zip
chromium_src-128ff759facb55e3c0c1326e97c00b325ac3f484.tar.gz
chromium_src-128ff759facb55e3c0c1326e97c00b325ac3f484.tar.bz2
expose bitmap in js.
Review URL: http://codereview.chromium.org/150058 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@20700 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d/core')
-rw-r--r--o3d/core/cross/bitmap.cc293
-rw-r--r--o3d/core/cross/bitmap.h781
-rw-r--r--o3d/core/cross/bitmap_test.cc739
-rw-r--r--o3d/core/cross/class_manager.cc1
-rw-r--r--o3d/core/cross/pack.cc52
-rw-r--r--o3d/core/cross/pack.h26
-rw-r--r--o3d/core/cross/renderer_test.cc16
-rw-r--r--o3d/core/cross/texture.cc154
-rw-r--r--o3d/core/cross/texture.h38
-rw-r--r--o3d/core/win/d3d9/renderer_d3d9.cc26
-rw-r--r--o3d/core/win/d3d9/texture_d3d9.cc64
-rw-r--r--o3d/core/win/d3d9/texture_d3d9.h4
12 files changed, 1626 insertions, 568 deletions
diff --git a/o3d/core/cross/bitmap.cc b/o3d/core/cross/bitmap.cc
index 947d68ea..d3d1499 100644
--- a/o3d/core/cross/bitmap.cc
+++ b/o3d/core/cross/bitmap.cc
@@ -37,9 +37,10 @@
// The precompiled header must appear before anything else.
#include "core/cross/precompile.h"
+#include "core/cross/bitmap.h"
#include <cstring>
+#include <cmath>
#include <sys/stat.h>
-#include "core/cross/bitmap.h"
#include "utils/cross/file_path_utils.h"
#include "base/file_path.h"
#include "base/file_util.h"
@@ -51,8 +52,23 @@ using file_util::OpenFile;
using file_util::CloseFile;
using file_util::GetFileSize;
+namespace {
+static const double kEpsilon = 0.0001;
+} // anonymous namespace.
+
namespace o3d {
+ O3D_DEFN_CLASS(Bitmap, ParamObject);
+
+Bitmap::Bitmap(ServiceLocator* service_locator)
+ : ParamObject(service_locator),
+ image_data_(NULL),
+ format_(Texture::UNKNOWN_FORMAT),
+ width_(0),
+ height_(0),
+ num_mipmaps_(0),
+ is_cubemap_(false) {}
+
// Gets the size of the buffer containing a an image, given its width, height
// and format.
unsigned int Bitmap::GetBufferSize(unsigned int width,
@@ -261,6 +277,178 @@ bool Bitmap::LoadFromRawData(RawData *raw_data,
return LoadFromStream(&stream, filename, file_type, generate_mipmaps);
}
+void Bitmap::DrawImage(Bitmap* src_img,
+ int src_x, int src_y,
+ int src_width, int src_height,
+ int dst_x, int dst_y,
+ int dst_width, int dst_height) {
+ DCHECK(src_img->image_data());
+ DCHECK(image_data());
+
+ // Clip source and destination rectangles to
+ // source and destination bitmaps.
+ // if src or dest rectangle is out of boundary,
+ // do nothing and return.
+ if (!AdjustDrawImageBoundary(&src_x, &src_y,
+ &src_width, &src_height,
+ src_img->width_, src_img->height_,
+ &dst_x, &dst_y,
+ &dst_width, &dst_height,
+ width_, height_))
+ return;
+
+ unsigned int components = 0;
+ // check formats of source and dest images.
+ // format of source and dest should be the same.
+ if (src_img->format_ != format_) {
+ O3D_ERROR(service_locator()) << "DrawImage does not support "
+ << "different formats.";
+ return;
+ }
+ // if src and dest are in the same size and drawImage is copying
+ // the entire bitmap on dest image, just perform memcpy.
+ if (src_x == 0 && src_y == 0 && dst_x == 0 && dst_y == 0 &&
+ src_img->width_ == width_ && src_img->height_ == height_ &&
+ src_width == src_img->width_ && src_height == src_img->height_ &&
+ dst_width == width_ && dst_height == height_) {
+ memcpy(image_data(), src_img->image_data(), GetTotalSize());
+ return;
+ }
+
+ // if drawImage is not copying the whole bitmap, we need to check
+ // the format. currently only support XRGB8 and ARGB8
+ if (src_img->format_ == Texture::XRGB8 ||
+ src_img->format_ == Texture::ARGB8) {
+ components = 4;
+ } else {
+ O3D_ERROR(service_locator()) << "DrawImage does not support format: "
+ << src_img->format_ << " unless src and "
+ << "dest images are in the same size and "
+ << "copying the entire bitmap";
+ return;
+ }
+
+ unsigned char* src_img_data = src_img->image_data();
+ unsigned char* dst_img_data = image_data();
+
+ // crop part of image from src img, scale it in
+ // bilinear interpolation fashion, and paste it
+ // on dst img.
+ BilinearInterpolateScale(src_img_data, src_x, src_y,
+ src_width, src_height,
+ src_img->width_, src_img->height_,
+ dst_img_data, dst_x, dst_y,
+ dst_width, dst_height,
+ width_, height_, components);
+}
+
+// static utility function used by DrawImage in bitmap and textures.
+// in this function, positions are converted to 4th-quadrant, which
+// means origin locates left-up corner.
+void Bitmap::BilinearInterpolateScale(const uint8* src_img_data,
+ int src_x, int src_y,
+ int src_width, int src_height,
+ int src_img_width, int src_img_height,
+ uint8* dest_img_data,
+ int dest_x, int dest_y,
+ int dest_width, int dest_height,
+ int dest_img_width, int dest_img_height,
+ int components) {
+ for (int i = 0; i < std::abs(dest_width); i++) {
+ // x is the iterator of dest_width in dest_img.
+ // change x to negative if dest_width is negative.
+ int x = i;
+ if (dest_width < 0)
+ x = -i;
+
+ // calculate corresponding coordinate in src_img.
+ double base_x = i * (std::abs(src_width) - 1) /
+ static_cast<double>(std::abs(dest_width) - 1);
+ // base_floor_x is the iterator of src_width in src_img.
+ // change base_x to negative if src_width is negative.
+ if (src_width < 0)
+ base_x = -base_x;
+ int base_floor_x = static_cast<int>(std::floor(base_x));
+
+ for (int j = 0; j < std::abs(dest_height); j++) {
+ // y is the iterator of dest_height in dest_img.
+ // change y to negative if dest_height is negative.
+ int y = j;
+ if (dest_height < 0)
+ y = -j;
+
+ // calculate coresponding coordinate in src_img.
+ double base_y = j * (std::abs(src_height) - 1) /
+ static_cast<double>(std::abs(dest_height) - 1);
+ // change base_y to negative if src_height is negative.
+ if (src_height < 0)
+ base_y = -base_y;
+ int base_floor_y = static_cast<int>(std::floor(base_y));
+
+ for (unsigned int c = 0; c < components; c++) {
+ // if base_x and base_y are integers, which means this point
+ // exists in src_img, just copy the original values.
+ if (base_x - base_floor_x < kEpsilon &&
+ base_y - base_floor_y < kEpsilon) {
+ dest_img_data[((dest_img_height - (y + dest_y) - 1) *
+ dest_img_width + dest_x + x) * components + c] =
+ src_img_data[((src_img_height - (base_floor_y + src_y) - 1) *
+ src_img_width + src_x + base_floor_x) * components + c];
+ continue;
+ }
+
+ // get four nearest neighbors of point (base_x, base_y) from src img.
+ uint8 src_neighbor_11, src_neighbor_21,
+ src_neighbor_12, src_neighbor_22;
+ src_neighbor_11 = src_img_data[((src_img_height - (base_floor_y +
+ src_y) - 1) * src_img_width + src_x +
+ base_floor_x) * components + c];
+ // if base_x exists in src img. set src_neighbor_21 to src_neighbor_11
+ // so the interpolation result would remain src_neighbor_11.
+ if (base_x - base_floor_x < kEpsilon)
+ src_neighbor_21 = src_neighbor_11;
+ else
+ src_neighbor_21 = src_img_data[((src_img_height - (base_floor_y +
+ src_y) - 1) * src_img_width + src_x +
+ base_floor_x + 1) * components + c];
+ // if base_y exists in src img. set src_neighbor_12 to src_neighbor_11
+ // so the interpolation result would remain src_neighbor_11.
+ if (base_y - base_floor_y < kEpsilon)
+ src_neighbor_12 = src_neighbor_11;
+ else
+ src_neighbor_12 = src_img_data[((src_img_height - (base_floor_y +
+ src_y) - 2) * src_img_width + src_x +
+ base_floor_x) * components + c];
+
+ if (base_x - base_floor_x < kEpsilon)
+ src_neighbor_22 = src_neighbor_21;
+ else if (base_y - base_floor_y < kEpsilon)
+ src_neighbor_22 = src_neighbor_12;
+ else
+ src_neighbor_22 = src_img_data[((src_img_height - (base_floor_y +
+ src_y) - 2) * src_img_width + src_x +
+ base_floor_x + 1) * components + c];
+
+ // calculate interpolated value.
+ double interpolatedValue = (1 - (base_y - base_floor_y)) *
+ ((base_x - base_floor_x) *
+ src_neighbor_21 +
+ (1 - (base_x - base_floor_x)) *
+ src_neighbor_11) +
+ (base_y - base_floor_y) *
+ ((base_x - base_floor_x) *
+ src_neighbor_22 +
+ (1 - (base_x - base_floor_x)) *
+ src_neighbor_12);
+
+ // assign the nearest integer of interpolatedValue to dest_img_data.
+ dest_img_data[((dest_img_height - (y + dest_y) - 1) * dest_img_width +
+ dest_x + x) * components + c] =
+ static_cast<uint8>(interpolatedValue + 0.5);
+ }
+ }
+ }
+}
Bitmap::ImageFileType Bitmap::GetFileTypeFromFilename(const char *filename) {
// Convert the filename to lower case for matching.
@@ -574,6 +762,105 @@ bool Bitmap::Scale(unsigned int src_width,
return true;
}
+// Adjust boundaries when using DrawImage function in bitmap or texture.
+bool Bitmap::AdjustDrawImageBoundary(int* src_x, int* src_y,
+ int* src_width, int* src_height,
+ int src_bmp_width, int src_bmp_height,
+ int* dest_x, int* dest_y,
+ int* dest_width, int* dest_height,
+ int dest_bmp_width, int dest_bmp_height) {
+ // if src or dest rectangle is out of boundaries, do nothing.
+ if ((*src_x < 0 && *src_x + *src_width <= 0) ||
+ (*src_y < 0 && *src_y + *src_height <= 0) ||
+ (*dest_x < 0 && *dest_x + *dest_width <= 0) ||
+ (*dest_y < 0 && *dest_y + *dest_height <= 0) ||
+ (*src_x >= src_bmp_width &&
+ *src_x + *src_width >= src_bmp_width - 1) ||
+ (*src_y >= src_bmp_height &&
+ *src_y + *src_height >= src_bmp_height - 1) ||
+ (*dest_x >= dest_bmp_width &&
+ *dest_x + *dest_width >= dest_bmp_width - 1) ||
+ (*dest_y >= dest_bmp_height &&
+ *dest_y + *dest_height >= dest_bmp_height - 1))
+ return false;
+
+ // if start points are negative.
+ // check whether src_x is negative.
+ if (!AdjustDrawImageBoundHelper(src_x, dest_x,
+ src_width, dest_width, src_bmp_width))
+ return false;
+ // check whether dest_x is negative.
+ if (!AdjustDrawImageBoundHelper(dest_x, src_x,
+ dest_width, src_width, dest_bmp_width))
+ return false;
+ // check whether src_y is negative.
+ if (!AdjustDrawImageBoundHelper(src_y, dest_y,
+ src_height, dest_height, src_bmp_height))
+ return false;
+ // check whether dest_y is negative.
+ if (!AdjustDrawImageBoundHelper(dest_y, src_y,
+ dest_height, src_height, dest_bmp_height))
+ return false;
+
+ // check any width or height becomes negative after adjustment.
+ if (*src_width == 0 || *src_height == 0 ||
+ *dest_width == 0 || *dest_height == 0) {
+ return false;
+ }
+
+ return true;
+}
+
+// utility function called in AdjustDrawImageBoundary.
+// help to adjust a specific dimension,
+// if start point or ending point is out of boundary.
+bool Bitmap::AdjustDrawImageBoundHelper(int* src_a, int* dest_a,
+ int* src_length, int* dest_length,
+ int src_bmp_length) {
+ if (*src_length == 0 || *dest_length == 0)
+ return false;
+
+ // check if start point is out of boundary.
+ // if src_a < 0, src_length must be positive.
+ if (*src_a < 0) {
+ int src_length_delta = 0 - *src_a;
+ *dest_a = *dest_a + (*dest_length) * src_length_delta / (*src_length);
+ *dest_length = *dest_length - (*dest_length) *
+ src_length_delta / (*src_length);
+ *src_length = *src_length - src_length_delta;
+ *src_a = 0;
+ }
+ // if src_a >= src_bmp_width, src_length must be negative.
+ if (*src_a >= src_bmp_length) {
+ int src_length_delta = *src_a - (src_bmp_length - 1);
+ *dest_a = *dest_a - (*dest_length) * src_length_delta / (*src_length);
+ *dest_length = *dest_length - (*dest_length) *
+ src_length_delta / *src_length;
+ *src_length = *src_length - src_length_delta;
+ *src_a = src_bmp_length - 1;
+ }
+
+ if (*src_length == 0 || *dest_length == 0)
+ return false;
+ // check whether start point + related length is out of boundary.
+ // if src_a + src_length > src_bmp_length, src_length must be positive.
+ if (*src_a + *src_length > src_bmp_length) {
+ int src_length_delta = *src_length - (src_bmp_length - *src_a);
+ *dest_length = *dest_length - (*dest_length) *
+ src_length_delta / (*src_length);
+ *src_length = *src_length - src_length_delta;
+ }
+ // if src_a + src_length < -1, src_length must be negative.
+ if (*src_a + *src_length < -1) {
+ int src_length_delta = 0 - (*src_a + *src_length);
+ *dest_length = *dest_length + (*dest_length) *
+ src_length_delta / (*src_length);
+ *src_length = *src_length + src_length_delta;
+ }
+
+ return true;
+}
+
// Checks that all the alpha values are 1.0
bool Bitmap::CheckAlphaIsOne() const {
if (!image_data())
@@ -682,4 +969,8 @@ bool Bitmap::CheckAlphaIsOne() const {
return true;
}
+ObjectBase::Ref Bitmap::Create(ServiceLocator* service_locator) {
+ return ObjectBase::Ref(new Bitmap(service_locator));
+}
+
} // namespace o3d
diff --git a/o3d/core/cross/bitmap.h b/o3d/core/cross/bitmap.h
index 1d16d4f7..60ebb4a 100644
--- a/o3d/core/cross/bitmap.h
+++ b/o3d/core/cross/bitmap.h
@@ -1,342 +1,439 @@
-/*
- * Copyright 2009, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-// This file contains the declaration of Bitmap helper class that can load
-// raw 24- and 32-bit bitmaps from popular image formats. The Bitmap class
-// also interprets the file format to record the correct OpenGL buffer format.
-//
-// Trying to keep this class independent from the OpenGL API in case they
-// need retargeting later on.
-
-#ifndef O3D_CORE_CROSS_BITMAP_H_
-#define O3D_CORE_CROSS_BITMAP_H_
-
-#include <stdlib.h>
-
-#include "base/cross/bits.h"
-#include "core/cross/types.h"
-#include "core/cross/texture.h"
-
-class FilePath;
-
-namespace o3d {
-
-class MemoryReadStream;
-class RawData;
-
-class Bitmap {
- public:
-
- // We will fail to load images that are bigger than 4kx4k to avoid security
- // risks. GPUs don't usually support bigger sizes anyway.
- // The biggest bitmap buffer size with these dimensions is:
- // 4k x 4k x 4xsizeof(float) x6 x4/3 (x6 for cube maps, x4/3 for mipmaps)
- // That makes 2GB, representable in an unsigned int, so we will avoid wraps.
- static const unsigned int kMaxImageDimension = 4096;
- enum ImageFileType {
- UNKNOWN,
- TGA,
- JPEG,
- PNG,
- DDS,
- };
-
- Bitmap()
- : image_data_(NULL),
- format_(Texture::UNKNOWN_FORMAT),
- width_(0),
- height_(0),
- num_mipmaps_(0),
- is_cubemap_(false) {}
- ~Bitmap() {}
-
- static bool CheckImageDimensions(unsigned int width, unsigned int height) {
- return width > 0 && height > 0 &&
- width <= kMaxImageDimension && height < kMaxImageDimension;
- }
-
- // Creates a copy of a bitmap, copying the pixels as well.
- // Parameters:
- // source: the source bitmap.
- void CopyDeepFrom(const Bitmap &source) {
- Allocate(source.format_, source.width_, source.height_,
- source.num_mipmaps_, source.is_cubemap_);
- memcpy(image_data(), source.image_data(), GetTotalSize());
- }
-
- // Sets the bitmap parameters from another bitmap, stealing the pixel buffer
- // from the source bitmap.
- // Parameters:
- // source: the source bitmap.
- void SetFrom(Bitmap *source) {
- image_data_.reset();
- format_ = source->format_;
- width_ = source->width_;
- height_ = source->height_;
- num_mipmaps_ = source->num_mipmaps_;
- is_cubemap_ = source->is_cubemap_;
- image_data_.swap(source->image_data_);
- }
-
- // Allocates an uninitialized bitmap with specified parameters.
- // Parameters:
- // format: the format of the pixels.
- // width: the width of the base image.
- // height: the height of the base image.
- // num_mipmaps: the number of mip-maps.
- // cube_map: true if creating a cube map.
- void Allocate(Texture::Format format,
- unsigned int width,
- unsigned int height,
- unsigned int num_mipmaps,
- bool cube_map);
-
- // Allocates a bitmap with initialized parameters.
- // data is zero-initialized
- void AllocateData() {
- image_data_.reset(new unsigned char[GetTotalSize()]);
- memset(image_data_.get(), 0, GetTotalSize());
- }
-
- // Frees the data owned by the bitmap.
- void FreeData() {
- image_data_.reset(NULL);
- }
-
- // Gets the total size of the bitmap data, counting all faces and mip levels.
- unsigned int GetTotalSize() {
- return (is_cubemap_ ? 6 : 1) *
- GetMipChainSize(width_, height_, format_, num_mipmaps_);
- }
-
- // Computes the number of bytes of a texture pixel buffer.
- static unsigned int GetBufferSize(unsigned int width,
- unsigned int height,
- Texture::Format format);
-
- // Gets the image data for a given mip-map level and cube map face.
- // Parameters:
- // level: mip level to get.
- // face: face of cube to get. This parameter is ignored if
- // this bitmap is not a cube map.
- unsigned char *GetMipData(unsigned int level,
- TextureCUBE::CubeFace face) const;
-
- unsigned char *image_data() const { return image_data_.get(); }
- Texture::Format format() const { return format_; }
- unsigned int width() const { return width_; }
- unsigned int height() const { return height_; }
- unsigned int num_mipmaps() const { return num_mipmaps_; }
- bool is_cubemap() const { return is_cubemap_; }
-
- // Returns whether or not the dimensions of the bitmap are power-of-two.
- bool IsPOT() const {
- return ((width_ & (width_ - 1)) == 0) && ((height_ & (height_ - 1)) == 0);
- }
-
- void set_format(Texture::Format format) { format_ = format; }
- void set_width(unsigned int n) { width_ = n; }
- void set_height(unsigned int n) { height_ = n; }
- void set_num_mipmaps(unsigned int n) { num_mipmaps_ = n; }
- void set_is_cubemap(bool is_cubemap) { is_cubemap_ = is_cubemap; }
-
- // Loads a bitmap from a file.
- // Parameters:
- // filename: the name of the file to load.
- // file_type: the type of file to load. If UNKNOWN, the file type will be
- // determined from the filename extension, and if it is not a
- // known extension, all the loaders will be tried.
- // generate_mipmaps: whether or not to generate all the mip-map levels.
- bool LoadFromFile(const FilePath &filepath,
- ImageFileType file_type,
- bool generate_mipmaps);
-
- // Loads a bitmap from a RawData object.
- // Parameters:
- // raw_data: contains the bitmap data in one of the known formats
- // file_type: the format of the bitmap data. If UNKNOWN, the file type
- // will be determined from the extension from raw_data's uri
- // and if it is not a known extension, all the loaders will
- // be tried.
- // generate_mipmaps: whether or not to generate all the mip-map levels.
- bool LoadFromRawData(RawData *raw_data,
- ImageFileType file_type,
- bool generate_mipmaps);
-
- // Loads a bitmap from a MemoryReadStream.
- // Parameters:
- // stream: a stream for the bitmap data in one of the known formats
- // filename: a filename (or uri) of the original bitmap data
- // (may be an empty string)
- // file_type: the format of the bitmap data. If UNKNOWN, the file type
- // will be determined from the extension of |filename|
- // and if it is not a known extension, all the loaders
- // will be tried.
- // generate_mipmaps: whether or not to generate all the mip-map levels.
- bool LoadFromStream(MemoryReadStream *stream,
- const String &filename,
- ImageFileType file_type,
- bool generate_mipmaps);
-
- bool LoadFromPNGStream(MemoryReadStream *stream,
- const String &filename,
- bool generate_mipmaps);
-
- bool LoadFromTGAStream(MemoryReadStream *stream,
- const String &filename,
- bool generate_mipmaps);
-
- bool LoadFromDDSStream(MemoryReadStream *stream,
- const String &filename,
- bool generate_mipmaps);
-
- bool LoadFromJPEGStream(MemoryReadStream *stream,
- const String &filename,
- bool generate_mipmaps);
-
- // Saves to a PNG file. The image must be of the ARGB8 format, be a 2D image
- // with no mip-maps (only the base level).
- // Parameters:
- // filename: the name of the file to into.
- // Returns:
- // true if successful.
- bool SaveToPNGFile(const char* filename);
-
- // Checks that the alpha channel for the entire bitmap is 1.0
- bool CheckAlphaIsOne() const;
-
- // Detects the type of image file based on the filename.
- static ImageFileType GetFileTypeFromFilename(const char *filename);
- // Detects the type of image file based on the mime-type.
- static ImageFileType GetFileTypeFromMimeType(const char *mime_type);
-
- // Adds filler alpha byte (0xff) after every pixel. Assumes buffer was
- // allocated with enough storage)
- // can convert RGB -> RGBA, BGR -> BGRA, etc.
- static void XYZToXYZA(unsigned char *image_data, int pixel_count);
-
- // Swaps Red and Blue components in the image.
- static void RGBAToBGRA(unsigned char *image_data, int pixel_count);
-
- // Gets the number of mip-maps required for a full chain starting at
- // width x height.
- static unsigned int GetMipMapCount(unsigned int width, unsigned int height) {
- return 1 + base::bits::Log2Floor(std::max(width, height));
- }
-
- // Gets the smallest power-of-two value that is at least as high as
- // dimension. This is the POT dimension used in ScaleUpToPOT.
- static unsigned int GetPOTSize(unsigned int dimension) {
- return 1 << base::bits::Log2Ceiling(dimension);
- }
-
- // Gets the size of the buffer containing a mip-map chain, given its base
- // width, height, format and number of mip-map levels.
- static unsigned int GetMipChainSize(unsigned int base_width,
- unsigned int base_height,
- Texture::Format format,
- unsigned int num_mipmaps);
-
- // Generates mip-map levels for a single image, using the data from the base
- // level.
- // NOTE: this doesn't work for DXTC, or floating-point images.
- //
- // Parameters:
- // base_width: the width of the base image.
- // base_height: the height of the base image.
- // format: the format of the data.
- // num_mipmaps: the number of mipmaps to generate.
- // data: the data containing the base image, and enough space for the
- // mip-maps.
- static bool GenerateMipmaps(unsigned int base_width,
- unsigned int base_height,
- Texture::Format format,
- unsigned int num_mipmaps,
- unsigned char *data);
-
- // Scales an image up to power-of-two textures, using point filtering.
- // NOTE: this doesn't work for DXTC, or floating-point images.
- //
- // Parameters:
- // width: the non-power-of-two width of the original image.
- // height: the non-power-of-two height of the original image.
- // format: the format of the data.
- // src: the data containing the source data of the original image.
- // dst: a buffer with enough space for the power-of-two version. Pixels are
- // written from the end to the beginning so dst can be the same buffer as
- // src.
- static bool ScaleUpToPOT(unsigned int width,
- unsigned int height,
- Texture::Format format,
- const unsigned char *src,
- unsigned char *dst);
-
- // Scales an image to an arbitrary size, using point filtering.
- // NOTE: this doesn't work for DXTC, or floating-point images.
- //
- // Parameters:
- // src_width: the width of the original image.
- // src_height: the height of the original image.
- // format: the format of the data.
- // src: the data containing the source data of the original image.
- // dst_width: the width of the target image.
- // dst_height: the height of the target image.
- // dst: a buffer with enough space for the target version. Pixels are
- // written from the end to the beginning so dst can be the same buffer as
- // src if the transformation is an upscaling.
- static bool Scale(unsigned int src_width,
- unsigned int src_height,
- Texture::Format format,
- const unsigned char *src,
- unsigned int dst_width,
- unsigned int dst_height,
- unsigned char *dst);
- private:
- // pointer to the raw bitmap data
- scoped_array<uint8> image_data_;
- // format of the texture this is meant to represent.
- Texture::Format format_;
- // width of the bitmap in pixels.
- unsigned int width_;
- // height of the bitmap in pixels.
- unsigned int height_;
- // number of mipmap levels in this texture.
- unsigned int num_mipmaps_;
- // is this cube-map data
- bool is_cubemap_;
-
- DISALLOW_COPY_AND_ASSIGN(Bitmap);
-};
-
-} // namespace o3d
-
-#endif // O3D_CORE_CROSS_BITMAP_H_
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the declaration of Bitmap helper class that can load
+// raw 24- and 32-bit bitmaps from popular image formats. The Bitmap class
+// also interprets the file format to record the correct OpenGL buffer format.
+//
+// Trying to keep this class independent from the OpenGL API in case they
+// need retargeting later on.
+
+#ifndef O3D_CORE_CROSS_BITMAP_H_
+#define O3D_CORE_CROSS_BITMAP_H_
+
+#include <stdlib.h>
+
+#include "base/cross/bits.h"
+#include "core/cross/types.h"
+#include "core/cross/texture.h"
+
+class FilePath;
+
+namespace o3d {
+
+class MemoryReadStream;
+class RawData;
+class Pack;
+
+// Bitmap provides an API for basic image operations on bitmap images,
+// including scale and crop. The contents of bitmap can be created from
+// a RawData object via LoadFromRawData(), and also can be transfered
+// to mip of a Texure2D or a specific face of TextureCUBE via methods
+// in Texture.
+
+class Bitmap : public ParamObject {
+ public:
+ typedef SmartPointer<Bitmap> Ref;
+
+ explicit Bitmap(ServiceLocator* service_locator);
+ virtual ~Bitmap() {}
+
+ // We will fail to load images that are bigger than 4kx4k to avoid security
+ // risks. GPUs don't usually support bigger sizes anyway.
+ // The biggest bitmap buffer size with these dimensions is:
+ // 4k x 4k x 4xsizeof(float) x6 x4/3 (x6 for cube maps, x4/3 for mipmaps)
+ // That makes 2GB, representable in an unsigned int, so we will avoid wraps.
+ static const unsigned int kMaxImageDimension = 4096;
+ enum ImageFileType {
+ UNKNOWN,
+ TGA,
+ JPEG,
+ PNG,
+ DDS,
+ };
+
+ static bool CheckImageDimensions(unsigned int width, unsigned int height) {
+ return width > 0 && height > 0 &&
+ width <= kMaxImageDimension && height < kMaxImageDimension;
+ }
+
+ // Creates a copy of a bitmap, copying the pixels as well.
+ // Parameters:
+ // source: the source bitmap.
+ void CopyDeepFrom(const Bitmap &source) {
+ Allocate(source.format_, source.width_, source.height_,
+ source.num_mipmaps_, source.is_cubemap_);
+ memcpy(image_data(), source.image_data(), GetTotalSize());
+ }
+
+ // Sets the bitmap parameters from another bitmap, stealing the pixel buffer
+ // from the source bitmap.
+ // Parameters:
+ // source: the source bitmap.
+ void SetFrom(Bitmap *source) {
+ image_data_.reset();
+ format_ = source->format_;
+ width_ = source->width_;
+ height_ = source->height_;
+ num_mipmaps_ = source->num_mipmaps_;
+ is_cubemap_ = source->is_cubemap_;
+ image_data_.swap(source->image_data_);
+ }
+
+ // Allocates an uninitialized bitmap with specified parameters.
+ // Parameters:
+ // format: the format of the pixels.
+ // width: the width of the base image.
+ // height: the height of the base image.
+ // num_mipmaps: the number of mip-maps.
+ // cube_map: true if creating a cube map.
+ void Allocate(Texture::Format format,
+ unsigned int width,
+ unsigned int height,
+ unsigned int num_mipmaps,
+ bool cube_map);
+
+ // Allocates a bitmap with initialized parameters.
+ // data is zero-initialized
+ void AllocateData() {
+ image_data_.reset(new unsigned char[GetTotalSize()]);
+ memset(image_data_.get(), 0, GetTotalSize());
+ }
+
+ // Frees the data owned by the bitmap.
+ void FreeData() {
+ image_data_.reset(NULL);
+ }
+
+ // Gets the total size of the bitmap data, counting all faces and mip levels.
+ unsigned int GetTotalSize() {
+ return (is_cubemap_ ? 6 : 1) *
+ GetMipChainSize(width_, height_, format_, num_mipmaps_);
+ }
+
+ // Computes the number of bytes of a texture pixel buffer.
+ static unsigned int GetBufferSize(unsigned int width,
+ unsigned int height,
+ Texture::Format format);
+
+ // Gets the image data for a given mip-map level and cube map face.
+ // Parameters:
+ // level: mip level to get.
+ // face: face of cube to get. This parameter is ignored if
+ // this bitmap is not a cube map.
+ unsigned char *GetMipData(unsigned int level,
+ TextureCUBE::CubeFace face) const;
+
+ unsigned char *image_data() const { return image_data_.get(); }
+ Texture::Format format() const { return format_; }
+ unsigned int width() const { return width_; }
+ unsigned int height() const { return height_; }
+ unsigned int num_mipmaps() const { return num_mipmaps_; }
+ bool is_cubemap() const { return is_cubemap_; }
+
+ // Returns whether or not the dimensions of the bitmap are power-of-two.
+ bool IsPOT() const {
+ return ((width_ & (width_ - 1)) == 0) && ((height_ & (height_ - 1)) == 0);
+ }
+
+ void set_format(Texture::Format format) { format_ = format; }
+ void set_width(unsigned int n) { width_ = n; }
+ void set_height(unsigned int n) { height_ = n; }
+ void set_num_mipmaps(unsigned int n) { num_mipmaps_ = n; }
+ void set_is_cubemap(bool is_cubemap) { is_cubemap_ = is_cubemap; }
+
+ // Loads a bitmap from a file.
+ // Parameters:
+ // filename: the name of the file to load.
+ // file_type: the type of file to load. If UNKNOWN, the file type will be
+ // determined from the filename extension, and if it is not a
+ // known extension, all the loaders will be tried.
+ // generate_mipmaps: whether or not to generate all the mip-map levels.
+ bool LoadFromFile(const FilePath &filepath,
+ ImageFileType file_type,
+ bool generate_mipmaps);
+
+ // Loads a bitmap from a RawData object.
+ // Parameters:
+ // raw_data: contains the bitmap data in one of the known formats
+ // file_type: the format of the bitmap data. If UNKNOWN, the file type
+ // will be determined from the extension from raw_data's uri
+ // and if it is not a known extension, all the loaders will
+ // be tried.
+ // generate_mipmaps: whether or not to generate all the mip-map levels.
+ bool LoadFromRawData(RawData *raw_data,
+ ImageFileType file_type,
+ bool generate_mipmaps);
+
+ // Loads a bitmap from a MemoryReadStream.
+ // Parameters:
+ // stream: a stream for the bitmap data in one of the known formats
+ // filename: a filename (or uri) of the original bitmap data
+ // (may be an empty string)
+ // file_type: the format of the bitmap data. If UNKNOWN, the file type
+ // will be determined from the extension of |filename|
+ // and if it is not a known extension, all the loaders
+ // will be tried.
+ // generate_mipmaps: whether or not to generate all the mip-map levels.
+ bool LoadFromStream(MemoryReadStream *stream,
+ const String &filename,
+ ImageFileType file_type,
+ bool generate_mipmaps);
+
+ bool LoadFromPNGStream(MemoryReadStream *stream,
+ const String &filename,
+ bool generate_mipmaps);
+
+ bool LoadFromTGAStream(MemoryReadStream *stream,
+ const String &filename,
+ bool generate_mipmaps);
+
+ bool LoadFromDDSStream(MemoryReadStream *stream,
+ const String &filename,
+ bool generate_mipmaps);
+
+ bool LoadFromJPEGStream(MemoryReadStream *stream,
+ const String &filename,
+ bool generate_mipmaps);
+
+ // Saves to a PNG file. The image must be of the ARGB8 format, be a 2D image
+ // with no mip-maps (only the base level).
+ // Parameters:
+ // filename: the name of the file to into.
+ // Returns:
+ // true if successful.
+ bool SaveToPNGFile(const char* filename);
+
+ // Checks that the alpha channel for the entire bitmap is 1.0
+ bool CheckAlphaIsOne() const;
+
+ // Copy pixels from source bitmap. Scales if the width and height of source
+ // and dest do not match.
+ // Parameters:
+ // source_img: source bitmap which would be drawn.
+ // source_x: x-coordinate of the starting pixel in the source image.
+ // source_x: y-coordinate of the starting pixel in the source image.
+ // source_width: width of the source image to draw.
+ // source_height: Height of the source image to draw.
+ // dest_x: x-coordinate of the starting pixel in the dest image.
+ // dest_y: y-coordinate of the starting pixel in the dest image.
+ // dest_width: width of the dest image to draw.
+ // dest_height: height of the dest image to draw.
+ void DrawImage(Bitmap* source_img, int source_x, int source_y,
+ int source_width, int source_height,
+ int dest_x, int dest_y,
+ int dest_width, int dest_height);
+
+ // Crop part of an image from src, scale it to an arbitrary size
+ // and paste in dest image. Utility function for all DrawImage
+ // function in bitmap and textures. Scale operation is based on
+ // bilinear interpolation.
+ // Note: this doesn't work for DXTC, or floating-point images.
+ //
+ // Parameters:
+ // src: source image which would be copied from.
+ // src_x: x-coordinate of the starting pixel in the src image.
+ // src_y: y-coordinate of the starting pixel in the src image.
+ // src_width: width of the part in src image to be croped.
+ // src_height: height of the part in src image to be croped.
+ // src_img_width: width of the src image.
+ // src_img_height: height of the src image.
+ // dest: dest image which would be copied to.
+ // dest_x: x-coordinate of the starting pixel in the dest image.
+ // dest_y: y-coordinate of the starting pixel in the dest image.
+ // dest_width: width of the part in dest image to be pasted to.
+ // dest_height: height of the part in dest image to be pasted to.
+ // dest_img_width: width of the dest image.
+ // dest_img_height: height of the src image.
+ // component: size of each pixel in terms of array element.
+ // Returns:
+ // true if crop and scale succeeds.
+ static void BilinearInterpolateScale(const uint8* src,
+ int src_x, int src_y,
+ int src_width, int src_height,
+ int src_img_width, int src_img_height,
+ uint8* dest,
+ int dest_x, int dest_y,
+ int dest_width, int dest_height,
+ int dest_img_width, int dest_img_height,
+ int component);
+
+ // Detects the type of image file based on the filename.
+ static ImageFileType GetFileTypeFromFilename(const char *filename);
+ // Detects the type of image file based on the mime-type.
+ static ImageFileType GetFileTypeFromMimeType(const char *mime_type);
+
+ // Adds filler alpha byte (0xff) after every pixel. Assumes buffer was
+ // allocated with enough storage)
+ // can convert RGB -> RGBA, BGR -> BGRA, etc.
+ static void XYZToXYZA(unsigned char *image_data, int pixel_count);
+
+ // Swaps Red and Blue components in the image.
+ static void RGBAToBGRA(unsigned char *image_data, int pixel_count);
+
+ // Gets the number of mip-maps required for a full chain starting at
+ // width x height.
+ static unsigned int GetMipMapCount(unsigned int width, unsigned int height) {
+ return 1 + base::bits::Log2Floor(std::max(width, height));
+ }
+
+ // Gets the smallest power-of-two value that is at least as high as
+ // dimension. This is the POT dimension used in ScaleUpToPOT.
+ static unsigned int GetPOTSize(unsigned int dimension) {
+ return 1 << base::bits::Log2Ceiling(dimension);
+ }
+
+ // Gets the size of the buffer containing a mip-map chain, given its base
+ // width, height, format and number of mip-map levels.
+ static unsigned int GetMipChainSize(unsigned int base_width,
+ unsigned int base_height,
+ Texture::Format format,
+ unsigned int num_mipmaps);
+
+ // Generates mip-map levels for a single image, using the data from the base
+ // level.
+ // NOTE: this doesn't work for DXTC, or floating-point images.
+ //
+ // Parameters:
+ // base_width: the width of the base image.
+ // base_height: the height of the base image.
+ // format: the format of the data.
+ // num_mipmaps: the number of mipmaps to generate.
+ // data: the data containing the base image, and enough space for the
+ // mip-maps.
+ static bool GenerateMipmaps(unsigned int base_width,
+ unsigned int base_height,
+ Texture::Format format,
+ unsigned int num_mipmaps,
+ unsigned char *data);
+
+ // Scales an image up to power-of-two textures, using point filtering.
+ // NOTE: this doesn't work for DXTC, or floating-point images.
+ //
+ // Parameters:
+ // width: the non-power-of-two width of the original image.
+ // height: the non-power-of-two height of the original image.
+ // format: the format of the data.
+ // src: the data containing the source data of the original image.
+ // dst: a buffer with enough space for the power-of-two version. Pixels are
+ // written from the end to the beginning so dst can be the same buffer as
+ // src.
+ static bool ScaleUpToPOT(unsigned int width,
+ unsigned int height,
+ Texture::Format format,
+ const unsigned char *src,
+ unsigned char *dst);
+
+ // Scales an image to an arbitrary size, using point filtering.
+ // NOTE: this doesn't work for DXTC, or floating-point images.
+ //
+ // Parameters:
+ // src_width: the width of the original image.
+ // src_height: the height of the original image.
+ // format: the format of the data.
+ // src: the data containing the source data of the original image.
+ // dst_width: the width of the target image.
+ // dst_height: the height of the target image.
+ // dst: a buffer with enough space for the target version. Pixels are
+ // written from the end to the beginning so dst can be the same buffer as
+ // src if the transformation is an upscaling.
+ static bool Scale(unsigned int src_width,
+ unsigned int src_height,
+ Texture::Format format,
+ const unsigned char *src,
+ unsigned int dst_width,
+ unsigned int dst_height,
+ unsigned char *dst);
+
+ // adjust start points and boundaries when using DrawImage data
+ // in bitmap and textures.
+ // Parameters:
+ // src_x: x-coordinate of the starting pixel in the source image.
+ // src_y: y-coordinate of the starting pixel in the source image.
+ // src_width: width of the source image to draw.
+ // src_height: height of the source image to draw.
+ // src_bmp_width: original width of source bitmap.
+ // src_bmp_height: original height of source bitmap.
+ // dest_x: x-coordinate of the starting pixel in the dest image.
+ // dest_y: y-coordinate of the starting pixel in the dest image.
+ // dest_width: width of the dest image to draw.
+ // dest_height: height of the dest image to draw.
+ // dest_bmp_width: original width of dest bitmap.
+ // dest_bmp_height: original height of dest bitmap.
+ // Returns:
+ // false if src or dest rectangle is out of boundaries.
+ static bool AdjustDrawImageBoundary(int* src_x, int* src_y,
+ int* src_width, int* src_height,
+ int src_bmp_width, int src_bmp_height,
+ int* dest_x, int* dest_y,
+ int* dest_width, int* dest_height,
+ int dest_bmp_width, int dest_bmp_height);
+
+ private:
+ friend class IClassManager;
+ static ObjectBase::Ref Create(ServiceLocator* service_locator);
+
+ // pointer to the raw bitmap data
+ scoped_array<uint8> image_data_;
+ // format of the texture this is meant to represent.
+ Texture::Format format_;
+ // width of the bitmap in pixels.
+ unsigned int width_;
+ // height of the bitmap in pixels.
+ unsigned int height_;
+ // number of mipmap levels in this texture.
+ unsigned int num_mipmaps_;
+ // is this cube-map data
+ bool is_cubemap_;
+
+ // utility function used in AdjustDrawImageBoundary.
+ // It adjusts start point and related measures
+ // for a specific dimension.
+ // Parameter:
+ // src_a: the coordinate which is negative.
+ // dest_a: same coordinate in the other image.
+ // src_length: length measure of source image to draw.
+ // dest_length: length measure of dest image to draw.
+ // src_bmp_length: length measure of src image.
+ // Returns:
+ // true if adjust is successful.
+ static bool AdjustDrawImageBoundHelper(int* src_a, int* dest_a,
+ int* src_length, int* dest_length,
+ int src_bmp_length);
+
+ O3D_DECL_CLASS(Bitmap, ParamObject);
+ DISALLOW_COPY_AND_ASSIGN(Bitmap);
+};
+
+} // namespace o3d
+
+#endif // O3D_CORE_CROSS_BITMAP_H_
diff --git a/o3d/core/cross/bitmap_test.cc b/o3d/core/cross/bitmap_test.cc
index 0c3766d..1d832ef 100644
--- a/o3d/core/cross/bitmap_test.cc
+++ b/o3d/core/cross/bitmap_test.cc
@@ -358,30 +358,30 @@ TEST_F(BitmapTest, LoadTGAFile24bit) {
// Load the texture object from a file.
String filename = *g_program_path + "/bitmap_test/tga-256x256-24bit.tga";
FilePath filepath = UTF8ToFilePath(filename);
- Bitmap bitmap;
- EXPECT_TRUE(bitmap.LoadFromFile(filepath, Bitmap::TGA, false));
- EXPECT_TRUE(bitmap.image_data() != NULL);
- EXPECT_FALSE(bitmap.is_cubemap());
- EXPECT_EQ(Texture::XRGB8, bitmap.format());
- EXPECT_EQ(256, bitmap.width());
- EXPECT_EQ(256, bitmap.height());
- EXPECT_EQ(1, bitmap.num_mipmaps());
- EXPECT_TRUE(TestBitmapData(bitmap, ktga256x256_24bit_BGRX));
+ Bitmap::Ref bitmap(new Bitmap(g_service_locator));
+ EXPECT_TRUE(bitmap->LoadFromFile(filepath, Bitmap::TGA, false));
+ EXPECT_TRUE(bitmap->image_data() != NULL);
+ EXPECT_FALSE(bitmap->is_cubemap());
+ EXPECT_EQ(Texture::XRGB8, bitmap->format());
+ EXPECT_EQ(256, bitmap->width());
+ EXPECT_EQ(256, bitmap->height());
+ EXPECT_EQ(1, bitmap->num_mipmaps());
+ EXPECT_TRUE(TestBitmapData(*bitmap, ktga256x256_24bit_BGRX));
}
// Loads a 32 bit TGA file, checks it against the known data.
TEST_F(BitmapTest, LoadTGAFile32bit) {
String filename = *g_program_path + "/bitmap_test/tga-256x256-32bit.tga";
FilePath filepath = UTF8ToFilePath(filename);
- Bitmap bitmap;
- EXPECT_TRUE(bitmap.LoadFromFile(filepath, Bitmap::TGA, false));
- EXPECT_TRUE(bitmap.image_data() != NULL);
- EXPECT_FALSE(bitmap.is_cubemap());
- EXPECT_EQ(Texture::ARGB8, bitmap.format());
- EXPECT_EQ(256, bitmap.width());
- EXPECT_EQ(256, bitmap.height());
- EXPECT_EQ(1, bitmap.num_mipmaps());
- EXPECT_TRUE(TestBitmapData(bitmap, ktga256x256_32bit_BGRA));
+ Bitmap::Ref bitmap(new Bitmap(g_service_locator));
+ EXPECT_TRUE(bitmap->LoadFromFile(filepath, Bitmap::TGA, false));
+ EXPECT_TRUE(bitmap->image_data() != NULL);
+ EXPECT_FALSE(bitmap->is_cubemap());
+ EXPECT_EQ(Texture::ARGB8, bitmap->format());
+ EXPECT_EQ(256, bitmap->width());
+ EXPECT_EQ(256, bitmap->height());
+ EXPECT_EQ(1, bitmap->num_mipmaps());
+ EXPECT_TRUE(TestBitmapData(*bitmap, ktga256x256_32bit_BGRA));
}
// Tries to load a 5kx5k TGA file, which should fail.
@@ -391,48 +391,48 @@ TEST_F(BitmapTest, LoadTGAFileTooLarge) {
// but bails before reading the actual image bytes.
String filename = *g_program_path + "/bitmap_test/5kx5k.tga";
FilePath filepath = UTF8ToFilePath(filename);
- Bitmap bitmap;
- EXPECT_FALSE(bitmap.LoadFromFile(filepath, Bitmap::TGA, false));
- EXPECT_TRUE(bitmap.image_data() == NULL);
+ Bitmap::Ref bitmap(new Bitmap(g_service_locator));
+ EXPECT_FALSE(bitmap->LoadFromFile(filepath, Bitmap::TGA, false));
+ EXPECT_TRUE(bitmap->image_data() == NULL);
}
// Loads a JPEG file, checks it against the known data.
TEST_F(BitmapTest, LoadJPEGFile) {
String filename = *g_program_path + "/bitmap_test/jpeg-256x256.jpg";
FilePath filepath = UTF8ToFilePath(filename);
- Bitmap bitmap;
- EXPECT_TRUE(bitmap.LoadFromFile(filepath, Bitmap::JPEG, false));
- EXPECT_TRUE(bitmap.image_data() != NULL);
- EXPECT_FALSE(bitmap.is_cubemap());
- EXPECT_EQ(Texture::XRGB8, bitmap.format());
- EXPECT_EQ(256, bitmap.width());
- EXPECT_EQ(256, bitmap.height());
- EXPECT_EQ(1, bitmap.num_mipmaps());
- EXPECT_TRUE(TestBitmapData(bitmap, kjpg256x256_BGRX));
+ Bitmap::Ref bitmap(new Bitmap(g_service_locator));
+ EXPECT_TRUE(bitmap->LoadFromFile(filepath, Bitmap::JPEG, false));
+ EXPECT_TRUE(bitmap->image_data() != NULL);
+ EXPECT_FALSE(bitmap->is_cubemap());
+ EXPECT_EQ(Texture::XRGB8, bitmap->format());
+ EXPECT_EQ(256, bitmap->width());
+ EXPECT_EQ(256, bitmap->height());
+ EXPECT_EQ(1, bitmap->num_mipmaps());
+ EXPECT_TRUE(TestBitmapData(*bitmap, kjpg256x256_BGRX));
}
// Tries to load a 5kx5k JPEG file, which should fail.
TEST_F(BitmapTest, LoadJPEGFileTooLarge) {
String filename = *g_program_path + "/bitmap_test/5kx5k.jpg";
FilePath filepath = UTF8ToFilePath(filename);
- Bitmap bitmap;
- EXPECT_FALSE(bitmap.LoadFromFile(filepath, Bitmap::JPEG, false));
- EXPECT_TRUE(bitmap.image_data() == NULL);
+ Bitmap::Ref bitmap(new Bitmap(g_service_locator));
+ EXPECT_FALSE(bitmap->LoadFromFile(filepath, Bitmap::JPEG, false));
+ EXPECT_TRUE(bitmap->image_data() == NULL);
}
// Loads a 24 bit PNG file, checks it against the known data.
TEST_F(BitmapTest, LoadPNGFile24bit) {
String filename = *g_program_path + "/bitmap_test/png-256x256-24bit.png";
FilePath filepath = UTF8ToFilePath(filename);
- Bitmap bitmap;
- EXPECT_TRUE(bitmap.LoadFromFile(filepath, Bitmap::PNG, false));
- EXPECT_TRUE(bitmap.image_data() != NULL);
- EXPECT_FALSE(bitmap.is_cubemap());
- EXPECT_EQ(Texture::XRGB8, bitmap.format());
- EXPECT_EQ(256, bitmap.width());
- EXPECT_EQ(256, bitmap.height());
- EXPECT_EQ(1, bitmap.num_mipmaps());
- EXPECT_TRUE(TestBitmapData(bitmap, kpng256x256_24bit_BGRX));
+ Bitmap::Ref bitmap(new Bitmap(g_service_locator));
+ EXPECT_TRUE(bitmap->LoadFromFile(filepath, Bitmap::PNG, false));
+ EXPECT_TRUE(bitmap->image_data() != NULL);
+ EXPECT_FALSE(bitmap->is_cubemap());
+ EXPECT_EQ(Texture::XRGB8, bitmap->format());
+ EXPECT_EQ(256, bitmap->width());
+ EXPECT_EQ(256, bitmap->height());
+ EXPECT_EQ(1, bitmap->num_mipmaps());
+ EXPECT_TRUE(TestBitmapData(*bitmap, kpng256x256_24bit_BGRX));
}
// Loads a 24 bit interlaced PNG file, checks it against the known data.
@@ -440,29 +440,29 @@ TEST_F(BitmapTest, LoadPNGFile24bitInterlaced) {
String filename = *g_program_path +
"/bitmap_test/png-256x256-24bit-interlaced.png";
FilePath filepath = UTF8ToFilePath(filename);
- Bitmap bitmap;
- EXPECT_TRUE(bitmap.LoadFromFile(filepath, Bitmap::PNG, false));
- EXPECT_TRUE(bitmap.image_data() != NULL);
- EXPECT_FALSE(bitmap.is_cubemap());
- EXPECT_EQ(Texture::XRGB8, bitmap.format());
- EXPECT_EQ(256, bitmap.width());
- EXPECT_EQ(256, bitmap.height());
- EXPECT_EQ(1, bitmap.num_mipmaps());
- EXPECT_TRUE(TestBitmapData(bitmap, kpng256x256_24bit_interlaced_BGRX));
+ Bitmap::Ref bitmap(new Bitmap(g_service_locator));
+ EXPECT_TRUE(bitmap->LoadFromFile(filepath, Bitmap::PNG, false));
+ EXPECT_TRUE(bitmap->image_data() != NULL);
+ EXPECT_FALSE(bitmap->is_cubemap());
+ EXPECT_EQ(Texture::XRGB8, bitmap->format());
+ EXPECT_EQ(256, bitmap->width());
+ EXPECT_EQ(256, bitmap->height());
+ EXPECT_EQ(1, bitmap->num_mipmaps());
+ EXPECT_TRUE(TestBitmapData(*bitmap, kpng256x256_24bit_interlaced_BGRX));
}
TEST_F(BitmapTest, LoadPNGFile32bit) {
String filename = *g_program_path + "/bitmap_test/png-256x256-32bit.png";
FilePath filepath = UTF8ToFilePath(filename);
- Bitmap bitmap;
- EXPECT_TRUE(bitmap.LoadFromFile(filepath, Bitmap::PNG, false));
- EXPECT_TRUE(bitmap.image_data() != NULL);
- EXPECT_FALSE(bitmap.is_cubemap());
- EXPECT_EQ(Texture::ARGB8, bitmap.format());
- EXPECT_EQ(256, bitmap.width());
- EXPECT_EQ(256, bitmap.height());
- EXPECT_EQ(1, bitmap.num_mipmaps());
- EXPECT_TRUE(TestBitmapData(bitmap, kpng256x256_32bit_BGRA));
+ Bitmap::Ref bitmap(new Bitmap(g_service_locator));
+ EXPECT_TRUE(bitmap->LoadFromFile(filepath, Bitmap::PNG, false));
+ EXPECT_TRUE(bitmap->image_data() != NULL);
+ EXPECT_FALSE(bitmap->is_cubemap());
+ EXPECT_EQ(Texture::ARGB8, bitmap->format());
+ EXPECT_EQ(256, bitmap->width());
+ EXPECT_EQ(256, bitmap->height());
+ EXPECT_EQ(1, bitmap->num_mipmaps());
+ EXPECT_TRUE(TestBitmapData(*bitmap, kpng256x256_32bit_BGRA));
}
// Loads a palettized PNG file, checks it against the known data.
@@ -470,15 +470,15 @@ TEST_F(BitmapTest, LoadPNGFile8bitPalette) {
String filename = *g_program_path +
"/bitmap_test/png-256x256-8bit-palette.png";
FilePath filepath = UTF8ToFilePath(filename);
- Bitmap bitmap;
- EXPECT_TRUE(bitmap.LoadFromFile(filepath, Bitmap::PNG, false));
- EXPECT_TRUE(bitmap.image_data() != NULL);
- EXPECT_FALSE(bitmap.is_cubemap());
- EXPECT_EQ(Texture::XRGB8, bitmap.format());
- EXPECT_EQ(256, bitmap.width());
- EXPECT_EQ(256, bitmap.height());
- EXPECT_EQ(1, bitmap.num_mipmaps());
- EXPECT_TRUE(TestBitmapData(bitmap, kpng256x256_8bit_palette_BGRX));
+ Bitmap::Ref bitmap(new Bitmap(g_service_locator));
+ EXPECT_TRUE(bitmap->LoadFromFile(filepath, Bitmap::PNG, false));
+ EXPECT_TRUE(bitmap->image_data() != NULL);
+ EXPECT_FALSE(bitmap->is_cubemap());
+ EXPECT_EQ(Texture::XRGB8, bitmap->format());
+ EXPECT_EQ(256, bitmap->width());
+ EXPECT_EQ(256, bitmap->height());
+ EXPECT_EQ(1, bitmap->num_mipmaps());
+ EXPECT_TRUE(TestBitmapData(*bitmap, kpng256x256_8bit_palette_BGRX));
}
// Loads a palettized PNG file, checks it against the known data.
@@ -486,15 +486,15 @@ TEST_F(BitmapTest, LoadPNGFile4bitPalette) {
String filename = *g_program_path +
"/bitmap_test/png-20x14-4bit-palette.png";
FilePath filepath = UTF8ToFilePath(filename);
- Bitmap bitmap;
- EXPECT_TRUE(bitmap.LoadFromFile(filepath, Bitmap::PNG, false));
- EXPECT_TRUE(bitmap.image_data() != NULL);
- EXPECT_FALSE(bitmap.is_cubemap());
- EXPECT_EQ(Texture::XRGB8, bitmap.format());
- EXPECT_EQ(20, bitmap.width());
- EXPECT_EQ(14, bitmap.height());
- EXPECT_EQ(1, bitmap.num_mipmaps());
- EXPECT_TRUE(TestBitmapData(bitmap, kpng20x14_4bit_palette_BGRX));
+ Bitmap::Ref bitmap(new Bitmap(g_service_locator));
+ EXPECT_TRUE(bitmap->LoadFromFile(filepath, Bitmap::PNG, false));
+ EXPECT_TRUE(bitmap->image_data() != NULL);
+ EXPECT_FALSE(bitmap->is_cubemap());
+ EXPECT_EQ(Texture::XRGB8, bitmap->format());
+ EXPECT_EQ(20, bitmap->width());
+ EXPECT_EQ(14, bitmap->height());
+ EXPECT_EQ(1, bitmap->num_mipmaps());
+ EXPECT_TRUE(TestBitmapData(*bitmap, kpng20x14_4bit_palette_BGRX));
}
@@ -502,9 +502,9 @@ TEST_F(BitmapTest, LoadPNGFile4bitPalette) {
TEST_F(BitmapTest, LoadPNGFileTooLarge) {
String filename = *g_program_path + "/bitmap_test/5kx5k.png";
FilePath filepath = UTF8ToFilePath(filename);
- Bitmap bitmap;
- EXPECT_FALSE(bitmap.LoadFromFile(filepath, Bitmap::PNG, false));
- EXPECT_TRUE(bitmap.image_data() == NULL);
+ Bitmap::Ref bitmap(new Bitmap(g_service_locator));
+ EXPECT_FALSE(bitmap->LoadFromFile(filepath, Bitmap::PNG, false));
+ EXPECT_TRUE(bitmap->image_data() == NULL);
}
// NOTE: Having trouble recognising the alpha channel in a PNG
@@ -514,14 +514,14 @@ TEST_F(BitmapTest, LoadPNGFile8bitPaletteAlpha) {
String filename = *g_program_path +
"/bitmap_test/png-256x256-8bit-palette-alpha.png";
FilePath filepath = UTF8ToFilePath(filename);
- Bitmap bitmap;
- EXPECT_TRUE(bitmap.LoadFromFile(filepath, Bitmap::PNG, false));
- EXPECT_TRUE(bitmap.image_data() != NULL);
- EXPECT_FALSE(bitmap.is_cubemap());
- EXPECT_EQ(Texture::ARGB8, bitmap.format());
- EXPECT_EQ(256, bitmap.width());
- EXPECT_EQ(256, bitmap.height());
- EXPECT_EQ(1, bitmap.num_mipmaps());
+ Bitmap::Ref bitmap(new Bitmap(g_service_locator));
+ EXPECT_TRUE(bitmap->LoadFromFile(filepath, Bitmap::PNG, false));
+ EXPECT_TRUE(bitmap->image_data() != NULL);
+ EXPECT_FALSE(bitmap->is_cubemap());
+ EXPECT_EQ(Texture::ARGB8, bitmap->format());
+ EXPECT_EQ(256, bitmap->width());
+ EXPECT_EQ(256, bitmap->height());
+ EXPECT_EQ(1, bitmap->num_mipmaps());
}
*/
@@ -529,15 +529,15 @@ TEST_F(BitmapTest, LoadPNGFile8bitPaletteAlpha) {
TEST_F(BitmapTest, LoadDDSFileDXT1) {
String filename = *g_program_path + "/bitmap_test/dds-dxt1-256x256.dds";
FilePath filepath = UTF8ToFilePath(filename);
- Bitmap bitmap;
- EXPECT_TRUE(bitmap.LoadFromFile(filepath, Bitmap::DDS, false));
- EXPECT_TRUE(bitmap.image_data() != NULL);
- EXPECT_FALSE(bitmap.is_cubemap());
- EXPECT_EQ(Texture::DXT1, bitmap.format());
- EXPECT_EQ(256, bitmap.width());
- EXPECT_EQ(256, bitmap.height());
- EXPECT_EQ(1, bitmap.num_mipmaps());
- EXPECT_TRUE(TestBitmapData(bitmap, kdxt1_256x256));
+ Bitmap::Ref bitmap(new Bitmap(g_service_locator));
+ EXPECT_TRUE(bitmap->LoadFromFile(filepath, Bitmap::DDS, false));
+ EXPECT_TRUE(bitmap->image_data() != NULL);
+ EXPECT_FALSE(bitmap->is_cubemap());
+ EXPECT_EQ(Texture::DXT1, bitmap->format());
+ EXPECT_EQ(256, bitmap->width());
+ EXPECT_EQ(256, bitmap->height());
+ EXPECT_EQ(1, bitmap->num_mipmaps());
+ EXPECT_TRUE(TestBitmapData(*bitmap, kdxt1_256x256));
}
// Loads a DXT1 DDS file with alpha, checks the format.
@@ -545,15 +545,15 @@ TEST_F(BitmapTest, LoadDDSFileDXT1Alpha) {
String filename = *g_program_path +
"/bitmap_test/dds-dxt1-256x256-alpha.dds";
FilePath filepath = UTF8ToFilePath(filename);
- Bitmap bitmap;
- EXPECT_TRUE(bitmap.LoadFromFile(filepath, Bitmap::DDS, false));
- EXPECT_TRUE(bitmap.image_data() != NULL);
- EXPECT_FALSE(bitmap.is_cubemap());
- EXPECT_EQ(Texture::DXT1, bitmap.format());
- EXPECT_EQ(256, bitmap.width());
- EXPECT_EQ(256, bitmap.height());
- EXPECT_EQ(1, bitmap.num_mipmaps());
- EXPECT_TRUE(TestBitmapData(bitmap, kdxt1_256x256_alpha));
+ Bitmap::Ref bitmap(new Bitmap(g_service_locator));
+ EXPECT_TRUE(bitmap->LoadFromFile(filepath, Bitmap::DDS, false));
+ EXPECT_TRUE(bitmap->image_data() != NULL);
+ EXPECT_FALSE(bitmap->is_cubemap());
+ EXPECT_EQ(Texture::DXT1, bitmap->format());
+ EXPECT_EQ(256, bitmap->width());
+ EXPECT_EQ(256, bitmap->height());
+ EXPECT_EQ(1, bitmap->num_mipmaps());
+ EXPECT_TRUE(TestBitmapData(*bitmap, kdxt1_256x256_alpha));
}
// Loads a DXT1 DDS file with mipmaps, checks the format.
@@ -561,18 +561,18 @@ TEST_F(BitmapTest, LoadDDSFileDXT1Mipmap) {
String filename = *g_program_path +
"/bitmap_test/dds-dxt1-256x256-mipmap.dds";
FilePath filepath = UTF8ToFilePath(filename);
- Bitmap bitmap;
- EXPECT_TRUE(bitmap.LoadFromFile(filepath, Bitmap::DDS, false));
- EXPECT_TRUE(bitmap.image_data() != NULL);
- EXPECT_FALSE(bitmap.is_cubemap());
- EXPECT_EQ(Texture::DXT1, bitmap.format());
- EXPECT_EQ(256, bitmap.width());
- EXPECT_EQ(256, bitmap.height());
- EXPECT_EQ(9, bitmap.num_mipmaps());
- for (unsigned int i = 0; i < bitmap.num_mipmaps(); ++i) {
- EXPECT_TRUE(bitmap.GetMipData(i, TextureCUBE::FACE_POSITIVE_X) != NULL);
+ Bitmap::Ref bitmap(new Bitmap(g_service_locator));
+ EXPECT_TRUE(bitmap->LoadFromFile(filepath, Bitmap::DDS, false));
+ EXPECT_TRUE(bitmap->image_data() != NULL);
+ EXPECT_FALSE(bitmap->is_cubemap());
+ EXPECT_EQ(Texture::DXT1, bitmap->format());
+ EXPECT_EQ(256, bitmap->width());
+ EXPECT_EQ(256, bitmap->height());
+ EXPECT_EQ(9, bitmap->num_mipmaps());
+ for (unsigned int i = 0; i < bitmap->num_mipmaps(); ++i) {
+ EXPECT_TRUE(bitmap->GetMipData(i, TextureCUBE::FACE_POSITIVE_X) != NULL);
}
- EXPECT_TRUE(TestBitmapData(bitmap, kdxt1_256x256_mipmap));
+ EXPECT_TRUE(TestBitmapData(*bitmap, kdxt1_256x256_mipmap));
}
// Loads a DXT3 DDS file, checks the format.
@@ -580,15 +580,15 @@ TEST_F(BitmapTest, LoadDDSFileDXT3) {
String filename = *g_program_path +
"/bitmap_test/dds-dxt3-256x256-alpha.dds";
FilePath filepath = UTF8ToFilePath(filename);
- Bitmap bitmap;
- EXPECT_TRUE(bitmap.LoadFromFile(filepath, Bitmap::DDS, false));
- EXPECT_TRUE(bitmap.image_data() != NULL);
- EXPECT_FALSE(bitmap.is_cubemap());
- EXPECT_EQ(Texture::DXT3, bitmap.format());
- EXPECT_EQ(256, bitmap.width());
- EXPECT_EQ(256, bitmap.height());
- EXPECT_EQ(1, bitmap.num_mipmaps());
- EXPECT_TRUE(TestBitmapData(bitmap, kdxt3_256x256_alpha));
+ Bitmap::Ref bitmap(new Bitmap(g_service_locator));
+ EXPECT_TRUE(bitmap->LoadFromFile(filepath, Bitmap::DDS, false));
+ EXPECT_TRUE(bitmap->image_data() != NULL);
+ EXPECT_FALSE(bitmap->is_cubemap());
+ EXPECT_EQ(Texture::DXT3, bitmap->format());
+ EXPECT_EQ(256, bitmap->width());
+ EXPECT_EQ(256, bitmap->height());
+ EXPECT_EQ(1, bitmap->num_mipmaps());
+ EXPECT_TRUE(TestBitmapData(*bitmap, kdxt3_256x256_alpha));
}
// Loads a DXT3 DDS file with mipmaps, checks the format.
@@ -596,18 +596,18 @@ TEST_F(BitmapTest, LoadDDSFileDXT3Mipmap) {
String filename = *g_program_path +
"/bitmap_test/dds-dxt3-256x256-mipmap.dds";
FilePath filepath = UTF8ToFilePath(filename);
- Bitmap bitmap;
- EXPECT_TRUE(bitmap.LoadFromFile(filepath, Bitmap::DDS, false));
- EXPECT_TRUE(bitmap.image_data() != NULL);
- EXPECT_FALSE(bitmap.is_cubemap());
- EXPECT_EQ(Texture::DXT3, bitmap.format());
- EXPECT_EQ(256, bitmap.width());
- EXPECT_EQ(256, bitmap.height());
- EXPECT_EQ(9, bitmap.num_mipmaps());
- for (unsigned int i = 0; i < bitmap.num_mipmaps(); ++i) {
- EXPECT_TRUE(bitmap.GetMipData(i, TextureCUBE::FACE_POSITIVE_X) != NULL);
+ Bitmap::Ref bitmap(new Bitmap(g_service_locator));
+ EXPECT_TRUE(bitmap->LoadFromFile(filepath, Bitmap::DDS, false));
+ EXPECT_TRUE(bitmap->image_data() != NULL);
+ EXPECT_FALSE(bitmap->is_cubemap());
+ EXPECT_EQ(Texture::DXT3, bitmap->format());
+ EXPECT_EQ(256, bitmap->width());
+ EXPECT_EQ(256, bitmap->height());
+ EXPECT_EQ(9, bitmap->num_mipmaps());
+ for (unsigned int i = 0; i < bitmap->num_mipmaps(); ++i) {
+ EXPECT_TRUE(bitmap->GetMipData(i, TextureCUBE::FACE_POSITIVE_X) != NULL);
}
- EXPECT_TRUE(TestBitmapData(bitmap, kdxt3_256x256_mipmap));
+ EXPECT_TRUE(TestBitmapData(*bitmap, kdxt3_256x256_mipmap));
}
// Loads a DXT5 DDS file, checks the format.
@@ -615,15 +615,15 @@ TEST_F(BitmapTest, LoadDDSFileDXT5) {
String filename = *g_program_path +
"/bitmap_test/dds-dxt5-256x256-alpha.dds";
FilePath filepath = UTF8ToFilePath(filename);
- Bitmap bitmap;
- EXPECT_TRUE(bitmap.LoadFromFile(filepath, Bitmap::DDS, false));
- EXPECT_TRUE(bitmap.image_data() != NULL);
- EXPECT_FALSE(bitmap.is_cubemap());
- EXPECT_EQ(Texture::DXT5, bitmap.format());
- EXPECT_EQ(256, bitmap.width());
- EXPECT_EQ(256, bitmap.height());
- EXPECT_EQ(1, bitmap.num_mipmaps());
- EXPECT_TRUE(TestBitmapData(bitmap, kdxt5_256x256_alpha));
+ Bitmap::Ref bitmap(new Bitmap(g_service_locator));
+ EXPECT_TRUE(bitmap->LoadFromFile(filepath, Bitmap::DDS, false));
+ EXPECT_TRUE(bitmap->image_data() != NULL);
+ EXPECT_FALSE(bitmap->is_cubemap());
+ EXPECT_EQ(Texture::DXT5, bitmap->format());
+ EXPECT_EQ(256, bitmap->width());
+ EXPECT_EQ(256, bitmap->height());
+ EXPECT_EQ(1, bitmap->num_mipmaps());
+ EXPECT_TRUE(TestBitmapData(*bitmap, kdxt5_256x256_alpha));
}
// Loads a DXT5 DDS file with mipmaps, checks the format.
@@ -631,18 +631,18 @@ TEST_F(BitmapTest, LoadDDSFileDXT5Mipmap) {
String filename = *g_program_path +
"/bitmap_test/dds-dxt5-256x256-mipmap.dds";
FilePath filepath = UTF8ToFilePath(filename);
- Bitmap bitmap;
- EXPECT_TRUE(bitmap.LoadFromFile(filepath, Bitmap::DDS, false));
- EXPECT_TRUE(bitmap.image_data() != NULL);
- EXPECT_FALSE(bitmap.is_cubemap());
- EXPECT_EQ(Texture::DXT5, bitmap.format());
- EXPECT_EQ(256, bitmap.width());
- EXPECT_EQ(256, bitmap.height());
- EXPECT_EQ(9, bitmap.num_mipmaps());
- for (unsigned int i = 0; i < bitmap.num_mipmaps(); ++i) {
- EXPECT_TRUE(bitmap.GetMipData(i, TextureCUBE::FACE_POSITIVE_X) != NULL);
+ Bitmap::Ref bitmap(new Bitmap(g_service_locator));
+ EXPECT_TRUE(bitmap->LoadFromFile(filepath, Bitmap::DDS, false));
+ EXPECT_TRUE(bitmap->image_data() != NULL);
+ EXPECT_FALSE(bitmap->is_cubemap());
+ EXPECT_EQ(Texture::DXT5, bitmap->format());
+ EXPECT_EQ(256, bitmap->width());
+ EXPECT_EQ(256, bitmap->height());
+ EXPECT_EQ(9, bitmap->num_mipmaps());
+ for (unsigned int i = 0; i < bitmap->num_mipmaps(); ++i) {
+ EXPECT_TRUE(bitmap->GetMipData(i, TextureCUBE::FACE_POSITIVE_X) != NULL);
}
- EXPECT_TRUE(TestBitmapData(bitmap, kdxt5_256x256_mipmap));
+ EXPECT_TRUE(TestBitmapData(*bitmap, kdxt5_256x256_mipmap));
}
// Tries to load a 5kx5k DDS file, which should fail.
@@ -652,9 +652,9 @@ TEST_F(BitmapTest, LoadDDSFileTooLarge) {
// but bails before reading the actual image bytes.
String filename = *g_program_path + "/bitmap_test/5kx5k.dds";
FilePath filepath = UTF8ToFilePath(filename);
- Bitmap bitmap;
- EXPECT_FALSE(bitmap.LoadFromFile(filepath, Bitmap::DDS, false));
- EXPECT_TRUE(bitmap.image_data() == NULL);
+ Bitmap::Ref bitmap(new Bitmap(g_service_locator));
+ EXPECT_FALSE(bitmap->LoadFromFile(filepath, Bitmap::DDS, false));
+ EXPECT_TRUE(bitmap->image_data() == NULL);
}
@@ -854,4 +854,421 @@ TEST_F(BitmapTest, ScaleUpToPOT) {
EXPECT_EQ(0, memcmp(data.get(), kScaleUPDataPOT, dst_size));
}
+static unsigned char kpng_8x4_drawImage[128] = {
+ // Raw dest image used in drawimage test.
+ 0x30, 0x60, 0xc0, 0xff, 0x32, 0x64, 0xc8, 0xff,
+ 0x34, 0x68, 0xd0, 0xff, 0x36, 0x6c, 0xd8, 0xff,
+ 0x38, 0x70, 0xe0, 0xff, 0x3a, 0x74, 0xe8, 0xff,
+ 0x3c, 0x78, 0xf0, 0xff, 0x3e, 0x7c, 0xf8, 0xff,
+ 0x20, 0x40, 0x80, 0xff, 0x22, 0x44, 0x88, 0xff,
+ 0x24, 0x48, 0x90, 0xff, 0x26, 0x4c, 0x98, 0xff,
+ 0x28, 0x50, 0xa0, 0xff, 0x2a, 0x54, 0xa8, 0xff,
+ 0x2c, 0x58, 0xb0, 0xff, 0x2e, 0x5c, 0xb8, 0xff,
+ 0x10, 0x20, 0x40, 0xff, 0x12, 0x24, 0x48, 0xff,
+ 0x14, 0x28, 0x50, 0xff, 0x16, 0x2c, 0x58, 0xff,
+ 0x18, 0x30, 0x60, 0xff, 0x1a, 0x34, 0x68, 0xff,
+ 0x1c, 0x38, 0x70, 0xff, 0x1e, 0x3c, 0x78, 0xff,
+ 0x00, 0x00, 0x00, 0xff, 0x02, 0x04, 0x08, 0xff,
+ 0x04, 0x08, 0x10, 0xff, 0x06, 0x0c, 0x18, 0xff,
+ 0x08, 0x10, 0x20, 0xff, 0x0a, 0x14, 0x28, 0xff,
+ 0x0c, 0x18, 0x30, 0xff, 0x0e, 0x1c, 0x38, 0xff,
+};
+
+static unsigned char kpng_8x4_drawImage_top_left[128] = {
+ // expected result of drawimage on top left corner of dest image.
+ 0x30, 0x60, 0xc0, 0xff, 0x32, 0x64, 0xc8, 0xff,
+ 0x34, 0x68, 0xd0, 0xff, 0x36, 0x6c, 0xd8, 0xff,
+ 0x38, 0x70, 0xe0, 0xff, 0x3a, 0x74, 0xe8, 0xff,
+ 0x3c, 0x78, 0xf0, 0xff, 0x3e, 0x7c, 0xf8, 0xff,
+ 0x2c, 0x2c, 0x2c, 0xff, 0x2d, 0x2d, 0x2d, 0xff,
+ 0x2e, 0x2e, 0x2e, 0xff, 0x26, 0x4c, 0x98, 0xff,
+ 0x28, 0x50, 0xa0, 0xff, 0x2a, 0x54, 0xa8, 0xff,
+ 0x2c, 0x58, 0xb0, 0xff, 0x2e, 0x5c, 0xb8, 0xff,
+ 0x28, 0x28, 0x28, 0xff, 0x29, 0x29, 0x29, 0xff,
+ 0x2a, 0x2a, 0x2a, 0xff, 0x16, 0x2c, 0x58, 0xff,
+ 0x18, 0x30, 0x60, 0xff, 0x1a, 0x34, 0x68, 0xff,
+ 0x1c, 0x38, 0x70, 0xff, 0x1e, 0x3c, 0x78, 0xff,
+ 0x24, 0x24, 0x24, 0xff, 0x25, 0x25, 0x25, 0xff,
+ 0x26, 0x26, 0x26, 0xff, 0x06, 0x0c, 0x18, 0xff,
+ 0x08, 0x10, 0x20, 0xff, 0x0a, 0x14, 0x28, 0xff,
+ 0x0c, 0x18, 0x30, 0xff, 0x0e, 0x1c, 0x38, 0xff,
+};
+
+static unsigned char kpng_8x4_drawImage_top[128] = {
+ // expected result of drawimage on top bound of dest image.
+ 0x30, 0x60, 0xc0, 0xff, 0x32, 0x64, 0xc8, 0xff,
+ 0x34, 0x68, 0xd0, 0xff, 0x36, 0x6c, 0xd8, 0xff,
+ 0x38, 0x70, 0xe0, 0xff, 0x3a, 0x74, 0xe8, 0xff,
+ 0x3c, 0x78, 0xf0, 0xff, 0x3e, 0x7c, 0xf8, 0xff,
+ 0x20, 0x40, 0x80, 0xff, 0x22, 0x44, 0x88, 0xff,
+ 0x24, 0x48, 0x90, 0xff, 0x26, 0x4c, 0x98, 0xff,
+ 0x28, 0x50, 0xa0, 0xff, 0x2a, 0x54, 0xa8, 0xff,
+ 0x2c, 0x58, 0xb0, 0xff, 0x2e, 0x5c, 0xb8, 0xff,
+ 0x10, 0x20, 0x40, 0xff, 0x12, 0x24, 0x48, 0xff,
+ 0x2b, 0x2b, 0x2b, 0xff, 0x2c, 0x2c, 0x2c, 0xff,
+ 0x2d, 0x2d, 0x2d, 0xff, 0x2e, 0x2e, 0x2e, 0xff,
+ 0x1c, 0x38, 0x70, 0xff, 0x1e, 0x3c, 0x78, 0xff,
+ 0x00, 0x00, 0x00, 0xff, 0x02, 0x04, 0x08, 0xff,
+ 0x27, 0x27, 0x27, 0xff, 0x28, 0x28, 0x28, 0xff,
+ 0x29, 0x29, 0x29, 0xff, 0x2a, 0x2a, 0x2a, 0xff,
+ 0x0c, 0x18, 0x30, 0xff, 0x0e, 0x1c, 0x38, 0xff,
+};
+
+static unsigned char kpng_8x4_drawImage_top_right[128] = {
+ // expected result of drawimage on top right corner of dest image.
+ 0x30, 0x60, 0xc0, 0xff, 0x32, 0x64, 0xc8, 0xff,
+ 0x34, 0x68, 0xd0, 0xff, 0x36, 0x6c, 0xd8, 0xff,
+ 0x38, 0x70, 0xe0, 0xff, 0x3a, 0x74, 0xe8, 0xff,
+ 0x3c, 0x78, 0xf0, 0xff, 0x3e, 0x7c, 0xf8, 0xff,
+ 0x20, 0x40, 0x80, 0xff, 0x22, 0x44, 0x88, 0xff,
+ 0x24, 0x48, 0x90, 0xff, 0x26, 0x4c, 0x98, 0xff,
+ 0x28, 0x50, 0xa0, 0xff, 0x2b, 0x2b, 0x2b, 0xff,
+ 0x2c, 0x2c, 0x2c, 0xff, 0x2d, 0x2d, 0x2d, 0xff,
+ 0x10, 0x20, 0x40, 0xff, 0x12, 0x24, 0x48, 0xff,
+ 0x14, 0x28, 0x50, 0xff, 0x16, 0x2c, 0x58, 0xff,
+ 0x18, 0x30, 0x60, 0xff, 0x27, 0x27, 0x27, 0xff,
+ 0x28, 0x28, 0x28, 0xff, 0x29, 0x29, 0x29, 0xff,
+ 0x00, 0x00, 0x00, 0xff, 0x02, 0x04, 0x08, 0xff,
+ 0x04, 0x08, 0x10, 0xff, 0x06, 0x0c, 0x18, 0xff,
+ 0x08, 0x10, 0x20, 0xff, 0x23, 0x23, 0x23, 0xff,
+ 0x24, 0x24, 0x24, 0xff, 0x25, 0x25, 0x25, 0xff,
+};
+
+static unsigned char kpng_8x4_drawImage_right[128] = {
+ // expected result of drawimage on right bound of dest image.
+ 0x30, 0x60, 0xc0, 0xff, 0x32, 0x64, 0xc8, 0xff,
+ 0x34, 0x68, 0xd0, 0xff, 0x36, 0x6c, 0xd8, 0xff,
+ 0x38, 0x70, 0xe0, 0xff, 0x2b, 0x2b, 0x2b, 0xff,
+ 0x2c, 0x2c, 0x2c, 0xff, 0x2d, 0x2d, 0x2d, 0xff,
+ 0x20, 0x40, 0x80, 0xff, 0x22, 0x44, 0x88, 0xff,
+ 0x24, 0x48, 0x90, 0xff, 0x26, 0x4c, 0x98, 0xff,
+ 0x28, 0x50, 0xa0, 0xff, 0x27, 0x27, 0x27, 0xff,
+ 0x28, 0x28, 0x28, 0xff, 0x29, 0x29, 0x29, 0xff,
+ 0x10, 0x20, 0x40, 0xff, 0x12, 0x24, 0x48, 0xff,
+ 0x14, 0x28, 0x50, 0xff, 0x16, 0x2c, 0x58, 0xff,
+ 0x18, 0x30, 0x60, 0xff, 0x23, 0x23, 0x23, 0xff,
+ 0x24, 0x24, 0x24, 0xff, 0x25, 0x25, 0x25, 0xff,
+ 0x00, 0x00, 0x00, 0xff, 0x02, 0x04, 0x08, 0xff,
+ 0x04, 0x08, 0x10, 0xff, 0x06, 0x0c, 0x18, 0xff,
+ 0x08, 0x10, 0x20, 0xff, 0x1f, 0x1f, 0x1f, 0xff,
+ 0x20, 0x20, 0x20, 0xff, 0x21, 0x21, 0x21, 0xff,
+};
+
+static unsigned char kpng_8x4_drawImage_bottom_right[128] = {
+ // expected result of drawimage on bottom right corner of dest image.
+ 0x30, 0x60, 0xc0, 0xff, 0x32, 0x64, 0xc8, 0xff,
+ 0x34, 0x68, 0xd0, 0xff, 0x36, 0x6c, 0xd8, 0xff,
+ 0x38, 0x70, 0xe0, 0xff, 0x27, 0x27, 0x27, 0xff,
+ 0x28, 0x28, 0x28, 0xff, 0x29, 0x29, 0x29, 0xff,
+ 0x20, 0x40, 0x80, 0xff, 0x22, 0x44, 0x88, 0xff,
+ 0x24, 0x48, 0x90, 0xff, 0x26, 0x4c, 0x98, 0xff,
+ 0x28, 0x50, 0xa0, 0xff, 0x23, 0x23, 0x23, 0xff,
+ 0x24, 0x24, 0x24, 0xff, 0x25, 0x25, 0x25, 0xff,
+ 0x10, 0x20, 0x40, 0xff, 0x12, 0x24, 0x48, 0xff,
+ 0x14, 0x28, 0x50, 0xff, 0x16, 0x2c, 0x58, 0xff,
+ 0x18, 0x30, 0x60, 0xff, 0x1f, 0x1f, 0x1f, 0xff,
+ 0x20, 0x20, 0x20, 0xff, 0x21, 0x21, 0x21, 0xff,
+ 0x00, 0x00, 0x00, 0xff, 0x02, 0x04, 0x08, 0xff,
+ 0x04, 0x08, 0x10, 0xff, 0x06, 0x0c, 0x18, 0xff,
+ 0x08, 0x10, 0x20, 0xff, 0x0a, 0x14, 0x28, 0xff,
+ 0x0c, 0x18, 0x30, 0xff, 0x0e, 0x1c, 0x38, 0xff,
+};
+
+static unsigned char kpng_8x4_drawImage_bottom[128] = {
+ // expected result of drawimage on bottom bound of dest image.
+ 0x30, 0x60, 0xc0, 0xff, 0x32, 0x64, 0xc8, 0xff,
+ 0x27, 0x27, 0x27, 0xff, 0x28, 0x28, 0x28, 0xff,
+ 0x29, 0x29, 0x29, 0xff, 0x2a, 0x2a, 0x2a, 0xff,
+ 0x3c, 0x78, 0xf0, 0xff, 0x3e, 0x7c, 0xf8, 0xff,
+ 0x20, 0x40, 0x80, 0xff, 0x22, 0x44, 0x88, 0xff,
+ 0x23, 0x23, 0x23, 0xff, 0x24, 0x24, 0x24, 0xff,
+ 0x25, 0x25, 0x25, 0xff, 0x26, 0x26, 0x26, 0xff,
+ 0x2c, 0x58, 0xb0, 0xff, 0x2e, 0x5c, 0xb8, 0xff,
+ 0x10, 0x20, 0x40, 0xff, 0x12, 0x24, 0x48, 0xff,
+ 0x1f, 0x1f, 0x1f, 0xff, 0x20, 0x20, 0x20, 0xff,
+ 0x21, 0x21, 0x21, 0xff, 0x22, 0x22, 0x22, 0xff,
+ 0x1c, 0x38, 0x70, 0xff, 0x1e, 0x3c, 0x78, 0xff,
+ 0x00, 0x00, 0x00, 0xff, 0x02, 0x04, 0x08, 0xff,
+ 0x04, 0x08, 0x10, 0xff, 0x06, 0x0c, 0x18, 0xff,
+ 0x08, 0x10, 0x20, 0xff, 0x0a, 0x14, 0x28, 0xff,
+ 0x0c, 0x18, 0x30, 0xff, 0x0e, 0x1c, 0x38, 0xff,
+};
+
+static unsigned char kpng_8x4_drawImage_bottom_left[128] = {
+ // expected result of drawimage on bottom left corner of dest image.
+ 0x28, 0x28, 0x28, 0xff, 0x29, 0x29, 0x29, 0xff,
+ 0x2a, 0x2a, 0x2a, 0xff, 0x36, 0x6c, 0xd8, 0xff,
+ 0x38, 0x70, 0xe0, 0xff, 0x3a, 0x74, 0xe8, 0xff,
+ 0x3c, 0x78, 0xf0, 0xff, 0x3e, 0x7c, 0xf8, 0xff,
+ 0x24, 0x24, 0x24, 0xff, 0x25, 0x25, 0x25, 0xff,
+ 0x26, 0x26, 0x26, 0xff, 0x26, 0x4c, 0x98, 0xff,
+ 0x28, 0x50, 0xa0, 0xff, 0x2a, 0x54, 0xa8, 0xff,
+ 0x2c, 0x58, 0xb0, 0xff, 0x2e, 0x5c, 0xb8, 0xff,
+ 0x20, 0x20, 0x20, 0xff, 0x21, 0x21, 0x21, 0xff,
+ 0x22, 0x22, 0x22, 0xff, 0x16, 0x2c, 0x58, 0xff,
+ 0x18, 0x30, 0x60, 0xff, 0x1a, 0x34, 0x68, 0xff,
+ 0x1c, 0x38, 0x70, 0xff, 0x1e, 0x3c, 0x78, 0xff,
+ 0x00, 0x00, 0x00, 0xff, 0x02, 0x04, 0x08, 0xff,
+ 0x04, 0x08, 0x10, 0xff, 0x06, 0x0c, 0x18, 0xff,
+ 0x08, 0x10, 0x20, 0xff, 0x0a, 0x14, 0x28, 0xff,
+ 0x0c, 0x18, 0x30, 0xff, 0x0e, 0x1c, 0x38, 0xff,
+};
+
+static unsigned char kpng_8x4_drawImage_left[128] = {
+ // expected result of drawimage on left bound of dest image.
+ 0x2c, 0x2c, 0x2c, 0xff, 0x2d, 0x2d, 0x2d, 0xff,
+ 0x2e, 0x2e, 0x2e, 0xff, 0x36, 0x6c, 0xd8, 0xff,
+ 0x38, 0x70, 0xe0, 0xff, 0x3a, 0x74, 0xe8, 0xff,
+ 0x3c, 0x78, 0xf0, 0xff, 0x3e, 0x7c, 0xf8, 0xff,
+ 0x28, 0x28, 0x28, 0xff, 0x29, 0x29, 0x29, 0xff,
+ 0x2a, 0x2a, 0x2a, 0xff, 0x26, 0x4c, 0x98, 0xff,
+ 0x28, 0x50, 0xa0, 0xff, 0x2a, 0x54, 0xa8, 0xff,
+ 0x2c, 0x58, 0xb0, 0xff, 0x2e, 0x5c, 0xb8, 0xff,
+ 0x24, 0x24, 0x24, 0xff, 0x25, 0x25, 0x25, 0xff,
+ 0x26, 0x26, 0x26, 0xff, 0x16, 0x2c, 0x58, 0xff,
+ 0x18, 0x30, 0x60, 0xff, 0x1a, 0x34, 0x68, 0xff,
+ 0x1c, 0x38, 0x70, 0xff, 0x1e, 0x3c, 0x78, 0xff,
+ 0x20, 0x20, 0x20, 0xff, 0x21, 0x21, 0x21, 0xff,
+ 0x22, 0x22, 0x22, 0xff, 0x06, 0x0c, 0x18, 0xff,
+ 0x08, 0x10, 0x20, 0xff, 0x0a, 0x14, 0x28, 0xff,
+ 0x0c, 0x18, 0x30, 0xff, 0x0e, 0x1c, 0x38, 0xff,
+};
+
+static unsigned char kpng_8x4_drawImage_scale_up[128] = {
+ // expected result of scale up from 2x2 to 8x4.
+ 0x3f, 0x3f, 0x3f, 0xff, 0x48, 0x48, 0x48, 0xff,
+ 0x51, 0x51, 0x51, 0xff, 0x5a, 0x5a, 0x5a, 0xff,
+ 0x64, 0x64, 0x64, 0xff, 0x6d, 0x6d, 0x6d, 0xff,
+ 0x76, 0x76, 0x76, 0xff, 0x7f, 0x7f, 0x7f, 0xff,
+ 0x2a, 0x2a, 0x2a, 0xff, 0x32, 0x32, 0x32, 0xff,
+ 0x39, 0x39, 0x39, 0xff, 0x41, 0x41, 0x41, 0xff,
+ 0x48, 0x48, 0x48, 0xff, 0x50, 0x50, 0x50, 0xff,
+ 0x57, 0x57, 0x57, 0xff, 0x5f, 0x5f, 0x5f, 0xff,
+ 0x15, 0x15, 0x15, 0xff, 0x1b, 0x1b, 0x1b, 0xff,
+ 0x21, 0x21, 0x21, 0xff, 0x27, 0x27, 0x27, 0xff,
+ 0x2d, 0x2d, 0x2d, 0xff, 0x33, 0x33, 0x33, 0xff,
+ 0x39, 0x39, 0x39, 0xff, 0x3f, 0x3f, 0x3f, 0xff,
+ 0x00, 0x00, 0x00, 0xff, 0x04, 0x04, 0x04, 0xff,
+ 0x09, 0x09, 0x09, 0xff, 0x0d, 0x0d, 0x0d, 0xff,
+ 0x12, 0x12, 0x12, 0xff, 0x16, 0x16, 0x16, 0xff,
+ 0x1b, 0x1b, 0x1b, 0xff, 0x1f, 0x1f, 0x1f, 0xff,
+};
+
+static unsigned char kpng_8x4_drawImage_scale_down[128] = {
+ // expected result of scale down from 8x8 to 4x4.
+ 0xa8, 0xa8, 0xa8, 0xff, 0xaf, 0xaf, 0xaf, 0xff,
+ 0xb6, 0xb6, 0xb6, 0xff, 0xbd, 0xbd, 0xbd, 0xff,
+ 0x38, 0x70, 0xe0, 0xff, 0x3a, 0x74, 0xe8, 0xff,
+ 0x3c, 0x78, 0xf0, 0xff, 0x3e, 0x7c, 0xf8, 0xff,
+ 0x70, 0x70, 0x70, 0xff, 0x77, 0x77, 0x77, 0xff,
+ 0x7e, 0x7e, 0x7e, 0xff, 0x85, 0x85, 0x85, 0xff,
+ 0x28, 0x50, 0xa0, 0xff, 0x2a, 0x54, 0xa8, 0xff,
+ 0x2c, 0x58, 0xb0, 0xff, 0x2e, 0x5c, 0xb8, 0xff,
+ 0x38, 0x38, 0x38, 0xff, 0x3f, 0x3f, 0x3f, 0xff,
+ 0x46, 0x46, 0x46, 0xff, 0x4d, 0x4d, 0x4d, 0xff,
+ 0x18, 0x30, 0x60, 0xff, 0x1a, 0x34, 0x68, 0xff,
+ 0x1c, 0x38, 0x70, 0xff, 0x1e, 0x3c, 0x78, 0xff,
+ 0x00, 0x00, 0x00, 0xff, 0x07, 0x07, 0x07, 0xff,
+ 0x0e, 0x0e, 0x0e, 0xff, 0x15, 0x15, 0x15, 0xff,
+ 0x08, 0x10, 0x20, 0xff, 0x0a, 0x14, 0x28, 0xff,
+ 0x0c, 0x18, 0x30, 0xff, 0x0e, 0x1c, 0x38, 0xff,
+};
+
+static unsigned char kpng_8x4_drawImage_scale_out[128] = {
+ // expected result of scale src image larger than dest image.
+ 0x63, 0x63, 0x63, 0xff, 0x65, 0x65, 0x65, 0xff,
+ 0x67, 0x67, 0x67, 0xff, 0x69, 0x69, 0x69, 0xff,
+ 0x6c, 0x6c, 0x6c, 0xff, 0x6e, 0x6e, 0x6e, 0xff,
+ 0x70, 0x70, 0x70, 0xff, 0x72, 0x72, 0x72, 0xff,
+ 0x53, 0x53, 0x53, 0xff, 0x55, 0x55, 0x55, 0xff,
+ 0x57, 0x57, 0x57, 0xff, 0x59, 0x59, 0x59, 0xff,
+ 0x5c, 0x5c, 0x5c, 0xff, 0x5e, 0x5e, 0x5e, 0xff,
+ 0x60, 0x60, 0x60, 0xff, 0x62, 0x62, 0x62, 0xff,
+ 0x43, 0x43, 0x43, 0xff, 0x45, 0x45, 0x45, 0xff,
+ 0x47, 0x47, 0x47, 0xff, 0x49, 0x49, 0x49, 0xff,
+ 0x4c, 0x4c, 0x4c, 0xff, 0x4e, 0x4e, 0x4e, 0xff,
+ 0x50, 0x50, 0x50, 0xff, 0x52, 0x52, 0x52, 0xff,
+ 0x33, 0x33, 0x33, 0xff, 0x35, 0x35, 0x35, 0xff,
+ 0x37, 0x37, 0x37, 0xff, 0x39, 0x39, 0x39, 0xff,
+ 0x3c, 0x3c, 0x3c, 0xff, 0x3e, 0x3e, 0x3e, 0xff,
+ 0x40, 0x40, 0x40, 0xff, 0x42, 0x42, 0x42, 0xff,
+};
+
+static unsigned char kpng_8x4_drawImage_flip[128] = {
+ // expected result of flip src image.
+ 0x30, 0x60, 0xc0, 0xff, 0x32, 0x64, 0xc8, 0xff,
+ 0x22, 0x22, 0x22, 0xff, 0x21, 0x21, 0x21, 0xff,
+ 0x20, 0x20, 0x20, 0xff, 0x1f, 0x1f, 0x1f, 0xff,
+ 0x3c, 0x78, 0xf0, 0xff, 0x3e, 0x7c, 0xf8, 0xff,
+ 0x20, 0x40, 0x80, 0xff, 0x22, 0x44, 0x88, 0xff,
+ 0x26, 0x26, 0x26, 0xff, 0x25, 0x25, 0x25, 0xff,
+ 0x24, 0x24, 0x24, 0xff, 0x23, 0x23, 0x23, 0xff,
+ 0x2c, 0x58, 0xb0, 0xff, 0x2e, 0x5c, 0xb8, 0xff,
+ 0x10, 0x20, 0x40, 0xff, 0x12, 0x24, 0x48, 0xff,
+ 0x2a, 0x2a, 0x2a, 0xff, 0x29, 0x29, 0x29, 0xff,
+ 0x28, 0x28, 0x28, 0xff, 0x27, 0x27, 0x27, 0xff,
+ 0x1c, 0x38, 0x70, 0xff, 0x1e, 0x3c, 0x78, 0xff,
+ 0x00, 0x00, 0x00, 0xff, 0x02, 0x04, 0x08, 0xff,
+ 0x2e, 0x2e, 0x2e, 0xff, 0x2d, 0x2d, 0x2d, 0xff,
+ 0x2c, 0x2c, 0x2c, 0xff, 0x2b, 0x2b, 0x2b, 0xff,
+ 0x0c, 0x18, 0x30, 0xff, 0x0e, 0x1c, 0x38, 0xff,
+};
+
+static unsigned char kpng_8x4_drawImage_argb8[128] = {
+ // expected result of drawimage with rgb8 format.
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xca, 0xca, 0xca, 0x3e, 0xd7, 0xd7, 0xd7, 0x9a,
+ 0x00, 0x00, 0x00, 0xee, 0x00, 0x00, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0xca, 0xca, 0xca, 0x3e,
+ 0xe6, 0xe6, 0xe6, 0xdc, 0xfc, 0xfc, 0xfc, 0xfe,
+ 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
+ 0xca, 0xca, 0xca, 0x3e, 0xe6, 0xe6, 0xe6, 0xdc,
+ 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
+ 0xc7, 0xc7, 0xc7, 0x83, 0xf4, 0xf4, 0xf4, 0xfb,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0xeb, 0x00, 0x00, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
+};
+
+// DrawImage from another bitmap on different positions,
+// compare with expected results.
+TEST_F(BitmapTest, DrawImage) {
+ // path of dest image.
+ String fname_dst = *g_program_path +
+ "/bitmap_test/png-8x4-24bit-drawimage-dest.png";
+
+ // load three src bitmaps in different sizes from files.
+ String filename_2x2_src = *g_program_path +
+ "/bitmap_test/png-2x2-24bit-drawimage-src.png";
+ Bitmap::Ref bitmap_2x2_src(new Bitmap(g_service_locator));
+ EXPECT_TRUE(bitmap_2x2_src->LoadFromFile(UTF8ToFilePath(filename_2x2_src),
+ Bitmap::PNG, false));
+
+ String filename_4x4_src = *g_program_path +
+ "/bitmap_test/png-4x4-24bit-drawimage-src.png";
+ Bitmap::Ref bitmap_4x4_src(new Bitmap(g_service_locator));
+ EXPECT_TRUE(bitmap_4x4_src->LoadFromFile(UTF8ToFilePath(filename_4x4_src),
+ Bitmap::PNG, false));
+
+ String filename_8x8_src = *g_program_path +
+ "/bitmap_test/png-8x8-24bit-drawimage-src.png";
+ Bitmap::Ref bitmap_8x8_src(new Bitmap(g_service_locator));
+ EXPECT_TRUE(bitmap_8x8_src->LoadFromFile(UTF8ToFilePath(filename_8x8_src),
+ Bitmap::PNG, false));
+
+ // test draw image on top left boundary.
+ Bitmap::Ref bitmap_dest_top_left(new Bitmap(g_service_locator));
+ EXPECT_TRUE(bitmap_dest_top_left->LoadFromFile(UTF8ToFilePath(fname_dst),
+ Bitmap::PNG, false));
+ // test whether the raw image is loaded correctly or not.
+ EXPECT_TRUE(bitmap_dest_top_left->image_data() != NULL);
+ EXPECT_TRUE(TestBitmapData(*bitmap_dest_top_left, kpng_8x4_drawImage));
+ bitmap_dest_top_left->DrawImage(bitmap_4x4_src, 0, 0, 4, 4, -1, -1, 4, 4);
+ EXPECT_TRUE(TestBitmapData(*bitmap_dest_top_left,
+ kpng_8x4_drawImage_top_left));
+
+ // test draw image on top boundary.
+ Bitmap::Ref bitmap_dest_top(new Bitmap(g_service_locator));
+ EXPECT_TRUE(bitmap_dest_top->LoadFromFile(UTF8ToFilePath(fname_dst),
+ Bitmap::PNG, false));
+ bitmap_dest_top->DrawImage(bitmap_4x4_src, 0, 0, 4, 4, 2, -2, 4, 4);
+ EXPECT_TRUE(TestBitmapData(*bitmap_dest_top, kpng_8x4_drawImage_top));
+
+ // test draw image on top right boundary.
+ Bitmap::Ref bitmap_dest_top_right(new Bitmap(g_service_locator));
+ EXPECT_TRUE(bitmap_dest_top_right->LoadFromFile(UTF8ToFilePath(fname_dst),
+ Bitmap::PNG, false));
+ bitmap_dest_top_right->DrawImage(bitmap_4x4_src, 0, 0, 4, 4, 5, -1, 4, 4);
+ EXPECT_TRUE(TestBitmapData(*bitmap_dest_top_right,
+ kpng_8x4_drawImage_top_right));
+
+ // test draw image on right boundary.
+ Bitmap::Ref bitmap_dest_right(new Bitmap(g_service_locator));
+ EXPECT_TRUE(bitmap_dest_right->LoadFromFile(UTF8ToFilePath(fname_dst),
+ Bitmap::PNG, false));
+ bitmap_dest_right->DrawImage(bitmap_4x4_src, 0, 0, 4, 4, 5, 0, 4, 4);
+ EXPECT_TRUE(TestBitmapData(*bitmap_dest_right, kpng_8x4_drawImage_right));
+
+ // test draw image on bottom right boundary.
+ Bitmap::Ref bitmap_dest_bottom_right(new Bitmap(g_service_locator));
+ EXPECT_TRUE(bitmap_dest_bottom_right->LoadFromFile(UTF8ToFilePath(fname_dst),
+ Bitmap::PNG, false));
+ bitmap_dest_bottom_right->DrawImage(bitmap_4x4_src, 0, 0, 4, 4, 5, 1, 4, 4);
+ EXPECT_TRUE(TestBitmapData(*bitmap_dest_bottom_right,
+ kpng_8x4_drawImage_bottom_right));
+
+ // test draw image on bottom boundary.
+ Bitmap::Ref bitmap_dest_bottom(new Bitmap(g_service_locator));
+ EXPECT_TRUE(bitmap_dest_bottom->LoadFromFile(UTF8ToFilePath(fname_dst),
+ Bitmap::PNG, false));
+ bitmap_dest_bottom->DrawImage(bitmap_4x4_src, 0, 0, 4, 4, 2, 1, 4, 4);
+ EXPECT_TRUE(TestBitmapData(*bitmap_dest_bottom, kpng_8x4_drawImage_bottom));
+
+ // test draw image on bottom left boundary.
+ Bitmap::Ref bitmap_dest_bottom_left(new Bitmap(g_service_locator));
+ EXPECT_TRUE(bitmap_dest_bottom_left->LoadFromFile(UTF8ToFilePath(fname_dst),
+ Bitmap::PNG, false));
+ bitmap_dest_bottom_left->DrawImage(bitmap_4x4_src, 0, 0, 4, 4, -1, 1, 4, 4);
+ EXPECT_TRUE(TestBitmapData(*bitmap_dest_bottom_left,
+ kpng_8x4_drawImage_bottom_left));
+
+ // test draw image on left boundary.
+ Bitmap::Ref bitmap_dest_left(new Bitmap(g_service_locator));
+ EXPECT_TRUE(bitmap_dest_left->LoadFromFile(UTF8ToFilePath(fname_dst),
+ Bitmap::PNG, false));
+ bitmap_dest_left->DrawImage(bitmap_4x4_src, 0, 0, 4, 4, -1, 0, 4, 4);
+ EXPECT_TRUE(TestBitmapData(*bitmap_dest_left, kpng_8x4_drawImage_left));
+
+ // test scale up.
+ Bitmap::Ref bitmap_dest_scale_up(new Bitmap(g_service_locator));
+ EXPECT_TRUE(bitmap_dest_scale_up->LoadFromFile(UTF8ToFilePath(fname_dst),
+ Bitmap::PNG, false));
+ bitmap_dest_scale_up->DrawImage(bitmap_2x2_src, 0, 0, 2, 2, 0, 0, 8, 4);
+ EXPECT_TRUE(TestBitmapData(*bitmap_dest_scale_up,
+ kpng_8x4_drawImage_scale_up));
+
+ // test scale down.
+ Bitmap::Ref bitmap_dest_scale_down(new Bitmap(g_service_locator));
+ EXPECT_TRUE(bitmap_dest_scale_down->LoadFromFile(UTF8ToFilePath(fname_dst),
+ Bitmap::PNG, false));
+ bitmap_dest_scale_down->DrawImage(bitmap_8x8_src, 0, 0, 8, 8, 0, 0, 4, 4);
+ EXPECT_TRUE(TestBitmapData(*bitmap_dest_scale_down,
+ kpng_8x4_drawImage_scale_down));
+
+ // test scale up to a large size.
+ Bitmap::Ref bitmap_dest_scale_out(new Bitmap(g_service_locator));
+ EXPECT_TRUE(bitmap_dest_scale_out->LoadFromFile(UTF8ToFilePath(fname_dst),
+ Bitmap::PNG, false));
+ bitmap_dest_scale_out->DrawImage(bitmap_8x8_src, 0, 0, 8, 8, -2, -4, 12, 12);
+ EXPECT_TRUE(TestBitmapData(*bitmap_dest_scale_out,
+ kpng_8x4_drawImage_scale_out));
+
+ // test flip an image on both x and y cooridnates.
+ Bitmap::Ref bitmap_dest_flip(new Bitmap(g_service_locator));
+ EXPECT_TRUE(bitmap_dest_flip->LoadFromFile(UTF8ToFilePath(fname_dst),
+ Bitmap::PNG, false));
+ bitmap_dest_flip->DrawImage(bitmap_4x4_src, 0, 0, 4, 4, 5, 3, -4, -4);
+ EXPECT_TRUE(TestBitmapData(*bitmap_dest_flip, kpng_8x4_drawImage_flip));
+
+ // test draw image on argb8 format.
+ String fname_dst_argb8 = *g_program_path +
+ "/bitmap_test/" +
+ "png-8x4-24bit-drawimage-argb8-dest.png";
+ Bitmap::Ref bitmap_dest_argb8(new Bitmap(g_service_locator));
+ EXPECT_TRUE(bitmap_dest_argb8->LoadFromFile(UTF8ToFilePath(fname_dst_argb8),
+ Bitmap::PNG, false));
+ String fname_src_argb8 = *g_program_path +
+ "/bitmap_test/" +
+ "png-4x4-24bit-drawimage-argb8-src.png";
+ Bitmap::Ref bitmap_src_argb8(new Bitmap(g_service_locator));
+ EXPECT_TRUE(bitmap_src_argb8->LoadFromFile(UTF8ToFilePath(fname_src_argb8),
+ Bitmap::PNG, false));
+ bitmap_dest_argb8->DrawImage(bitmap_src_argb8, 0, 0, 4, 4, 0, 0, 4, 4);
+ EXPECT_TRUE(TestBitmapData(*bitmap_dest_argb8, kpng_8x4_drawImage_argb8));
+}
+
} // namespace
diff --git a/o3d/core/cross/class_manager.cc b/o3d/core/cross/class_manager.cc
index 8f3cfd5..c037a7b 100644
--- a/o3d/core/cross/class_manager.cc
+++ b/o3d/core/cross/class_manager.cc
@@ -140,6 +140,7 @@ ClassManager::ClassManager(ServiceLocator* service_locator)
AddTypedClass<WorldViewProjectionInverseTransposeParamMatrix4>();
// Other Objects.
+ AddTypedClass<Bitmap>();
AddTypedClass<Canvas>();
AddTypedClass<CanvasLinearGradient>();
AddTypedClass<CanvasPaint>();
diff --git a/o3d/core/cross/pack.cc b/o3d/core/cross/pack.cc
index 96b06de..87c64be8 100644
--- a/o3d/core/cross/pack.cc
+++ b/o3d/core/cross/pack.cc
@@ -135,14 +135,14 @@ Texture* Pack::CreateTextureFromFile(const String& uri,
// TODO: Add support for volume texture when we have code to load
// them
- Bitmap bitmap;
- if (!bitmap.LoadFromFile(filepath, file_type, generate_mipmaps)) {
+ Bitmap::Ref bitmap(new Bitmap(service_locator()));
+ if (!bitmap->LoadFromFile(filepath, file_type, generate_mipmaps)) {
O3D_ERROR(service_locator())
<< "Failed to load bitmap file \"" << uri << "\"";
return NULL;
}
- return CreateTextureFromBitmap(&bitmap, uri);
+ return CreateTextureFromBitmap(bitmap, uri);
}
// Creates a Texture object from a file in the current render context format.
@@ -198,7 +198,6 @@ Texture* Pack::CreateTextureFromBitmap(Bitmap *bitmap, const String& uri) {
return texture.Get();
}
-
// Creates a Texture object from RawData and allocates
// the necessary resources for it.
Texture* Pack::CreateTextureFromRawData(RawData *raw_data,
@@ -213,14 +212,53 @@ Texture* Pack::CreateTextureFromRawData(RawData *raw_data,
DLOG(INFO) << "CreateTextureFromRawData(uri='" << uri << "')";
- Bitmap bitmap;
- if (!bitmap.LoadFromRawData(raw_data, Bitmap::UNKNOWN, generate_mips)) {
+ Bitmap::Ref bitmap(new Bitmap(service_locator()));
+ if (!bitmap->LoadFromRawData(raw_data, Bitmap::UNKNOWN, generate_mips)) {
O3D_ERROR(service_locator())
<< "Failed to load bitmap from raw data \"" << uri << "\"";
return NULL;
}
- return CreateTextureFromBitmap(&bitmap, uri);
+ return CreateTextureFromBitmap(bitmap, uri);
+}
+
+// Create a bitmap object.
+Bitmap* Pack::CreateBitmap(int width, int height,
+ Texture::Format format) {
+ DCHECK(Bitmap::CheckImageDimensions(width, height));
+
+ Bitmap::Ref bitmap(new Bitmap(service_locator()));
+ if (bitmap.IsNull()) {
+ O3D_ERROR(service_locator())
+ << "Failed to create bitmap object.";
+ return NULL;
+ }
+ bitmap->Allocate(format, width, height, 1, false);
+ if (!bitmap->image_data()) {
+ O3D_ERROR(service_locator())
+ << "Failed to allocate memory for bitmap.";
+ return NULL;
+ }
+ RegisterObject(bitmap);
+ return bitmap.Get();
+}
+
+// Create a new bitmap object from rawdata.
+Bitmap* Pack::CreateBitmapFromRawData(RawData* raw_data) {
+ Bitmap::Ref bitmap(new Bitmap(service_locator()));
+ if (bitmap.IsNull()) {
+ O3D_ERROR(service_locator())
+ << "Failed to create bitmap object.";
+ return NULL;
+ }
+ if (!bitmap->LoadFromRawData(raw_data, Bitmap::UNKNOWN,
+ false)) {
+ O3D_ERROR(service_locator())
+ << "Failed to load bitmap from raw data.";
+ return NULL;
+ }
+ RegisterObject(bitmap);
+ return bitmap.Get();
}
// Creates a Texture2D object and allocates the necessary resources for it.
diff --git a/o3d/core/cross/pack.h b/o3d/core/cross/pack.h
index 2628dc0..8832f02 100644
--- a/o3d/core/cross/pack.h
+++ b/o3d/core/cross/pack.h
@@ -215,6 +215,26 @@ class Pack : public NamedObject {
Texture* CreateTextureFromRawData(RawData* raw_data,
bool generate_mips);
+ // Creates a new Bitmap object of the specified size and format and
+ // reserves the necessary resources for it.
+ // Paramters:
+ // width: The width of the bitmap in pixel.
+ // height: The height of the bitmap in pixel.
+ // format: The format of the bitmap.
+ // Returns:
+ // A pointer to the bitmap obejct.
+
+ Bitmap* CreateBitmap(int width, int height, Texture::Format format);
+
+ // Creates a new Bitmap object from RawData.
+ // Parameters:
+ // raw_data: contains the bitmap data in one of the know formats.
+ // file_type: the format of the bitmap data. If UNKNOW, the file
+ // type would determined from the extension.
+ // Returns:
+ // A pointer to the bitmap object.
+ Bitmap* CreateBitmapFromRawData(RawData* raw_data);
+
// Creates a new Texture2D object of the specified size and format and
// reserves the necessary resources for it.
// Parameters:
@@ -404,13 +424,13 @@ class Pack : public NamedObject {
}
};
- // Helper method
- Texture* CreateTextureFromBitmap(Bitmap *bitmap, const String& uri);
-
IClassManager* class_manager_;
ObjectManager* object_manager_;
Renderer* renderer_;
+ // helper function
+ Texture* CreateTextureFromBitmap(Bitmap *bitmap, const String& uri);
+
// The set of objects owned by the pack. This container contains all of the
// references that force the lifespan of the contained objects to match
// or exceed that of the pack.
diff --git a/o3d/core/cross/renderer_test.cc b/o3d/core/cross/renderer_test.cc
index c52645b..4c4acdd 100644
--- a/o3d/core/cross/renderer_test.cc
+++ b/o3d/core/cross/renderer_test.cc
@@ -118,14 +118,14 @@ TEST_F(RendererTest, OffScreen) {
// TODO: add InitAndDestroyGL and InitAndDestroyMock
TEST_F(RendererTest, Creates2DTextureFromBitmap) {
- Bitmap bitmap;
- bitmap.Allocate(Texture::ARGB8, 16, 32, 2, false);
- memset(bitmap.image_data(), 0x34, bitmap.GetTotalSize());
+ Bitmap::Ref bitmap(new Bitmap(g_service_locator));
+ bitmap->Allocate(Texture::ARGB8, 16, 32, 2, false);
+ memset(bitmap->image_data(), 0x34, bitmap->GetTotalSize());
Client client(g_service_locator);
client.Init();
- Texture::Ref texture = g_renderer->CreateTextureFromBitmap(&bitmap);
+ Texture::Ref texture = g_renderer->CreateTextureFromBitmap(bitmap);
ASSERT_TRUE(NULL != texture);
EXPECT_EQ(Texture::ARGB8, texture->format());
EXPECT_EQ(2, texture->levels());
@@ -137,14 +137,14 @@ TEST_F(RendererTest, Creates2DTextureFromBitmap) {
}
TEST_F(RendererTest, CreatesCubeTextureFromBitmap) {
- Bitmap bitmap;
- bitmap.Allocate(Texture::ARGB8, 16, 16, 2, true);
- memset(bitmap.image_data(), 0x34, bitmap.GetTotalSize());
+ Bitmap::Ref bitmap(new Bitmap(g_service_locator));
+ bitmap->Allocate(Texture::ARGB8, 16, 16, 2, true);
+ memset(bitmap->image_data(), 0x34, bitmap->GetTotalSize());
Client client(g_service_locator);
client.Init();
- Texture::Ref texture = g_renderer->CreateTextureFromBitmap(&bitmap);
+ Texture::Ref texture = g_renderer->CreateTextureFromBitmap(bitmap);
ASSERT_TRUE(NULL != texture);
EXPECT_EQ(Texture::ARGB8, texture->format());
EXPECT_EQ(2, texture->levels());
diff --git a/o3d/core/cross/texture.cc b/o3d/core/cross/texture.cc
index 058dbb4..88897c3 100644
--- a/o3d/core/cross/texture.cc
+++ b/o3d/core/cross/texture.cc
@@ -89,6 +89,82 @@ Texture2D::~Texture2D() {
levels())));
}
+void Texture2D::DrawImage(Bitmap* src_img,
+ int src_x, int src_y,
+ int src_width, int src_height,
+ int dst_x, int dst_y,
+ int dst_width, int dst_height, int dest_mip) {
+ DCHECK(src_img->image_data());
+
+ int mip_width = std::max(1, width() >> dest_mip);
+ int mip_height = std::max(1, height() >> dest_mip);
+
+ // Clip source and destination rectangles to
+ // source and destination bitmaps.
+ // if src or dest rectangle is out of boundary,
+ // do nothing and return.
+ if (!Bitmap::AdjustDrawImageBoundary(&src_x, &src_y,
+ &src_width, &src_height,
+ src_img->width(), src_img->height(),
+ &dst_x, &dst_y,
+ &dst_width, &dst_height,
+ mip_width, mip_height))
+ return;
+
+ unsigned int components = 0;
+ // check formats of source and dest images.
+ // format of source and dest should be the same.
+ if (src_img->format() != format()) {
+ O3D_ERROR(service_locator()) << "DrawImage does not support "
+ << "different formats.";
+ return;
+ }
+ // if src and dest are in the same size and drawImage is copying
+ // the entire bitmap on dest image, just perform memcpy.
+ if (src_x == 0 && src_y == 0 && dst_x == 0 && dst_y == 0 &&
+ src_img->width() == mip_width && src_img->height() == mip_height &&
+ src_width == src_img->width() && src_height == src_img->height() &&
+ dst_width == mip_width && dst_height == mip_height) {
+ void* data = NULL;
+ if (!Lock(dest_mip, &data))
+ return;
+
+ uint8* mip_data = static_cast<uint8*>(data);
+ unsigned int size = Bitmap::GetMipChainSize(mip_width, mip_height,
+ format(), 1);
+ memcpy(mip_data, src_img->image_data(), size);
+ this->Unlock(dest_mip);
+
+ return;
+ }
+ if (src_img->format() == Texture::XRGB8 ||
+ src_img->format() == Texture::ARGB8) {
+ components = 4;
+ } else {
+ O3D_ERROR(service_locator()) << "DrawImage does not support format: "
+ << src_img->format() << " unless src and "
+ << "dest images are in the same size and "
+ << "copying the entire bitmap";
+ return;
+ }
+
+ void* data = NULL;
+ if (!Lock(dest_mip, &data))
+ return;
+
+ uint8* src_img_data = src_img->image_data();
+ uint8* mip_data = static_cast<uint8*>(data);
+
+ Bitmap::BilinearInterpolateScale(src_img_data, src_x, src_y,
+ src_width, src_height,
+ src_img->width(), src_img->height(),
+ mip_data, dst_x, dst_y,
+ dst_width, dst_height,
+ mip_width, mip_height, components);
+
+ this->Unlock(dest_mip);
+}
+
ObjectBase::Ref Texture2D::Create(ServiceLocator* service_locator) {
return ObjectBase::Ref();
}
@@ -164,4 +240,82 @@ ObjectBase::Ref TextureCUBE::Create(ServiceLocator* service_locator) {
return ObjectBase::Ref();
}
+void TextureCUBE::DrawImage(Bitmap* src_img,
+ int src_x, int src_y,
+ int src_width, int src_height,
+ int dst_x, int dst_y,
+ int dst_width, int dst_height,
+ CubeFace dest_face, int dest_mip) {
+ DCHECK(src_img->image_data());
+
+ int mip_length = std::max(1, edge_length() >> dest_mip);
+
+ // Clip source and destination rectangles to
+ // source and destination bitmaps.
+ // if src or dest rectangle is out of boundary,
+ // do nothing and return true.
+ if (!Bitmap::AdjustDrawImageBoundary(&src_x, &src_y,
+ &src_width, &src_height,
+ src_img->width(), src_img->height(),
+ &dst_x, &dst_y,
+ &dst_width, &dst_height,
+ mip_length, mip_length))
+ return;
+
+ unsigned int components = 0;
+ // check formats of source and dest images.
+ // format of source and dest should be the same.
+ if (src_img->format() != format()) {
+ O3D_ERROR(service_locator()) << "DrawImage does not support "
+ << "different formats.";
+ return;
+ }
+ // if src and dest are in the same size and drawImage is copying
+ // the entire bitmap on dest image, just perform memcpy.
+ if (src_x == 0 && src_y == 0 && dst_x == 0 && dst_y == 0 &&
+ src_img->width() == mip_length && src_img->height() == mip_length &&
+ src_width == src_img->width() && src_height == src_img->height() &&
+ dst_width == mip_length && dst_height == mip_length) {
+ // get mip data by lock method.
+ void* data = NULL;
+ if (!Lock(dest_face, dest_mip, &data))
+ return;
+
+ uint8* mip_data = static_cast<uint8*>(data);
+ unsigned int size = Bitmap::GetMipChainSize(mip_length, mip_length,
+ format(), 1);
+ memcpy(mip_data, src_img->image_data(), size);
+ this->Unlock(dest_face, dest_mip);
+
+ return;
+ }
+ if (src_img->format() == Texture::XRGB8 ||
+ src_img->format() == Texture::ARGB8) {
+ components = 4;
+ } else {
+ O3D_ERROR(service_locator()) << "DrawImage does not support format: "
+ << src_img->format() << " unless src and "
+ << "dest images are in the same size and "
+ << "copying the entire bitmap";
+ return;
+ }
+
+ void* data = NULL;
+ if (!Lock(dest_face, dest_mip, &data)) {
+ return;
+ }
+
+ uint8* src_img_data = src_img->image_data();
+ uint8* mip_data = static_cast<uint8*>(data);
+
+ Bitmap::BilinearInterpolateScale(src_img_data, src_x, src_y,
+ src_width, src_height,
+ src_img->width(), src_img->height(),
+ mip_data, dst_x, dst_y,
+ dst_width, dst_height,
+ mip_length, mip_length, components);
+
+ this->Unlock(dest_face, dest_mip);
+}
+
} // namespace o3d
diff --git a/o3d/core/cross/texture.h b/o3d/core/cross/texture.h
index a0808ec..49ff0d2 100644
--- a/o3d/core/cross/texture.h
+++ b/o3d/core/cross/texture.h
@@ -41,6 +41,7 @@
namespace o3d {
class Pack;
+class Bitmap;
// An abstract class for 2D textures that defines the interface for getting
// the dimensions of the texture and number of mipmap levels.
@@ -96,6 +97,24 @@ class Texture2D : public Texture {
// Reference to the RenderSurface object.
virtual RenderSurface::Ref GetRenderSurface(int mip_level, Pack* pack) = 0;
+ // Copy pixels from source bitmap to certain mip level.
+ // Scales if the width and height of source and dest do not match.
+ // Parameters:
+ // source_img: source bitmap which would be drawn.
+ // source_x: x-coordinate of the starting pixel in the source image.
+ // source_y: y-coordinate of the starting pixel in the source image.
+ // source_width: width of the source image to draw.
+ // source_height: Height of the source image to draw.
+ // dest_x: x-coordinate of the starting pixel in the dest image.
+ // dest_y: y-coordinate of the starting pixel in the dest image.
+ // dest_width: width of the dest image.
+ // dest_height: height of the dest image.
+ // dest_mip: on which mip level the sourceImg would be drawn.
+ void DrawImage(Bitmap* source_img, int source_x, int source_y,
+ int source_width, int source_height,
+ int dest_x, int dest_y,
+ int dest_width, int dest_height, int dest_mip);
+
protected:
// Returns true if the mip-map level has been locked.
bool IsLocked(unsigned int level) {
@@ -208,6 +227,25 @@ class TextureCUBE : public Texture {
int level,
Pack* pack) = 0;
+ // Copy pixels from source bitmap to certain mip level.
+ // Scales if the width and height of source and dest do not match.
+ // Parameters:
+ // source_img: source bitmap which would be drawn.
+ // source_x: x-coordinate of the starting pixel in the source image.
+ // source_y: y-coordinate of the starting pixel in the source image.
+ // source_width: width of the source image to draw.
+ // source_height: Height of the source image to draw.
+ // dest_x: x-coordinate of the starting pixel in the dest image.
+ // dest_y: y-coordinate of the starting pixel in the dest image.
+ // dest_width: width of the dest image.
+ // dest_height: height of the dest image.
+ // face: on which face the sourceImg would be drawn.
+ // dest_mip: on which mip level the sourceImg would be drawn.
+ void DrawImage(Bitmap* source_img, int source_x, int source_y,
+ int source_width, int source_height,
+ int dest_x, int dest_y, int dest_width,
+ int dest_height, CubeFace face, int dest_mip);
+
protected:
// Returns true if the mip-map level has been locked.
bool IsLocked(unsigned int level, CubeFace face) {
diff --git a/o3d/core/win/d3d9/renderer_d3d9.cc b/o3d/core/win/d3d9/renderer_d3d9.cc
index a2b9470..b4c7ac2 100644
--- a/o3d/core/win/d3d9/renderer_d3d9.cc
+++ b/o3d/core/win/d3d9/renderer_d3d9.cc
@@ -1663,13 +1663,13 @@ Texture2D::Ref RendererD3D9::CreatePlatformSpecificTexture2D(
Texture::Format format,
int levels,
bool enable_render_surfaces) {
- Bitmap bitmap;
- bitmap.set_format(format);
- bitmap.set_width(width);
- bitmap.set_height(height);
- bitmap.set_num_mipmaps(levels);
+ Bitmap::Ref bitmap = Bitmap::Ref(new Bitmap(service_locator()));
+ bitmap->set_format(format);
+ bitmap->set_width(width);
+ bitmap->set_height(height);
+ bitmap->set_num_mipmaps(levels);
return Texture2D::Ref(Texture2DD3D9::Create(service_locator(),
- &bitmap,
+ bitmap,
this,
enable_render_surfaces));
}
@@ -1681,14 +1681,14 @@ TextureCUBE::Ref RendererD3D9::CreatePlatformSpecificTextureCUBE(
Texture::Format format,
int levels,
bool enable_render_surfaces) {
- Bitmap bitmap;
- bitmap.set_format(format);
- bitmap.set_width(edge_length);
- bitmap.set_height(edge_length);
- bitmap.set_num_mipmaps(levels);
- bitmap.set_is_cubemap(true);
+ Bitmap::Ref bitmap = Bitmap::Ref(new Bitmap(service_locator()));
+ bitmap->set_format(format);
+ bitmap->set_width(edge_length);
+ bitmap->set_height(edge_length);
+ bitmap->set_num_mipmaps(levels);
+ bitmap->set_is_cubemap(true);
return TextureCUBE::Ref(TextureCUBED3D9::Create(service_locator(),
- &bitmap,
+ bitmap,
this,
enable_render_surfaces));
}
diff --git a/o3d/core/win/d3d9/texture_d3d9.cc b/o3d/core/win/d3d9/texture_d3d9.cc
index 1e8bad6..7477848 100644
--- a/o3d/core/win/d3d9/texture_d3d9.cc
+++ b/o3d/core/win/d3d9/texture_d3d9.cc
@@ -231,6 +231,7 @@ Texture2DD3D9::Texture2DD3D9(ServiceLocator* service_locator,
enable_render_surfaces),
d3d_texture_(tex) {
DCHECK(tex);
+ backing_bitmap_ = Bitmap::Ref(new Bitmap(service_locator));
}
// Attempts to create a IDirect3DTexture9 with the given specs. If the creation
@@ -263,8 +264,8 @@ Texture2DD3D9* Texture2DD3D9::Create(ServiceLocator* service_locator,
resize_to_pot,
enable_render_surfaces);
- texture->backing_bitmap_.SetFrom(bitmap);
- if (texture->backing_bitmap_.image_data()) {
+ texture->backing_bitmap_->SetFrom(bitmap);
+ if (texture->backing_bitmap_->image_data()) {
for (unsigned int i = 0; i < bitmap->num_mipmaps(); ++i) {
if (!texture->UpdateBackedMipLevel(i)) {
DLOG(ERROR) << "Failed to upload bitmap to texture.";
@@ -275,12 +276,12 @@ Texture2DD3D9* Texture2DD3D9::Create(ServiceLocator* service_locator,
mip_height = std::max(1U, mip_height >> 1);
}
if (!resize_to_pot)
- texture->backing_bitmap_.FreeData();
+ texture->backing_bitmap_->FreeData();
} else {
if (resize_to_pot) {
- texture->backing_bitmap_.AllocateData();
- memset(texture->backing_bitmap_.image_data(), 0,
- texture->backing_bitmap_.GetTotalSize());
+ texture->backing_bitmap_->AllocateData();
+ memset(texture->backing_bitmap_->image_data(), 0,
+ texture->backing_bitmap_->GetTotalSize());
}
}
@@ -294,11 +295,11 @@ Texture2DD3D9::~Texture2DD3D9() {
bool Texture2DD3D9::UpdateBackedMipLevel(unsigned int level) {
DCHECK_LT(level, static_cast<unsigned int>(levels()));
- DCHECK(backing_bitmap_.image_data());
- DCHECK_EQ(backing_bitmap_.width(), width());
- DCHECK_EQ(backing_bitmap_.height(), height());
- DCHECK_EQ(backing_bitmap_.format(), format());
- DCHECK_EQ(backing_bitmap_.num_mipmaps(), levels());
+ DCHECK(backing_bitmap_->image_data());
+ DCHECK_EQ(backing_bitmap_->width(), width());
+ DCHECK_EQ(backing_bitmap_->height(), height());
+ DCHECK_EQ(backing_bitmap_->format(), format());
+ DCHECK_EQ(backing_bitmap_->num_mipmaps(), levels());
unsigned int mip_width = std::max(1, width() >> level);
unsigned int mip_height = std::max(1, height() >> level);
@@ -322,7 +323,7 @@ bool Texture2DD3D9::UpdateBackedMipLevel(unsigned int level) {
// TODO: check that the returned pitch is what we expect.
const unsigned char *mip_data =
- backing_bitmap_.GetMipData(level, TextureCUBE::FACE_POSITIVE_X);
+ backing_bitmap_->GetMipData(level, TextureCUBE::FACE_POSITIVE_X);
if (resize_to_pot_) {
Bitmap::Scale(mip_width, mip_height, format(), mip_data,
rect_width, rect_height,
@@ -393,8 +394,8 @@ bool Texture2DD3D9::Lock(int level, void** texture_data) {
return false;
}
if (resize_to_pot_) {
- DCHECK(backing_bitmap_.image_data());
- *texture_data = backing_bitmap_.GetMipData(level,
+ DCHECK(backing_bitmap_->image_data());
+ *texture_data = backing_bitmap_->GetMipData(level,
TextureCUBE::FACE_POSITIVE_X);
locked_levels_ |= 1 << level;
return true;
@@ -459,7 +460,7 @@ bool Texture2DD3D9::OnResetDevice() {
bool resize_to_pot;
unsigned int mip_width, mip_height;
return HR(CreateTexture2DD3D9(renderer_d3d9,
- &backing_bitmap_,
+ backing_bitmap_,
render_surfaces_enabled(),
&resize_to_pot,
&mip_width,
@@ -487,6 +488,7 @@ TextureCUBED3D9::TextureCUBED3D9(ServiceLocator* service_locator,
resize_to_pot,
enable_render_surfaces),
d3d_cube_texture_(tex) {
+ backing_bitmap_ = Bitmap::Ref(new Bitmap(service_locator));
}
// Attempts to create a D3D9 CubeTexture with the given specs. If creation
@@ -519,8 +521,8 @@ TextureCUBED3D9* TextureCUBED3D9::Create(ServiceLocator* service_locator,
resize_to_pot,
enable_render_surfaces);
- texture->backing_bitmap_.SetFrom(bitmap);
- if (texture->backing_bitmap_.image_data()) {
+ texture->backing_bitmap_->SetFrom(bitmap);
+ if (texture->backing_bitmap_->image_data()) {
for (int face = 0; face < 6; ++face) {
unsigned int mip_edge = edge;
for (unsigned int i = 0; i < bitmap->num_mipmaps(); ++i) {
@@ -533,12 +535,12 @@ TextureCUBED3D9* TextureCUBED3D9::Create(ServiceLocator* service_locator,
}
}
if (!resize_to_pot)
- texture->backing_bitmap_.FreeData();
+ texture->backing_bitmap_->FreeData();
} else {
if (resize_to_pot) {
- texture->backing_bitmap_.AllocateData();
- memset(texture->backing_bitmap_.image_data(), 0,
- texture->backing_bitmap_.GetTotalSize());
+ texture->backing_bitmap_->AllocateData();
+ memset(texture->backing_bitmap_->image_data(), 0,
+ texture->backing_bitmap_->GetTotalSize());
}
}
@@ -563,12 +565,12 @@ TextureCUBED3D9::~TextureCUBED3D9() {
bool TextureCUBED3D9::UpdateBackedMipLevel(unsigned int level,
TextureCUBE::CubeFace face) {
DCHECK_LT(level, static_cast<unsigned int>(levels()));
- DCHECK(backing_bitmap_.image_data());
- DCHECK(backing_bitmap_.is_cubemap());
- DCHECK_EQ(backing_bitmap_.width(), edge_length());
- DCHECK_EQ(backing_bitmap_.height(), edge_length());
- DCHECK_EQ(backing_bitmap_.format(), format());
- DCHECK_EQ(backing_bitmap_.num_mipmaps(), levels());
+ DCHECK(backing_bitmap_->image_data());
+ DCHECK(backing_bitmap_->is_cubemap());
+ DCHECK_EQ(backing_bitmap_->width(), edge_length());
+ DCHECK_EQ(backing_bitmap_->height(), edge_length());
+ DCHECK_EQ(backing_bitmap_->format(), format());
+ DCHECK_EQ(backing_bitmap_->num_mipmaps(), levels());
unsigned int mip_edge = std::max(1, edge_length() >> level);
unsigned int rect_edge = mip_edge;
@@ -590,7 +592,7 @@ bool TextureCUBED3D9::UpdateBackedMipLevel(unsigned int level,
DCHECK(out_rect.pBits);
// TODO: check that the returned pitch is what we expect.
- const unsigned char *mip_data = backing_bitmap_.GetMipData(level, face);
+ const unsigned char *mip_data = backing_bitmap_->GetMipData(level, face);
if (resize_to_pot_) {
Bitmap::Scale(mip_edge, mip_edge, format(), mip_data,
rect_edge, rect_edge,
@@ -664,8 +666,8 @@ bool TextureCUBED3D9::Lock(CubeFace face, int level, void** texture_data) {
return false;
}
if (resize_to_pot_) {
- DCHECK(backing_bitmap_.image_data());
- *texture_data = backing_bitmap_.GetMipData(level, face);
+ DCHECK(backing_bitmap_->image_data());
+ *texture_data = backing_bitmap_->GetMipData(level, face);
locked_levels_[face] |= 1 << level;
return true;
} else {
@@ -731,7 +733,7 @@ bool TextureCUBED3D9::OnResetDevice() {
bool resize_to_pot;
unsigned int mip_edge;
return HR(CreateTextureCUBED3D9(renderer_d3d9,
- &backing_bitmap_,
+ backing_bitmap_,
render_surfaces_enabled(),
&resize_to_pot,
&mip_edge,
diff --git a/o3d/core/win/d3d9/texture_d3d9.h b/o3d/core/win/d3d9/texture_d3d9.h
index fe954a2..8a19913 100644
--- a/o3d/core/win/d3d9/texture_d3d9.h
+++ b/o3d/core/win/d3d9/texture_d3d9.h
@@ -110,7 +110,7 @@ class Texture2DD3D9 : public Texture2D {
CComPtr<IDirect3DTexture9> d3d_texture_;
// A bitmap used to back the NPOT textures on POT-only hardware.
- Bitmap backing_bitmap_;
+ Bitmap::Ref backing_bitmap_;
DISALLOW_COPY_AND_ASSIGN(Texture2DD3D9);
};
@@ -178,7 +178,7 @@ class TextureCUBED3D9 : public TextureCUBE {
CComPtr<IDirect3DCubeTexture9> d3d_cube_texture_;
// A bitmap used to back the NPOT textures on POT-only hardware.
- Bitmap backing_bitmap_;
+ Bitmap::Ref backing_bitmap_;
DISALLOW_COPY_AND_ASSIGN(TextureCUBED3D9);
};