| 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 | 
|---|