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

Side by Side Diff: core/cross/bitmap.cc

Issue 150058: expose bitmap in js. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/o3d/
Patch Set: '' Created 11 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « core/cross/bitmap.h ('k') | core/cross/bitmap_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2009, Google Inc. 2 * Copyright 2009, Google Inc.
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are 6 * modification, are permitted provided that the following conditions are
7 * met: 7 * met:
8 * 8 *
9 * * Redistributions of source code must retain the above copyright 9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
(...skipping 19 matching lines...) Expand all
30 */ 30 */
31 31
32 32
33 // This file contains the image file codec operations for OpenGL texture 33 // This file contains the image file codec operations for OpenGL texture
34 // loading. Trying to keep this class as independent from the OpenGL API in 34 // loading. Trying to keep this class as independent from the OpenGL API in
35 // case they need retargeting later on. 35 // case they need retargeting later on.
36 36
37 // The precompiled header must appear before anything else. 37 // The precompiled header must appear before anything else.
38 #include "core/cross/precompile.h" 38 #include "core/cross/precompile.h"
39 39
40 #include "core/cross/bitmap.h"
40 #include <cstring> 41 #include <cstring>
42 #include <cmath>
41 #include <sys/stat.h> 43 #include <sys/stat.h>
42 #include "core/cross/bitmap.h"
43 #include "utils/cross/file_path_utils.h" 44 #include "utils/cross/file_path_utils.h"
44 #include "base/file_path.h" 45 #include "base/file_path.h"
45 #include "base/file_util.h" 46 #include "base/file_util.h"
46 #include "import/cross/raw_data.h" 47 #include "import/cross/raw_data.h"
47 #include "import/cross/memory_buffer.h" 48 #include "import/cross/memory_buffer.h"
48 #include "import/cross/memory_stream.h" 49 #include "import/cross/memory_stream.h"
49 50
50 using file_util::OpenFile; 51 using file_util::OpenFile;
51 using file_util::CloseFile; 52 using file_util::CloseFile;
52 using file_util::GetFileSize; 53 using file_util::GetFileSize;
53 54
55 namespace {
56 static const double kEpsilon = 0.0001;
57 } // anonymous namespace.
58
54 namespace o3d { 59 namespace o3d {
55 60
61 O3D_DEFN_CLASS(Bitmap, ParamObject);
62
63 Bitmap::Bitmap(ServiceLocator* service_locator)
64 : ParamObject(service_locator),
65 image_data_(NULL),
66 format_(Texture::UNKNOWN_FORMAT),
67 width_(0),
68 height_(0),
69 num_mipmaps_(0),
70 is_cubemap_(false) {}
71
56 // Gets the size of the buffer containing a an image, given its width, height 72 // Gets the size of the buffer containing a an image, given its width, height
57 // and format. 73 // and format.
58 unsigned int Bitmap::GetBufferSize(unsigned int width, 74 unsigned int Bitmap::GetBufferSize(unsigned int width,
59 unsigned int height, 75 unsigned int height,
60 Texture::Format format) { 76 Texture::Format format) {
61 DCHECK(CheckImageDimensions(width, height)); 77 DCHECK(CheckImageDimensions(width, height));
62 unsigned int pixels = width * height; 78 unsigned int pixels = width * height;
63 switch (format) { 79 switch (format) {
64 case Texture::XRGB8: 80 case Texture::XRGB8:
65 case Texture::ARGB8: 81 case Texture::ARGB8:
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 const uint8* data = raw_data->GetData(); 270 const uint8* data = raw_data->GetData();
255 if (!data) { 271 if (!data) {
256 return false; 272 return false;
257 } 273 }
258 274
259 MemoryReadStream stream(data, raw_data->GetLength()); 275 MemoryReadStream stream(data, raw_data->GetLength());
260 276
261 return LoadFromStream(&stream, filename, file_type, generate_mipmaps); 277 return LoadFromStream(&stream, filename, file_type, generate_mipmaps);
262 } 278 }
263 279
280 void Bitmap::DrawImage(Bitmap* src_img,
281 int src_x, int src_y,
282 int src_width, int src_height,
283 int dst_x, int dst_y,
284 int dst_width, int dst_height) {
285 DCHECK(src_img->image_data());
286 DCHECK(image_data());
287
288 // Clip source and destination rectangles to
289 // source and destination bitmaps.
290 // if src or dest rectangle is out of boundary,
291 // do nothing and return.
292 if (!AdjustDrawImageBoundary(&src_x, &src_y,
293 &src_width, &src_height,
294 src_img->width_, src_img->height_,
295 &dst_x, &dst_y,
296 &dst_width, &dst_height,
297 width_, height_))
298 return;
299
300 unsigned int components = 0;
301 // check formats of source and dest images.
302 // format of source and dest should be the same.
303 if (src_img->format_ != format_) {
304 O3D_ERROR(service_locator()) << "DrawImage does not support "
305 << "different formats.";
306 return;
307 }
308 // if src and dest are in the same size and drawImage is copying
309 // the entire bitmap on dest image, just perform memcpy.
310 if (src_x == 0 && src_y == 0 && dst_x == 0 && dst_y == 0 &&
311 src_img->width_ == width_ && src_img->height_ == height_ &&
312 src_width == src_img->width_ && src_height == src_img->height_ &&
313 dst_width == width_ && dst_height == height_) {
314 memcpy(image_data(), src_img->image_data(), GetTotalSize());
315 return;
316 }
317
318 // if drawImage is not copying the whole bitmap, we need to check
319 // the format. currently only support XRGB8 and ARGB8
320 if (src_img->format_ == Texture::XRGB8 ||
321 src_img->format_ == Texture::ARGB8) {
322 components = 4;
323 } else {
324 O3D_ERROR(service_locator()) << "DrawImage does not support format: "
325 << src_img->format_ << " unless src and "
326 << "dest images are in the same size and "
327 << "copying the entire bitmap";
328 return;
329 }
330
331 unsigned char* src_img_data = src_img->image_data();
332 unsigned char* dst_img_data = image_data();
333
334 // crop part of image from src img, scale it in
335 // bilinear interpolation fashion, and paste it
336 // on dst img.
337 BilinearInterpolateScale(src_img_data, src_x, src_y,
338 src_width, src_height,
339 src_img->width_, src_img->height_,
340 dst_img_data, dst_x, dst_y,
341 dst_width, dst_height,
342 width_, height_, components);
343 }
344
345 // static utility function used by DrawImage in bitmap and textures.
346 // in this function, positions are converted to 4th-quadrant, which
347 // means origin locates left-up corner.
348 void Bitmap::BilinearInterpolateScale(const uint8* src_img_data,
349 int src_x, int src_y,
350 int src_width, int src_height,
351 int src_img_width, int src_img_height,
352 uint8* dest_img_data,
353 int dest_x, int dest_y,
354 int dest_width, int dest_height,
355 int dest_img_width, int dest_img_height,
356 int components) {
357 for (int i = 0; i < std::abs(dest_width); i++) {
358 // x is the iterator of dest_width in dest_img.
359 // change x to negative if dest_width is negative.
360 int x = i;
361 if (dest_width < 0)
362 x = -i;
363
364 // calculate corresponding coordinate in src_img.
365 double base_x = i * (std::abs(src_width) - 1) /
366 static_cast<double>(std::abs(dest_width) - 1);
367 // base_floor_x is the iterator of src_width in src_img.
368 // change base_x to negative if src_width is negative.
369 if (src_width < 0)
370 base_x = -base_x;
371 int base_floor_x = static_cast<int>(std::floor(base_x));
372
373 for (int j = 0; j < std::abs(dest_height); j++) {
374 // y is the iterator of dest_height in dest_img.
375 // change y to negative if dest_height is negative.
376 int y = j;
377 if (dest_height < 0)
378 y = -j;
379
380 // calculate coresponding coordinate in src_img.
381 double base_y = j * (std::abs(src_height) - 1) /
382 static_cast<double>(std::abs(dest_height) - 1);
383 // change base_y to negative if src_height is negative.
384 if (src_height < 0)
385 base_y = -base_y;
386 int base_floor_y = static_cast<int>(std::floor(base_y));
387
388 for (unsigned int c = 0; c < components; c++) {
389 // if base_x and base_y are integers, which means this point
390 // exists in src_img, just copy the original values.
391 if (base_x - base_floor_x < kEpsilon &&
392 base_y - base_floor_y < kEpsilon) {
393 dest_img_data[((dest_img_height - (y + dest_y) - 1) *
394 dest_img_width + dest_x + x) * components + c] =
395 src_img_data[((src_img_height - (base_floor_y + src_y) - 1) *
396 src_img_width + src_x + base_floor_x) * components + c];
397 continue;
398 }
399
400 // get four nearest neighbors of point (base_x, base_y) from src img.
401 uint8 src_neighbor_11, src_neighbor_21,
402 src_neighbor_12, src_neighbor_22;
403 src_neighbor_11 = src_img_data[((src_img_height - (base_floor_y +
404 src_y) - 1) * src_img_width + src_x +
405 base_floor_x) * components + c];
406 // if base_x exists in src img. set src_neighbor_21 to src_neighbor_11
407 // so the interpolation result would remain src_neighbor_11.
408 if (base_x - base_floor_x < kEpsilon)
409 src_neighbor_21 = src_neighbor_11;
410 else
411 src_neighbor_21 = src_img_data[((src_img_height - (base_floor_y +
412 src_y) - 1) * src_img_width + src_x +
413 base_floor_x + 1) * components + c];
414 // if base_y exists in src img. set src_neighbor_12 to src_neighbor_11
415 // so the interpolation result would remain src_neighbor_11.
416 if (base_y - base_floor_y < kEpsilon)
417 src_neighbor_12 = src_neighbor_11;
418 else
419 src_neighbor_12 = src_img_data[((src_img_height - (base_floor_y +
420 src_y) - 2) * src_img_width + src_x +
421 base_floor_x) * components + c];
422
423 if (base_x - base_floor_x < kEpsilon)
424 src_neighbor_22 = src_neighbor_21;
425 else if (base_y - base_floor_y < kEpsilon)
426 src_neighbor_22 = src_neighbor_12;
427 else
428 src_neighbor_22 = src_img_data[((src_img_height - (base_floor_y +
429 src_y) - 2) * src_img_width + src_x +
430 base_floor_x + 1) * components + c];
431
432 // calculate interpolated value.
433 double interpolatedValue = (1 - (base_y - base_floor_y)) *
434 ((base_x - base_floor_x) *
435 src_neighbor_21 +
436 (1 - (base_x - base_floor_x)) *
437 src_neighbor_11) +
438 (base_y - base_floor_y) *
439 ((base_x - base_floor_x) *
440 src_neighbor_22 +
441 (1 - (base_x - base_floor_x)) *
442 src_neighbor_12);
443
444 // assign the nearest integer of interpolatedValue to dest_img_data.
445 dest_img_data[((dest_img_height - (y + dest_y) - 1) * dest_img_width +
446 dest_x + x) * components + c] =
447 static_cast<uint8>(interpolatedValue + 0.5);
448 }
449 }
450 }
451 }
264 452
265 Bitmap::ImageFileType Bitmap::GetFileTypeFromFilename(const char *filename) { 453 Bitmap::ImageFileType Bitmap::GetFileTypeFromFilename(const char *filename) {
266 // Convert the filename to lower case for matching. 454 // Convert the filename to lower case for matching.
267 // NOTE: Surprisingly, "tolower" is not in the std namespace. 455 // NOTE: Surprisingly, "tolower" is not in the std namespace.
268 String name(filename); 456 String name(filename);
269 std::transform(name.begin(), name.end(), name.begin(), ::tolower); 457 std::transform(name.begin(), name.end(), name.begin(), ::tolower);
270 458
271 // Dispatch loading functions based on filename extensions. 459 // Dispatch loading functions based on filename extensions.
272 String::size_type i = name.rfind("."); 460 String::size_type i = name.rfind(".");
273 if (i == String::npos) { 461 if (i == String::npos) {
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after
567 DCHECK_LT(base_x, src_width); 755 DCHECK_LT(base_x, src_width);
568 for (unsigned int c = 0; c < components; ++c) { 756 for (unsigned int c = 0; c < components; ++c) {
569 dst[(y * dst_width + x) * components + c] = 757 dst[(y * dst_width + x) * components + c] =
570 src[(base_y * src_width + base_x) * components + c]; 758 src[(base_y * src_width + base_x) * components + c];
571 } 759 }
572 } 760 }
573 } 761 }
574 return true; 762 return true;
575 } 763 }
576 764
765 // Adjust boundaries when using DrawImage function in bitmap or texture.
766 bool Bitmap::AdjustDrawImageBoundary(int* src_x, int* src_y,
767 int* src_width, int* src_height,
768 int src_bmp_width, int src_bmp_height,
769 int* dest_x, int* dest_y,
770 int* dest_width, int* dest_height,
771 int dest_bmp_width, int dest_bmp_height) {
772 // if src or dest rectangle is out of boundaries, do nothing.
773 if ((*src_x < 0 && *src_x + *src_width <= 0) ||
774 (*src_y < 0 && *src_y + *src_height <= 0) ||
775 (*dest_x < 0 && *dest_x + *dest_width <= 0) ||
776 (*dest_y < 0 && *dest_y + *dest_height <= 0) ||
777 (*src_x >= src_bmp_width &&
778 *src_x + *src_width >= src_bmp_width - 1) ||
779 (*src_y >= src_bmp_height &&
780 *src_y + *src_height >= src_bmp_height - 1) ||
781 (*dest_x >= dest_bmp_width &&
782 *dest_x + *dest_width >= dest_bmp_width - 1) ||
783 (*dest_y >= dest_bmp_height &&
784 *dest_y + *dest_height >= dest_bmp_height - 1))
785 return false;
786
787 // if start points are negative.
788 // check whether src_x is negative.
789 if (!AdjustDrawImageBoundHelper(src_x, dest_x,
790 src_width, dest_width, src_bmp_width))
791 return false;
792 // check whether dest_x is negative.
793 if (!AdjustDrawImageBoundHelper(dest_x, src_x,
794 dest_width, src_width, dest_bmp_width))
795 return false;
796 // check whether src_y is negative.
797 if (!AdjustDrawImageBoundHelper(src_y, dest_y,
798 src_height, dest_height, src_bmp_height))
799 return false;
800 // check whether dest_y is negative.
801 if (!AdjustDrawImageBoundHelper(dest_y, src_y,
802 dest_height, src_height, dest_bmp_height))
803 return false;
804
805 // check any width or height becomes negative after adjustment.
806 if (*src_width == 0 || *src_height == 0 ||
807 *dest_width == 0 || *dest_height == 0) {
808 return false;
809 }
810
811 return true;
812 }
813
814 // utility function called in AdjustDrawImageBoundary.
815 // help to adjust a specific dimension,
816 // if start point or ending point is out of boundary.
817 bool Bitmap::AdjustDrawImageBoundHelper(int* src_a, int* dest_a,
818 int* src_length, int* dest_length,
819 int src_bmp_length) {
820 if (*src_length == 0 || *dest_length == 0)
821 return false;
822
823 // check if start point is out of boundary.
824 // if src_a < 0, src_length must be positive.
825 if (*src_a < 0) {
826 int src_length_delta = 0 - *src_a;
827 *dest_a = *dest_a + (*dest_length) * src_length_delta / (*src_length);
828 *dest_length = *dest_length - (*dest_length) *
829 src_length_delta / (*src_length);
830 *src_length = *src_length - src_length_delta;
831 *src_a = 0;
832 }
833 // if src_a >= src_bmp_width, src_length must be negative.
834 if (*src_a >= src_bmp_length) {
835 int src_length_delta = *src_a - (src_bmp_length - 1);
836 *dest_a = *dest_a - (*dest_length) * src_length_delta / (*src_length);
837 *dest_length = *dest_length - (*dest_length) *
838 src_length_delta / *src_length;
839 *src_length = *src_length - src_length_delta;
840 *src_a = src_bmp_length - 1;
841 }
842
843 if (*src_length == 0 || *dest_length == 0)
844 return false;
845 // check whether start point + related length is out of boundary.
846 // if src_a + src_length > src_bmp_length, src_length must be positive.
847 if (*src_a + *src_length > src_bmp_length) {
848 int src_length_delta = *src_length - (src_bmp_length - *src_a);
849 *dest_length = *dest_length - (*dest_length) *
850 src_length_delta / (*src_length);
851 *src_length = *src_length - src_length_delta;
852 }
853 // if src_a + src_length < -1, src_length must be negative.
854 if (*src_a + *src_length < -1) {
855 int src_length_delta = 0 - (*src_a + *src_length);
856 *dest_length = *dest_length + (*dest_length) *
857 src_length_delta / (*src_length);
858 *src_length = *src_length + src_length_delta;
859 }
860
861 return true;
862 }
863
577 // Checks that all the alpha values are 1.0 864 // Checks that all the alpha values are 1.0
578 bool Bitmap::CheckAlphaIsOne() const { 865 bool Bitmap::CheckAlphaIsOne() const {
579 if (!image_data()) 866 if (!image_data())
580 return false; 867 return false;
581 868
582 switch (format()) { 869 switch (format()) {
583 case Texture::XRGB8: 870 case Texture::XRGB8:
584 return true; 871 return true;
585 case Texture::ARGB8: { 872 case Texture::ARGB8: {
586 int faces = is_cubemap() ? 6 : 1; 873 int faces = is_cubemap() ? 6 : 1;
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
675 } 962 }
676 } 963 }
677 break; 964 break;
678 } 965 }
679 case Texture::UNKNOWN_FORMAT: 966 case Texture::UNKNOWN_FORMAT:
680 return false; 967 return false;
681 } 968 }
682 return true; 969 return true;
683 } 970 }
684 971
972 ObjectBase::Ref Bitmap::Create(ServiceLocator* service_locator) {
973 return ObjectBase::Ref(new Bitmap(service_locator));
974 }
975
685 } // namespace o3d 976 } // namespace o3d
OLDNEW
« no previous file with comments | « core/cross/bitmap.h ('k') | core/cross/bitmap_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698