1/**************************************************************************/
2/* image_loader_png.cpp */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10/* */
11/* Permission is hereby granted, free of charge, to any person obtaining */
12/* a copy of this software and associated documentation files (the */
13/* "Software"), to deal in the Software without restriction, including */
14/* without limitation the rights to use, copy, modify, merge, publish, */
15/* distribute, sublicense, and/or sell copies of the Software, and to */
16/* permit persons to whom the Software is furnished to do so, subject to */
17/* the following conditions: */
18/* */
19/* The above copyright notice and this permission notice shall be */
20/* included in all copies or substantial portions of the Software. */
21/* */
22/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29/**************************************************************************/
30
31#include "image_loader_png.h"
32
33#include "core/os/os.h"
34#include "core/string/print_string.h"
35#include "drivers/png/png_driver_common.h"
36
37#include <string.h>
38
39Error ImageLoaderPNG::load_image(Ref<Image> p_image, Ref<FileAccess> f, BitField<ImageFormatLoader::LoaderFlags> p_flags, float p_scale) {
40 const uint64_t buffer_size = f->get_length();
41 Vector<uint8_t> file_buffer;
42 Error err = file_buffer.resize(buffer_size);
43 if (err) {
44 return err;
45 }
46 {
47 uint8_t *writer = file_buffer.ptrw();
48 f->get_buffer(writer, buffer_size);
49 }
50 const uint8_t *reader = file_buffer.ptr();
51 return PNGDriverCommon::png_to_image(reader, buffer_size, p_flags & FLAG_FORCE_LINEAR, p_image);
52}
53
54void ImageLoaderPNG::get_recognized_extensions(List<String> *p_extensions) const {
55 p_extensions->push_back("png");
56}
57
58Ref<Image> ImageLoaderPNG::load_mem_png(const uint8_t *p_png, int p_size) {
59 Ref<Image> img;
60 img.instantiate();
61
62 // the value of p_force_linear does not matter since it only applies to 16 bit
63 Error err = PNGDriverCommon::png_to_image(p_png, p_size, false, img);
64 ERR_FAIL_COND_V(err, Ref<Image>());
65
66 return img;
67}
68
69Ref<Image> ImageLoaderPNG::lossless_unpack_png(const Vector<uint8_t> &p_data) {
70 const int len = p_data.size();
71 ERR_FAIL_COND_V(len < 4, Ref<Image>());
72 const uint8_t *r = p_data.ptr();
73 ERR_FAIL_COND_V(r[0] != 'P' || r[1] != 'N' || r[2] != 'G' || r[3] != ' ', Ref<Image>());
74 return load_mem_png(&r[4], len - 4);
75}
76
77Vector<uint8_t> ImageLoaderPNG::lossless_pack_png(const Ref<Image> &p_image) {
78 Vector<uint8_t> out_buffer;
79
80 // add Godot's own "PNG " prefix
81 if (out_buffer.resize(4) != OK) {
82 ERR_FAIL_V(Vector<uint8_t>());
83 }
84
85 // scope for writer lifetime
86 {
87 // must be closed before call to image_to_png
88 uint8_t *writer = out_buffer.ptrw();
89 memcpy(writer, "PNG ", 4);
90 }
91
92 Error err = PNGDriverCommon::image_to_png(p_image, out_buffer);
93 if (err) {
94 ERR_FAIL_V(Vector<uint8_t>());
95 }
96
97 return out_buffer;
98}
99
100ImageLoaderPNG::ImageLoaderPNG() {
101 Image::_png_mem_loader_func = load_mem_png;
102 Image::png_unpacker = lossless_unpack_png;
103 Image::png_packer = lossless_pack_png;
104}
105