From 00e82140e0d8727f6701e07224f3fac9ebe0c77c Mon Sep 17 00:00:00 2001 From: scawful Date: Tue, 28 May 2024 23:49:45 -0400 Subject: [PATCH] cleanup bitmap class --- src/app/gfx/bitmap.cc | 257 ++++++++++++++++++++---------------------- src/app/gfx/bitmap.h | 1 - 2 files changed, 123 insertions(+), 135 deletions(-) diff --git a/src/app/gfx/bitmap.cc b/src/app/gfx/bitmap.cc index 2e479f86..4a202982 100644 --- a/src/app/gfx/bitmap.cc +++ b/src/app/gfx/bitmap.cc @@ -49,139 +49,138 @@ void PngReadCallback(png_structp png_ptr, png_bytep outBytes, } // namespace bool ConvertSurfaceToPNG(SDL_Surface *surface, std::vector &buffer) { - png_structp png_ptr = png_create_write_struct("1.6.40", NULL, NULL, - NULL); if (!png_ptr) { - SDL_Log("Failed to create PNG write struct"); - return false; - } + png_structp png_ptr = png_create_write_struct("1.6.40", NULL, NULL, NULL); + if (!png_ptr) { + SDL_Log("Failed to create PNG write struct"); + return false; + } - png_infop info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) { - png_destroy_write_struct(&png_ptr, (png_infopp)NULL); - SDL_Log("Failed to create PNG info struct"); - return false; - } - - if (setjmp(png_jmpbuf(png_ptr))) { - png_destroy_write_struct(&png_ptr, &info_ptr); - SDL_Log("Error during PNG write"); - return false; - } - - png_set_write_fn(png_ptr, &buffer, PngWriteCallback, NULL); - - png_colorp pal_ptr; - - /* Prepare chunks */ - int colortype = PNG_COLOR_MASK_COLOR; - int i = 0; - SDL_Palette *pal; - if (surface->format->BytesPerPixel > 0 && - surface->format->BytesPerPixel <= 8 && (pal = - surface->format->palette)) { - SDL_Log("Writing PNG image with palette"); - colortype |= PNG_COLOR_MASK_PALETTE; - pal_ptr = (png_colorp)malloc(pal->ncolors * sizeof(png_color)); - for (i = 0; i < pal->ncolors; i++) { - pal_ptr[i].red = pal->colors[i].r; - pal_ptr[i].green = pal->colors[i].g; - pal_ptr[i].blue = pal->colors[i].b; - } - png_set_PLTE(png_ptr, info_ptr, pal_ptr, pal->ncolors); - free(pal_ptr); - } - - if (surface->format->Amask) { // Check for alpha channel - colortype |= PNG_COLOR_MASK_ALPHA; - } - - auto depth = surface->format->BitsPerPixel; - - // Set image attributes. - png_set_IHDR(png_ptr, info_ptr, surface->w, surface->h, depth, colortype, - PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, - PNG_FILTER_TYPE_DEFAULT); - - png_set_bgr(png_ptr); - - // Write the image data. - std::vector row_pointers(surface->h); - for (int y = 0; y < surface->h; ++y) { - row_pointers[y] = (png_bytep)(surface->pixels) + y * surface->pitch; - } - - png_set_rows(png_ptr, info_ptr, row_pointers.data()); - - SDL_Log("Writing PNG image..."); - png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); - SDL_Log("PNG image write complete"); + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_write_struct(&png_ptr, (png_infopp)NULL); + SDL_Log("Failed to create PNG info struct"); + return false; + } + if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); + SDL_Log("Error during PNG write"); + return false; + } + + png_set_write_fn(png_ptr, &buffer, PngWriteCallback, NULL); + + png_colorp pal_ptr; + + /* Prepare chunks */ + int colortype = PNG_COLOR_MASK_COLOR; + int i = 0; + SDL_Palette *pal; + if (surface->format->BytesPerPixel > 0 && + surface->format->BytesPerPixel <= 8 && (pal = surface->format->palette)) { + SDL_Log("Writing PNG image with palette"); + colortype |= PNG_COLOR_MASK_PALETTE; + pal_ptr = (png_colorp)malloc(pal->ncolors * sizeof(png_color)); + for (i = 0; i < pal->ncolors; i++) { + pal_ptr[i].red = pal->colors[i].r; + pal_ptr[i].green = pal->colors[i].g; + pal_ptr[i].blue = pal->colors[i].b; + } + png_set_PLTE(png_ptr, info_ptr, pal_ptr, pal->ncolors); + free(pal_ptr); + } + + if (surface->format->Amask) { // Check for alpha channel + colortype |= PNG_COLOR_MASK_ALPHA; + } + + auto depth = surface->format->BitsPerPixel; + + // Set image attributes. + png_set_IHDR(png_ptr, info_ptr, surface->w, surface->h, depth, colortype, + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); + + png_set_bgr(png_ptr); + + // Write the image data. + std::vector row_pointers(surface->h); + for (int y = 0; y < surface->h; ++y) { + row_pointers[y] = (png_bytep)(surface->pixels) + y * surface->pitch; + } + + png_set_rows(png_ptr, info_ptr, row_pointers.data()); + + SDL_Log("Writing PNG image..."); + png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); + SDL_Log("PNG image write complete"); + + png_destroy_write_struct(&png_ptr, &info_ptr); return true; } void ConvertPngToSurface(const std::vector &png_data, SDL_Surface **outSurface) { - std::vector data(png_data); - png_structp png_ptr = png_create_read_struct("1.6.40", NULL, NULL, NULL); - if (!png_ptr) { - throw std::runtime_error("Failed to create PNG read struct"); - } + std::vector data(png_data); + png_structp png_ptr = png_create_read_struct("1.6.40", NULL, NULL, NULL); + if (!png_ptr) { + throw std::runtime_error("Failed to create PNG read struct"); + } - png_infop info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) { - png_destroy_read_struct(&png_ptr, NULL, NULL); - throw std::runtime_error("Failed to create PNG info struct"); - } + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_read_struct(&png_ptr, NULL, NULL); + throw std::runtime_error("Failed to create PNG info struct"); + } - if (setjmp(png_jmpbuf(png_ptr))) { - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - throw std::runtime_error("Error during PNG read"); - } - - // Set our custom read function - png_set_read_fn(png_ptr, &data, PngReadCallback); - - // Read the PNG info - png_read_info(png_ptr, info_ptr); - - uint32_t width = png_get_image_width(png_ptr, info_ptr); - uint32_t height = png_get_image_height(png_ptr, info_ptr); - png_byte color_type = png_get_color_type(png_ptr, info_ptr); - png_byte bit_depth = png_get_bit_depth(png_ptr, info_ptr); - - // Apply necessary transformations... - // (Same as in your existing code) - - // Update info structure with transformations - png_read_update_info(png_ptr, info_ptr); - - // Read the file - std::vector raw_data(width * height * - 4); // Assuming 4 bytes per pixel (RGBA) - std::vector row_pointers(height); - for (size_t y = 0; y < height; y++) { - row_pointers[y] = raw_data.data() + y * width * 4; - } - - png_read_image(png_ptr, row_pointers.data()); + if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + throw std::runtime_error("Error during PNG read"); + } - // Create an SDL_Surface - *outSurface = SDL_CreateRGBSurfaceWithFormat(0, width, height, 32, - SDL_PIXELFORMAT_RGBA32); - if (*outSurface == nullptr) { - SDL_Log("SDL_CreateRGBSurfaceWithFormat failed: %s\n", SDL_GetError()); - return; - } + // Set our custom read function + png_set_read_fn(png_ptr, &data, PngReadCallback); - // Copy the raw data into the SDL_Surface - SDL_LockSurface(*outSurface); - memcpy((*outSurface)->pixels, raw_data.data(), raw_data.size()); - SDL_UnlockSurface(*outSurface); + // Read the PNG info + png_read_info(png_ptr, info_ptr); - SDL_Log("Successfully created SDL_Surface from PNG data"); + uint32_t width = png_get_image_width(png_ptr, info_ptr); + uint32_t height = png_get_image_height(png_ptr, info_ptr); + png_byte color_type = png_get_color_type(png_ptr, info_ptr); + png_byte bit_depth = png_get_bit_depth(png_ptr, info_ptr); + + // Apply necessary transformations... + // (Same as in your existing code) + + // Update info structure with transformations + png_read_update_info(png_ptr, info_ptr); + + // Read the file + std::vector raw_data(width * height * + 4); // Assuming 4 bytes per pixel (RGBA) + std::vector row_pointers(height); + for (size_t y = 0; y < height; y++) { + row_pointers[y] = raw_data.data() + y * width * 4; + } + + png_read_image(png_ptr, row_pointers.data()); + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + + // Create an SDL_Surface + *outSurface = SDL_CreateRGBSurfaceWithFormat(0, width, height, 32, + SDL_PIXELFORMAT_RGBA32); + if (*outSurface == nullptr) { + SDL_Log("SDL_CreateRGBSurfaceWithFormat failed: %s\n", SDL_GetError()); + return; + } + + // Copy the raw data into the SDL_Surface + SDL_LockSurface(*outSurface); + memcpy((*outSurface)->pixels, raw_data.data(), raw_data.size()); + SDL_UnlockSurface(*outSurface); + + SDL_Log("Successfully created SDL_Surface from PNG data"); } Bitmap::Bitmap(int width, int height, int depth, int data_size) { @@ -230,10 +229,8 @@ void Bitmap::CreateTexture(SDL_Renderer *renderer) { SDL_LockTexture(texture_.get(), nullptr, (void **)&texture_pixels, &converted_surface_->pitch); - memcpy(texture_pixels, converted_surface_->pixels, converted_surface_->h * converted_surface_->pitch); - SDL_UnlockTexture(texture_.get()); } @@ -249,19 +246,13 @@ void Bitmap::UpdateTexture(SDL_Renderer *renderer, bool use_sdl_update) { SDL_LockTexture(texture_.get(), nullptr, (void **)&texture_pixels, &converted_surface_->pitch); - - try { - if (use_sdl_update) { - SDL_UpdateTexture(texture_.get(), nullptr, converted_surface_->pixels, - converted_surface_->pitch); - } else { - memcpy(texture_pixels, converted_surface_->pixels, - converted_surface_->h * converted_surface_->pitch); - } - } catch (const std::exception &e) { - SDL_Log("Exception: %s\n", e.what()); + if (use_sdl_update) { + SDL_UpdateTexture(texture_.get(), nullptr, converted_surface_->pixels, + converted_surface_->pitch); + } else { + memcpy(texture_pixels, converted_surface_->pixels, + converted_surface_->h * converted_surface_->pitch); } - SDL_UnlockTexture(texture_.get()); } @@ -272,8 +263,6 @@ void Bitmap::CreateTexture(std::shared_ptr renderer) { } void Bitmap::UpdateTexture(std::shared_ptr renderer) { - // SDL_DestroyTexture(texture_.get()); - // texture_ = nullptr; texture_ = std::shared_ptr{ SDL_CreateTextureFromSurface(renderer.get(), surface_.get()), SDL_Texture_Deleter{}}; diff --git a/src/app/gfx/bitmap.h b/src/app/gfx/bitmap.h index 9eab5080..a632a6db 100644 --- a/src/app/gfx/bitmap.h +++ b/src/app/gfx/bitmap.h @@ -253,7 +253,6 @@ class Bitmap { struct SDL_Surface_Deleter { void operator()(SDL_Surface *p) const { if (p != nullptr) { - p->pixels = nullptr; SDL_FreeSurface(p); p = nullptr; }