Aeon Engine c550894
AeonGames Open Source Game Engine
Loading...
Searching...
No Matches
PngImage.cpp
1/*
2Copyright (C) 2016-2020,2022,2025,2026 Rodrigo Jose Hernandez Cordoba
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16#include <iostream>
17#include <fstream>
18#include <png.h>
19#include <algorithm>
20#include <exception>
21#include <stdexcept>
22#include <cstring>
23#include "PngImage.h"
25
26namespace AeonGames
27{
30 {
31 const uint8_t* buffer;
32 const uint8_t* pointer;
33 png_size_t size;
34 };
35
36 static void png_read_memory_data ( png_structp png_ptr, png_bytep data, png_size_t length )
37 {
38 if ( png_ptr == nullptr )
39 {
40 std::cout << __FUNCTION__ << " got NULL png_ptr pointer." << std::endl;
41 png_warning ( png_ptr, "Got NULL png_ptr pointer." );
42 return;
43 }
44 auto* read_struct = static_cast<png_read_memory_struct*> ( png_get_io_ptr ( png_ptr ) );
45 // Clip lenght not to get passed the end of the buffer.
46 png_size_t real_length = std::min<png_size_t> ( ( ( read_struct->buffer + read_struct->size ) - read_struct->pointer ), length );
47 if ( length < 1 )
48 {
49 std::cout << __FUNCTION__ << " tried to read past end of file" << std::endl;
50 png_warning ( png_ptr, "Tried to read past end of file" );
51 return;
52 }
53 memcpy ( data, read_struct->pointer, real_length );
54 if ( real_length < length )
55 {
56 std::cout << __FUNCTION__ << " Returning " << real_length << " bytes instead of requested " << length << " because of end of memory" << std::endl;
57 memset ( data + real_length, 0, length - real_length );
58 }
59 read_struct->pointer += real_length;
60 }
61 bool DecodePNG ( Texture& aTexture, size_t aBufferSize, const void* aBuffer )
62 {
63 if ( png_sig_cmp ( static_cast<uint8_t * > ( const_cast<void * > ( aBuffer ) ), 0, 8 ) != 0 )
64 {
65 return false;
66 }
67 try
68 {
69 png_structp png_ptr =
70 png_create_read_struct ( PNG_LIBPNG_VER_STRING,
71 nullptr, nullptr, nullptr );
72 if ( png_ptr == nullptr )
73 {
74 std::cout << LogLevel::Error << "png_create_read_struct failed." << std::endl;
75 throw std::runtime_error ( "png_create_read_struct failed." );
76 }
77 png_infop info_ptr = png_create_info_struct ( png_ptr );
78 if ( info_ptr == nullptr )
79 {
80 std::cout << LogLevel::Error << "png_create_info_struct failed." << std::endl;
81 throw std::runtime_error ( "png_create_info_struct failed." );
82 }
83 if ( setjmp ( png_jmpbuf ( png_ptr ) ) )
84 {
85 std::cout << LogLevel::Error << "Error during init_io." << std::endl;
86 throw std::runtime_error ( "Error during init_io." );
87 }
88 png_read_memory_struct read_memory_struct = {static_cast<const uint8_t*> ( aBuffer ), static_cast<const uint8_t*> ( aBuffer ) + 8,
89 static_cast<png_size_t> ( aBufferSize * sizeof ( uint8_t ) )
90 };
91 png_set_read_fn ( png_ptr, &read_memory_struct, png_read_memory_data );
92 png_set_sig_bytes ( png_ptr, 8 );
93
94 png_read_info ( png_ptr, info_ptr );
95
96 uint32_t width = png_get_image_width ( png_ptr, info_ptr );
97 uint32_t height = png_get_image_height ( png_ptr, info_ptr );
98 png_byte color_type = png_get_color_type ( png_ptr, info_ptr );
99 png_byte bit_depth = png_get_bit_depth ( png_ptr, info_ptr );
100
101 Texture::Format format;
102 Texture::Type type;
103 if ( ( color_type == PNG_COLOR_TYPE_RGB ) || ( color_type == PNG_COLOR_TYPE_RGBA ) )
104 {
105 format = ( color_type == PNG_COLOR_TYPE_RGB ) ? Texture::Format::RGB : Texture::Format::RGBA;
107 }
108 else
109 {
110 std::cout << LogLevel::Error << "PNG image color type not supported...yet" << std::endl;
111 throw std::runtime_error ( "PNG image color type not supported...yet" );
112 }
113
114 /*int number_of_passes =*/ png_set_interlace_handling ( png_ptr );
115 png_read_update_info ( png_ptr, info_ptr );
116
117 /* read file */
118 if ( setjmp ( png_jmpbuf ( png_ptr ) ) )
119 {
120 std::cout << LogLevel::Error << "Error during read_image." << std::endl;
121 throw std::runtime_error ( "Error during read_image." );
122 }
123 // --------------------------------------
124 png_size_t rowbytes = png_get_rowbytes ( png_ptr, info_ptr );
125 std::vector<uint8_t*> row_pointers ( sizeof ( png_bytep ) * height );
126 std::vector<uint8_t> pixels ( width * height * GetPixelSize ( format, type ) );
127 for ( png_uint_32 y = 0; y < height; ++y )
128 {
129 row_pointers[y] = pixels.data() + ( rowbytes * y );
130 }
131 // --------------------------------------
132 png_read_image ( png_ptr, row_pointers.data() );
133 png_destroy_read_struct ( &png_ptr, &info_ptr, ( png_infopp ) nullptr );
134 aTexture.Resize ( width, height, pixels.data(), format, type );
135 }
136 catch ( const std::runtime_error& e )
137 {
138 std::cout << e.what() << std::endl;
139 return false;
140 }
141 return true;
142 }
143}
Defines log severity levels and stream output for the AeonGames engine.
Represents a 2D texture image resource.
Definition Texture.hpp:33
DLL void Resize(uint32_t aWidth, uint32_t aHeight, const uint8_t *aPixels=nullptr, Format aFormat=Format::Unknown, Type aType=Type::Unknown)
Resizes the texture and optionally replaces pixel data.
Definition Texture.cpp:46
Type
Pixel component data type.
Definition Texture.hpp:51
@ UNSIGNED_SHORT
16-bit unsigned integer per channel.
Definition Texture.hpp:54
@ UNSIGNED_BYTE
8-bit unsigned integer per channel.
Definition Texture.hpp:53
Format
Pixel channel layout format.
Definition Texture.hpp:40
@ RGB
3-channel red, green, blue.
Definition Texture.hpp:42
@ RGBA
4-channel red, green, blue, alpha.
Definition Texture.hpp:43
<- This is here just for the literals
Definition AABB.hpp:31
@ Error
Error conditions.
Definition LogLevel.hpp:33
bool DecodePNG(Texture &aTexture, size_t aBufferSize, const void *aBuffer)
Decodes PNG image data from a memory buffer into a Texture.
Definition PngImage.cpp:61
Helper struct for reading PNG data from memory.
Definition PngImage.cpp:30
const uint8_t * buffer
Pointer to the start of the memory buffer.
Definition PngImage.cpp:31
const uint8_t * pointer
Current read position within the buffer.
Definition PngImage.cpp:32
png_size_t size
Total size of the memory buffer in bytes.
Definition PngImage.cpp:33