| /* | 
 |  * Copyright 2012 Google Inc. | 
 |  * | 
 |  * Use of this source code is governed by a BSD-style license that can be | 
 |  * found in the LICENSE file. | 
 |  */ | 
 |  | 
 | #include "picture_utils.h" | 
 | #include "SkBitmap.h" | 
 | #include "SkColorPriv.h" | 
 | #include "SkHalf.h" | 
 | #include "SkImageEncoder.h" | 
 | #include "SkOSFile.h" | 
 | #include "SkOSPath.h" | 
 | #include "SkPM4fPriv.h" | 
 | #include "SkPicture.h" | 
 | #include "SkStream.h" | 
 | #include "SkString.h" | 
 |  | 
 | #include "sk_tool_utils.h" | 
 |  | 
 | namespace sk_tools { | 
 |     void force_all_opaque(const SkBitmap& bitmap) { | 
 |         SkASSERT(kN32_SkColorType == bitmap.colorType()); | 
 |         if (kN32_SkColorType == bitmap.colorType()) { | 
 |             return; | 
 |         } | 
 |  | 
 |         SkAutoLockPixels lock(bitmap); | 
 |         for (int y = 0; y < bitmap.height(); y++) { | 
 |             for (int x = 0; x < bitmap.width(); x++) { | 
 |                 *bitmap.getAddr32(x, y) |= (SK_A32_MASK << SK_A32_SHIFT); | 
 |             } | 
 |         } | 
 |     } | 
 |  | 
 |     void replace_char(SkString* str, const char oldChar, const char newChar) { | 
 |         if (nullptr == str) { | 
 |             return; | 
 |         } | 
 |         for (size_t i = 0; i < str->size(); ++i) { | 
 |             if (oldChar == str->operator[](i)) { | 
 |                 str->operator[](i) = newChar; | 
 |             } | 
 |         } | 
 |     } | 
 |  | 
 |     bool is_percentage(const char* const string) { | 
 |         SkString skString(string); | 
 |         return skString.endsWith("%"); | 
 |     } | 
 |  | 
 |     void setup_bitmap(SkBitmap* bitmap, int width, int height) { | 
 |         bitmap->allocN32Pixels(width, height); | 
 |         bitmap->eraseColor(SK_ColorTRANSPARENT); | 
 |     } | 
 |  | 
 |     bool write_bitmap_to_disk(const SkBitmap& bm, const SkString& dirPath, | 
 |                               const char *subdirOrNull, const SkString& baseName) { | 
 |         SkString partialPath; | 
 |         if (subdirOrNull) { | 
 |             partialPath = SkOSPath::Join(dirPath.c_str(), subdirOrNull); | 
 |             sk_mkdir(partialPath.c_str()); | 
 |         } else { | 
 |             partialPath.set(dirPath); | 
 |         } | 
 |         SkString fullPath = SkOSPath::Join(partialPath.c_str(), baseName.c_str()); | 
 |         if (sk_tool_utils::EncodeImageToFile(fullPath.c_str(), bm, SkEncodedImageFormat::kPNG, 100)) { | 
 |             return true; | 
 |         } else { | 
 |             SkDebugf("Failed to write the bitmap to %s.\n", fullPath.c_str()); | 
 |             return false; | 
 |         } | 
 |     } | 
 |  | 
 |     sk_sp<SkData> encode_bitmap_for_png(SkBitmap bitmap) { | 
 |         const int w = bitmap.width(), | 
 |                 h = bitmap.height(); | 
 |         // PNG wants unpremultiplied 8-bit RGBA pixels (16-bit could work fine too). | 
 |         // We leave the gamma of these bytes unspecified, to continue the status quo, | 
 |         // which we think generally is to interpret them as sRGB. | 
 |  | 
 |         SkAutoTMalloc<uint32_t> rgba(w*h); | 
 |  | 
 |         auto srgbColorSpace = SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named); | 
 |         if (bitmap. colorType() ==  kN32_SkColorType && | 
 |             bitmap.colorSpace() == srgbColorSpace.get()) { | 
 |             // These are premul sRGB 8-bit pixels in SkPMColor order. | 
 |             // We want unpremul sRGB 8-bit pixels in RGBA order.  We'll get there via floats. | 
 |             bitmap.lockPixels(); | 
 |             auto px = (const uint32_t*)bitmap.getPixels(); | 
 |             if (!px) { | 
 |                 return nullptr; | 
 |             } | 
 |             for (int i = 0; i < w*h; i++) { | 
 |                 Sk4f fs = Sk4f_fromS32(px[i]);         // Convert up to linear floats. | 
 | #if defined(SK_PMCOLOR_IS_BGRA) | 
 |                 fs = SkNx_shuffle<2,1,0,3>(fs);        // Shuffle to RGBA, if not there already. | 
 | #endif | 
 |                 float invA = 1.0f / fs[3]; | 
 |                 fs = fs * Sk4f(invA, invA, invA, 1);   // Unpremultiply. | 
 |                 rgba[i] = Sk4f_toS32(fs);              // Pack down to sRGB bytes. | 
 |             } | 
 |  | 
 |         } else if (bitmap.colorType() == kRGBA_F16_SkColorType) { | 
 |             // These are premul linear half-float pixels in RGBA order. | 
 |             // We want unpremul sRGB 8-bit pixels in RGBA order.  We'll get there via floats. | 
 |             bitmap.lockPixels(); | 
 |             auto px = (const uint64_t*)bitmap.getPixels(); | 
 |             if (!px) { | 
 |                 return nullptr; | 
 |             } | 
 |             for (int i = 0; i < w*h; i++) { | 
 |                 // Convert up to linear floats. | 
 |                 Sk4f fs(SkHalfToFloat(static_cast<SkHalf>(px[i] >> (0 * 16))), | 
 |                         SkHalfToFloat(static_cast<SkHalf>(px[i] >> (1 * 16))), | 
 |                         SkHalfToFloat(static_cast<SkHalf>(px[i] >> (2 * 16))), | 
 |                         SkHalfToFloat(static_cast<SkHalf>(px[i] >> (3 * 16)))); | 
 |                 fs = Sk4f::Max(0.0f, Sk4f::Min(fs, 1.0f));  // Clamp | 
 |                 float invA = 1.0f / fs[3]; | 
 |                 fs = fs * Sk4f(invA, invA, invA, 1);  // Unpremultiply. | 
 |                 rgba[i] = Sk4f_toS32(fs);             // Pack down to sRGB bytes. | 
 |             } | 
 |  | 
 |         } else { | 
 |             // We "should" gamma correct in here but we don't. | 
 |             // We want Gold to show exactly what our clients are seeing, broken gamma. | 
 |  | 
 |             // Convert smaller formats up to premul linear 8-bit (in SkPMColor order). | 
 |             if (bitmap.colorType() != kN32_SkColorType) { | 
 |                 SkBitmap n32; | 
 |                 if (!bitmap.copyTo(&n32, kN32_SkColorType)) { | 
 |                     return nullptr; | 
 |                 } | 
 |                 bitmap = n32; | 
 |             } | 
 |  | 
 |             // Convert premul linear 8-bit to unpremul linear 8-bit RGBA. | 
 |             if (!bitmap.readPixels(SkImageInfo::Make(w,h, kRGBA_8888_SkColorType, | 
 |                                                      kUnpremul_SkAlphaType), | 
 |                                    rgba, 4*w, 0,0)) { | 
 |                 return nullptr; | 
 |             } | 
 |         } | 
 |  | 
 |         return SkData::MakeFromMalloc(rgba.release(), w*h*sizeof(uint32_t)); | 
 |     } | 
 |  | 
 | } // namespace sk_tools |