1// Copyright 2019 The Amber Authors. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15#include "samples/png.h" 16 17#include <cassert> 18 19#include "amber/result.h" 20#include "amber/value.h" 21 22#pragma clang diagnostic push 23#pragma clang diagnostic ignored "-Wweak-vtables" 24#include "third_party/lodepng/lodepng.h" 25#pragma clang diagnostic pop 26 27namespace png { 28 29namespace { 30 31unsigned char byte0(uint32_t word) { 32 return static_cast<unsigned char>(word); 33} 34 35unsigned char byte1(uint32_t word) { 36 return static_cast<unsigned char>(word >> 8); 37} 38 39unsigned char byte2(uint32_t word) { 40 return static_cast<unsigned char>(word >> 16); 41} 42 43unsigned char byte3(uint32_t word) { 44 return static_cast<unsigned char>(word >> 24); 45} 46 47} // namespace 48 49amber::Result ConvertToPNG(uint32_t width, 50 uint32_t height, 51 const std::vector<amber::Value>& values, 52 std::vector<uint8_t>* buffer) { 53 assert(values.size() == (width * height) && 54 "Buffer values != width * height"); 55 assert(!values.empty() && "Buffer empty"); 56 57 std::vector<uint8_t> data; 58 59 // Prepare data as lodepng expects it 60 for (const amber::Value& value : values) { 61 const uint32_t pixel = value.AsUint32(); 62 data.push_back(byte2(pixel)); // R 63 data.push_back(byte1(pixel)); // G 64 data.push_back(byte0(pixel)); // B 65 data.push_back(byte3(pixel)); // A 66 } 67 68 lodepng::State state; 69 70 // Force RGBA color type, otherwise many PNG decoders will ignore the alpha 71 // channel. 72 state.encoder.auto_convert = 0; 73 state.info_raw.colortype = LodePNGColorType::LCT_RGBA; 74 state.info_raw.bitdepth = 8; 75 state.info_png.color.colortype = LodePNGColorType::LCT_RGBA; 76 state.info_png.color.bitdepth = 8; 77 78 if (lodepng::encode(*buffer, data, width, height, state) != 0) 79 return amber::Result("lodepng::encode() returned non-zero"); 80 81 return {}; 82} 83 84amber::Result LoadPNG(const std::string file_name, 85 uint32_t* width, 86 uint32_t* height, 87 std::vector<amber::Value>* values) { 88 std::vector<uint8_t> decoded_buffer; 89 if (lodepng::decode(decoded_buffer, *width, *height, file_name, 90 LodePNGColorType::LCT_RGBA, 8) != 0) { 91 return amber::Result("lodepng::decode() returned non-zero"); 92 } 93 94 for (auto d : decoded_buffer) { 95 amber::Value v; 96 v.SetIntValue(d); 97 values->push_back(v); 98 } 99 100 return {}; 101} 102 103} // namespace png 104