From ffd3e3f852ad2997e3cf6e24cdee2ddf76519ef3 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 12 Nov 2023 03:26:06 +0300 Subject: [PATCH] Added graphics/ImageData class --- src/coders/png.cpp | 85 ++++++++++++++------------------------ src/coders/png.h | 2 + src/engine.cpp | 1 + src/graphics/Batch2D.cpp | 2 +- src/graphics/Batch3D.cpp | 2 +- src/graphics/ImageData.cpp | 14 +++++++ src/graphics/ImageData.h | 37 +++++++++++++++++ src/graphics/Texture.cpp | 22 ++++++++-- src/graphics/Texture.h | 6 ++- 9 files changed, 110 insertions(+), 61 deletions(-) create mode 100644 src/graphics/ImageData.cpp create mode 100644 src/graphics/ImageData.h diff --git a/src/coders/png.cpp b/src/coders/png.cpp index 19ba6120..d614142c 100644 --- a/src/coders/png.cpp +++ b/src/coders/png.cpp @@ -2,6 +2,8 @@ #include #include + +#include "../graphics/ImageData.h" #include "../graphics/Texture.h" #ifndef _WIN32 @@ -11,7 +13,7 @@ #ifdef LIBPNG #include -int _png_load(const char* file, int* width, int* height){ +ImageData* _png_load(const char* file, int* width, int* height){ FILE *f; int is_png, bit_depth, color_type, row_bytes; png_infop info_ptr, end_info; @@ -19,42 +21,40 @@ int _png_load(const char* file, int* width, int* height){ png_byte header[8], *image_data; png_bytepp row_pointers; png_structp png_ptr; - GLuint texture; - int alpha; - if ( !( f = fopen(file, "r" ) ) ) { - return 0; + if (!( f = fopen(file, "r" ) ) ) { + return nullptr; } fread( header, 1, 8, f ); is_png = !png_sig_cmp( header, 0, 8 ); if ( !is_png ) { fclose( f ); - return 0; + return nullptr; } png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL ); if ( !png_ptr ) { fclose( f ); - return 0; + return nullptr; } info_ptr = png_create_info_struct( png_ptr ); if ( !info_ptr ) { png_destroy_read_struct( &png_ptr, (png_infopp) NULL, (png_infopp) NULL ); fclose( f ); - return 0; + return nullptr; } end_info = png_create_info_struct( png_ptr ); if ( !end_info ) { png_destroy_read_struct( &png_ptr, (png_infopp) NULL, (png_infopp) NULL ); fclose( f ); - return 0; + return nullptr; } if ( setjmp( png_jmpbuf( png_ptr ) ) ) { png_destroy_read_struct( &png_ptr, &info_ptr, &end_info ); fclose( f ); - return 0; + return nullptr; } png_init_io( png_ptr, f ); png_set_sig_bytes( png_ptr, 8 ); @@ -65,56 +65,43 @@ int _png_load(const char* file, int* width, int* height){ *height = t_height; png_read_update_info( png_ptr, info_ptr ); row_bytes = png_get_rowbytes( png_ptr, info_ptr ); - image_data = (png_bytep) malloc( row_bytes * t_height * sizeof(png_byte) ); - if ( !image_data ) { + image_data = new png_byte[row_bytes * t_height]; + if (!image_data) { png_destroy_read_struct( &png_ptr, &info_ptr, &end_info ); - fclose( f ); - return 0; + fclose(f); + return nullptr; } row_pointers = (png_bytepp) malloc( t_height * sizeof(png_bytep) ); if ( !row_pointers ) { png_destroy_read_struct( &png_ptr, &info_ptr, &end_info ); - free( image_data ); - fclose( f ); - return 0; + delete[] image_data; + fclose(f); + return nullptr; } for (unsigned int i = 0; i < t_height; ++i ) { row_pointers[t_height - 1 - i] = image_data + i * row_bytes; } - png_read_image( png_ptr, row_pointers ); + png_read_image(png_ptr, row_pointers); + + ImageFormat format; switch ( png_get_color_type( png_ptr, info_ptr ) ) { case PNG_COLOR_TYPE_RGBA: - alpha = GL_RGBA; + format = ImageFormat::rgba8888; break; case PNG_COLOR_TYPE_RGB: - alpha = GL_RGB; + format = ImageFormat::rgb888; break; default: printf( "Color type %d not supported!\n", png_get_color_type( png_ptr, info_ptr ) ); png_destroy_read_struct( &png_ptr, &info_ptr, &end_info ); - return 0; + return nullptr; } - // configure second post-processing framebuffer - - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, t_width, t_height, 0, - alpha, GL_UNSIGNED_BYTE, (GLvoid *) image_data); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1); - glGenerateMipmap(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, 0); - + ImageData* image = new ImageData(format, *width, *height, (void*)image_data); png_destroy_read_struct( &png_ptr, &info_ptr, &end_info ); - free( image_data ); free( row_pointers ); fclose( f ); - return texture; + return image; } #else #include @@ -205,18 +192,8 @@ int _png_load(const char* file, int* pwidth, int* pheight){ delete[] out; unsigned int texture; - int alpha = GL_RGBA; - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ihdr.width, ihdr.height, 0, - alpha, GL_UNSIGNED_BYTE, (GLvoid *) flipped); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glBindTexture(GL_TEXTURE_2D, 0); + ImageData* image = new ImageData(ImageFormat::rgba8888, ihdr.width, ihdr.height, (void*)flipped); pwidth[0] = ihdr.width; pheight[0] = ihdr.height; @@ -224,17 +201,17 @@ int _png_load(const char* file, int* pwidth, int* pheight){ spng_ctx_free(ctx); delete[] pngbuf; - return texture; + return image; } #endif Texture* png::load_texture(std::string filename){ int width, height; - GLuint texture = _png_load(filename.c_str(), &width, &height); - if (texture == 0){ - std::cerr << "Could not load texture " << filename << std::endl; + ImageData* image = _png_load(filename.c_str(), &width, &height); + if (image == nullptr){ + std::cerr << "Could not load image " << filename << std::endl; return nullptr; } - return new Texture(texture, width, height); + return Texture::from(image); } diff --git a/src/coders/png.h b/src/coders/png.h index 0bb46628..dba3ed93 100644 --- a/src/coders/png.h +++ b/src/coders/png.h @@ -4,8 +4,10 @@ #include class Texture; +class ImageData; namespace png { + extern ImageData load_image(std::string filename); extern Texture* load_texture(std::string filename); } diff --git a/src/engine.cpp b/src/engine.cpp index 3c29967d..003c1cec 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -133,4 +133,5 @@ Engine::~Engine() { std::cout << "-- shutting down" << std::endl; delete assets; Window::terminate(); + std::cout << "-- engine finished" << std::endl; } \ No newline at end of file diff --git a/src/graphics/Batch2D.cpp b/src/graphics/Batch2D.cpp index e6d73d89..4fbea3a9 100644 --- a/src/graphics/Batch2D.cpp +++ b/src/graphics/Batch2D.cpp @@ -19,7 +19,7 @@ Batch2D::Batch2D(size_t capacity) : capacity(capacity), offset(0), color(1.0f, 1 unsigned char pixels[] = { 255, 255, 255, 255, }; - blank = new Texture(pixels, 1, 1); + blank = new Texture(pixels, 1, 1, GL_RGBA); _texture = nullptr; } diff --git a/src/graphics/Batch3D.cpp b/src/graphics/Batch3D.cpp index 57b38c7d..cb57b53a 100644 --- a/src/graphics/Batch3D.cpp +++ b/src/graphics/Batch3D.cpp @@ -19,7 +19,7 @@ Batch3D::Batch3D(size_t capacity) : capacity(capacity), offset(0), color(1.0f, 1 unsigned char pixels[] = { 255, 255, 255, 255, }; - blank = new Texture(pixels, 1, 1); + blank = new Texture(pixels, 1, 1, GL_RGBA); _texture = nullptr; } diff --git a/src/graphics/ImageData.cpp b/src/graphics/ImageData.cpp new file mode 100644 index 00000000..7dfbe732 --- /dev/null +++ b/src/graphics/ImageData.cpp @@ -0,0 +1,14 @@ +#include "ImageData.h" + +ImageData::ImageData(ImageFormat format, uint width, uint height, void* data) + : format(format), width(width), height(height), data(data) { +} + +ImageData::~ImageData() { + switch (format) { + case ImageFormat::rgb888: + case ImageFormat::rgba8888: + delete[] data; + break; + } +} \ No newline at end of file diff --git a/src/graphics/ImageData.h b/src/graphics/ImageData.h new file mode 100644 index 00000000..aba28261 --- /dev/null +++ b/src/graphics/ImageData.h @@ -0,0 +1,37 @@ +#ifndef GRAPHICS_IMAGE_DATA_H_ +#define GRAPHICS_IMAGE_DATA_H_ + +#include "../typedefs.h" + +enum class ImageFormat { + rgb888, + rgba8888 +}; + +class ImageData { + ImageFormat format; + uint width; + uint height; + void* data; +public: + ImageData(ImageFormat format, uint width, uint height, void* data); + ~ImageData(); + + void* getData() const { + return data; + } + + ImageFormat getFormat() const { + return format; + } + + uint getWidth() const { + return width; + } + + uint getHeight() const { + return height; + } +}; + +#endif // GRAPHICS_IMAGE_DATA_H_ \ No newline at end of file diff --git a/src/graphics/Texture.cpp b/src/graphics/Texture.cpp index 71804d2d..ebc0326d 100644 --- a/src/graphics/Texture.cpp +++ b/src/graphics/Texture.cpp @@ -1,15 +1,18 @@ #include "Texture.h" #include +#include + +#include "ImageData.h" Texture::Texture(unsigned int id, int width, int height) : id(id), width(width), height(height) { } -Texture::Texture(unsigned char* data, int width, int height) : width(width), height(height) { +Texture::Texture(unsigned char* data, int width, int height, uint format) : width(width), height(height) { glGenTextures(1, &id); glBindTexture(GL_TEXTURE_2D, id); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, - GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *) data); + glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, + format, GL_UNSIGNED_BYTE, (GLvoid *) data); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glBindTexture(GL_TEXTURE_2D, 0); @@ -21,7 +24,6 @@ Texture::~Texture() { void Texture::bind(){ glBindTexture(GL_TEXTURE_2D, id); - // glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, id); } void Texture::reload(unsigned char* data){ @@ -30,3 +32,15 @@ void Texture::reload(unsigned char* data){ GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *) data); glBindTexture(GL_TEXTURE_2D, 0); } + +Texture* Texture::from(const ImageData* image) { + uint format; + const void* data = image->getData(); + switch (image->getFormat()) { + case ImageFormat::rgb888: format = GL_RGB; break; + case ImageFormat::rgba8888: format = GL_RGBA; break; + default: + throw std::runtime_error("unsupported image data format"); + } + return new Texture((unsigned char*)data, image->getWidth(), image->getHeight(), format); +} \ No newline at end of file diff --git a/src/graphics/Texture.h b/src/graphics/Texture.h index 0046c90f..65fbf677 100644 --- a/src/graphics/Texture.h +++ b/src/graphics/Texture.h @@ -3,17 +3,21 @@ #include +class ImageData; + class Texture { public: unsigned int id; int width; int height; Texture(unsigned int id, int width, int height); - Texture(unsigned char* data, int width, int height); + Texture(unsigned char* data, int width, int height, uint format); ~Texture(); void bind(); void reload(unsigned char* data); + + static Texture* from(const ImageData* image); }; #endif /* GRAPHICS_TEXTURE_H_ */