| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "gfx/codec/png_codec.h" | 5 #include "gfx/codec/png_codec.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/scoped_ptr.h" | 8 #include "base/scoped_ptr.h" |
| 9 #include "third_party/skia/include/core/SkBitmap.h" | 9 #include "third_party/skia/include/core/SkBitmap.h" |
| 10 #include "third_party/skia/include/core/SkUnPreMultiply.h" | 10 #include "third_party/skia/include/core/SkUnPreMultiply.h" |
| (...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 534 unsigned char* rgb, bool* is_opaque) { | 534 unsigned char* rgb, bool* is_opaque) { |
| 535 for (int x = 0; x < pixel_width; x++) { | 535 for (int x = 0; x < pixel_width; x++) { |
| 536 const unsigned char* pixel_in = &bgra[x * 4]; | 536 const unsigned char* pixel_in = &bgra[x * 4]; |
| 537 unsigned char* pixel_out = &rgb[x * 3]; | 537 unsigned char* pixel_out = &rgb[x * 3]; |
| 538 pixel_out[0] = pixel_in[2]; | 538 pixel_out[0] = pixel_in[2]; |
| 539 pixel_out[1] = pixel_in[1]; | 539 pixel_out[1] = pixel_in[1]; |
| 540 pixel_out[2] = pixel_in[0]; | 540 pixel_out[2] = pixel_in[0]; |
| 541 } | 541 } |
| 542 } | 542 } |
| 543 | 543 |
| 544 // Automatically destroys the given write structs on destruction to make | 544 // The type of functions usable for converting between pixel formats. |
| 545 // cleanup and error handling code cleaner. | 545 typedef void (*FormatConverter)(const unsigned char* in, int w, |
| 546 class PngWriteStructDestroyer { | 546 unsigned char* out, bool* is_opaque); |
| 547 public: | 547 |
| 548 PngWriteStructDestroyer(png_struct** ps, png_info** pi) : ps_(ps), pi_(pi) { | 548 // libpng uses a wacky setjmp-based API, which makes the compiler nervous. |
| 549 // We constrain all of the calls we make to libpng where the setjmp() is in |
| 550 // place to this function. |
| 551 // Returns true on success. |
| 552 bool DoLibpngWrite(png_struct* png_ptr, png_info* info_ptr, |
| 553 PngEncoderState* state, |
| 554 int width, int height, int row_byte_width, |
| 555 const unsigned char* input, |
| 556 int png_output_color_type, int output_color_components, |
| 557 FormatConverter converter) { |
| 558 // Make sure to not declare any locals here -- locals in the presence |
| 559 // of setjmp() in C++ code makes gcc complain. |
| 560 |
| 561 if (setjmp(png_jmpbuf(png_ptr))) |
| 562 return false; |
| 563 |
| 564 // Set our callback for libpng to give us the data. |
| 565 png_set_write_fn(png_ptr, state, EncoderWriteCallback, NULL); |
| 566 |
| 567 png_set_IHDR(png_ptr, info_ptr, width, height, 8, png_output_color_type, |
| 568 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, |
| 569 PNG_FILTER_TYPE_DEFAULT); |
| 570 png_write_info(png_ptr, info_ptr); |
| 571 |
| 572 if (!converter) { |
| 573 // No conversion needed, give the data directly to libpng. |
| 574 for (int y = 0; y < height; y ++) { |
| 575 png_write_row(png_ptr, |
| 576 const_cast<unsigned char*>(&input[y * row_byte_width])); |
| 577 } |
| 578 } else { |
| 579 // Needs conversion using a separate buffer. |
| 580 unsigned char* row = new unsigned char[width * output_color_components]; |
| 581 for (int y = 0; y < height; y ++) { |
| 582 converter(&input[y * row_byte_width], width, row, NULL); |
| 583 png_write_row(png_ptr, row); |
| 584 } |
| 585 delete[] row; |
| 549 } | 586 } |
| 550 ~PngWriteStructDestroyer() { | |
| 551 png_destroy_write_struct(ps_, pi_); | |
| 552 } | |
| 553 private: | |
| 554 png_struct** ps_; | |
| 555 png_info** pi_; | |
| 556 | 587 |
| 557 DISALLOW_EVIL_CONSTRUCTORS(PngWriteStructDestroyer); | 588 png_write_end(png_ptr, info_ptr); |
| 558 }; | 589 return true; |
| 590 } |
| 559 | 591 |
| 560 } // namespace | 592 } // namespace |
| 561 | 593 |
| 562 // static | 594 // static |
| 563 bool PNGCodec::Encode(const unsigned char* input, ColorFormat format, | 595 bool PNGCodec::Encode(const unsigned char* input, ColorFormat format, |
| 564 int w, int h, int row_byte_width, | 596 int w, int h, int row_byte_width, |
| 565 bool discard_transparency, | 597 bool discard_transparency, |
| 566 std::vector<unsigned char>* output) { | 598 std::vector<unsigned char>* output) { |
| 567 // Run to convert an input row into the output row format, NULL means no | 599 // Run to convert an input row into the output row format, NULL means no |
| 568 // conversion is necessary. | 600 // conversion is necessary. |
| 569 void (*converter)(const unsigned char* in, int w, unsigned char* out, | 601 FormatConverter converter = NULL; |
| 570 bool* is_opaque) = NULL; | |
| 571 | 602 |
| 572 int input_color_components, output_color_components; | 603 int input_color_components, output_color_components; |
| 573 int png_output_color_type; | 604 int png_output_color_type; |
| 574 switch (format) { | 605 switch (format) { |
| 575 case FORMAT_RGB: | 606 case FORMAT_RGB: |
| 576 input_color_components = 3; | 607 input_color_components = 3; |
| 577 output_color_components = 3; | 608 output_color_components = 3; |
| 578 png_output_color_type = PNG_COLOR_TYPE_RGB; | 609 png_output_color_type = PNG_COLOR_TYPE_RGB; |
| 579 discard_transparency = false; | 610 discard_transparency = false; |
| 580 break; | 611 break; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 628 | 659 |
| 629 png_struct* png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, | 660 png_struct* png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, |
| 630 NULL, NULL, NULL); | 661 NULL, NULL, NULL); |
| 631 if (!png_ptr) | 662 if (!png_ptr) |
| 632 return false; | 663 return false; |
| 633 png_info* info_ptr = png_create_info_struct(png_ptr); | 664 png_info* info_ptr = png_create_info_struct(png_ptr); |
| 634 if (!info_ptr) { | 665 if (!info_ptr) { |
| 635 png_destroy_write_struct(&png_ptr, NULL); | 666 png_destroy_write_struct(&png_ptr, NULL); |
| 636 return false; | 667 return false; |
| 637 } | 668 } |
| 638 PngWriteStructDestroyer destroyer(&png_ptr, &info_ptr); | |
| 639 | 669 |
| 640 if (setjmp(png_jmpbuf(png_ptr))) { | 670 PngEncoderState state(output); |
| 641 // The destroyer will ensure that the structures are cleaned up in this | 671 bool success = DoLibpngWrite(png_ptr, info_ptr, &state, |
| 642 // case, even though we may get here as a jump from random parts of the | 672 w, h, row_byte_width, input, |
| 643 // PNG library called below. | 673 png_output_color_type, output_color_components, |
| 644 return false; | 674 converter); |
| 645 } | 675 png_destroy_write_struct(&png_ptr, &info_ptr); |
| 646 | 676 |
| 647 // Set our callback for libpng to give us the data. | 677 return success; |
| 648 PngEncoderState state(output); | |
| 649 png_set_write_fn(png_ptr, &state, EncoderWriteCallback, NULL); | |
| 650 | |
| 651 png_set_IHDR(png_ptr, info_ptr, w, h, 8, png_output_color_type, | |
| 652 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, | |
| 653 PNG_FILTER_TYPE_DEFAULT); | |
| 654 png_write_info(png_ptr, info_ptr); | |
| 655 | |
| 656 if (!converter) { | |
| 657 // No conversion needed, give the data directly to libpng. | |
| 658 for (int y = 0; y < h; y ++) { | |
| 659 png_write_row(png_ptr, | |
| 660 const_cast<unsigned char*>(&input[y * row_byte_width])); | |
| 661 } | |
| 662 } else { | |
| 663 // Needs conversion using a separate buffer. | |
| 664 unsigned char* row = new unsigned char[w * output_color_components]; | |
| 665 for (int y = 0; y < h; y ++) { | |
| 666 converter(&input[y * row_byte_width], w, row, NULL); | |
| 667 png_write_row(png_ptr, row); | |
| 668 } | |
| 669 delete[] row; | |
| 670 } | |
| 671 | |
| 672 png_write_end(png_ptr, info_ptr); | |
| 673 return true; | |
| 674 } | 678 } |
| 675 | 679 |
| 676 // static | 680 // static |
| 677 bool PNGCodec::EncodeBGRASkBitmap(const SkBitmap& input, | 681 bool PNGCodec::EncodeBGRASkBitmap(const SkBitmap& input, |
| 678 bool discard_transparency, | 682 bool discard_transparency, |
| 679 std::vector<unsigned char>* output) { | 683 std::vector<unsigned char>* output) { |
| 680 static const int bbp = 4; | 684 static const int bbp = 4; |
| 681 | 685 |
| 682 SkAutoLockPixels lock_input(input); | 686 SkAutoLockPixels lock_input(input); |
| 683 DCHECK(input.empty() || input.bytesPerPixel() == bbp); | 687 DCHECK(input.empty() || input.bytesPerPixel() == bbp); |
| 684 | 688 |
| 685 return Encode(reinterpret_cast<unsigned char*>(input.getAddr32(0, 0)), | 689 return Encode(reinterpret_cast<unsigned char*>(input.getAddr32(0, 0)), |
| 686 FORMAT_SkBitmap, input.width(), input.height(), | 690 FORMAT_SkBitmap, input.width(), input.height(), |
| 687 input.width() * bbp, discard_transparency, output); | 691 input.width() * bbp, discard_transparency, output); |
| 688 } | 692 } |
| 689 | 693 |
| 690 } // namespace gfx | 694 } // namespace gfx |
| OLD | NEW |