29namespace png_internal {
31void PngWriteCallback(png_structp png_ptr, png_bytep data, png_size_t length) {
32 std::vector<uint8_t> *p = (std::vector<uint8_t> *)png_get_io_ptr(png_ptr);
33 p->insert(p->end(), data, data + length);
36void PngReadCallback(png_structp png_ptr, png_bytep outBytes,
37 png_size_t byteCountToRead) {
38 png_voidp io_ptr = png_get_io_ptr(png_ptr);
41 std::vector<uint8_t> *png_data =
42 reinterpret_cast<std::vector<uint8_t> *
>(io_ptr);
43 static size_t pos = 0;
45 if (pos + byteCountToRead <= png_data->size()) {
46 memcpy(outBytes, png_data->data() + pos, byteCountToRead);
47 pos += byteCountToRead;
49 png_error(png_ptr,
"Read error in PngReadCallback");
55bool ConvertSurfaceToPNG(SDL_Surface *surface, std::vector<uint8_t> &buffer) {
56 png_structp png_ptr = png_create_write_struct(
"1.6.40", NULL, NULL, NULL);
58 SDL_Log(
"Failed to create PNG write struct");
62 png_infop info_ptr = png_create_info_struct(png_ptr);
64 png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
65 SDL_Log(
"Failed to create PNG info struct");
69 if (setjmp(png_jmpbuf(png_ptr))) {
70 png_destroy_write_struct(&png_ptr, &info_ptr);
71 SDL_Log(
"Error during PNG write");
75 png_set_write_fn(png_ptr, &buffer, png_internal::PngWriteCallback, NULL);
80 int colortype = PNG_COLOR_MASK_COLOR;
83 if (surface->format->BytesPerPixel > 0 &&
84 surface->format->BytesPerPixel <= 8 && (pal = surface->format->palette)) {
85 SDL_Log(
"Writing PNG image with palette");
86 colortype |= PNG_COLOR_MASK_PALETTE;
87 pal_ptr = (png_colorp)malloc(pal->ncolors *
sizeof(png_color));
88 for (i = 0; i < pal->ncolors; i++) {
89 pal_ptr[i].red = pal->colors[i].r;
90 pal_ptr[i].green = pal->colors[i].g;
91 pal_ptr[i].blue = pal->colors[i].b;
93 png_set_PLTE(png_ptr, info_ptr, pal_ptr, pal->ncolors);
97 if (surface->format->Amask) {
98 colortype |= PNG_COLOR_MASK_ALPHA;
101 auto depth = surface->format->BitsPerPixel;
104 png_set_IHDR(png_ptr, info_ptr, surface->w, surface->h, depth, colortype,
105 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
106 PNG_FILTER_TYPE_DEFAULT);
108 png_set_bgr(png_ptr);
111 std::vector<png_bytep> row_pointers(surface->h);
112 for (
int y = 0; y < surface->h; ++y) {
113 row_pointers[y] = (png_bytep)(surface->pixels) + y * surface->pitch;
116 png_set_rows(png_ptr, info_ptr, row_pointers.data());
118 SDL_Log(
"Writing PNG image...");
119 png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
120 SDL_Log(
"PNG image write complete");
122 png_destroy_write_struct(&png_ptr, &info_ptr);
127void ConvertPngToSurface(
const std::vector<uint8_t> &png_data,
128 SDL_Surface **outSurface) {
129 std::vector<uint8_t> data(png_data);
130 png_structp png_ptr = png_create_read_struct(
"1.6.40", NULL, NULL, NULL);
132 throw std::runtime_error(
"Failed to create PNG read struct");
135 png_infop info_ptr = png_create_info_struct(png_ptr);
137 png_destroy_read_struct(&png_ptr, NULL, NULL);
138 throw std::runtime_error(
"Failed to create PNG info struct");
141 if (setjmp(png_jmpbuf(png_ptr))) {
142 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
143 throw std::runtime_error(
"Error during PNG read");
147 png_set_read_fn(png_ptr, &data, png_internal::PngReadCallback);
150 png_read_info(png_ptr, info_ptr);
152 uint32_t width = png_get_image_width(png_ptr, info_ptr);
153 uint32_t height = png_get_image_height(png_ptr, info_ptr);
154 png_byte color_type = png_get_color_type(png_ptr, info_ptr);
155 png_byte bit_depth = png_get_bit_depth(png_ptr, info_ptr);
161 png_read_update_info(png_ptr, info_ptr);
164 std::vector<uint8_t> raw_data(width * height *
166 std::vector<png_bytep> row_pointers(height);
167 for (
size_t y = 0; y < height; y++) {
168 row_pointers[y] = raw_data.data() + y * width * 4;
171 png_read_image(png_ptr, row_pointers.data());
172 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
175 *outSurface = SDL_CreateRGBSurfaceWithFormat(0, width, height, 32,
176 SDL_PIXELFORMAT_RGBA32);
177 if (*outSurface ==
nullptr) {
178 SDL_Log(
"SDL_CreateRGBSurfaceWithFormat failed: %s\n", SDL_GetError());
183 SDL_LockSurface(*outSurface);
184 memcpy((*outSurface)->pixels, raw_data.data(), raw_data.size());
185 SDL_UnlockSurface(*outSurface);
187 SDL_Log(
"Successfully created SDL_Surface from PNG data");
190std::vector<uint8_t> Bitmap::GetPngData() {
200 for (
int i = 0; i < 8; i++) {
201 palette->colors[i].r = i * 31;
202 palette->colors[i].g = i * 31;
203 palette->colors[i].b = i * 31;
210 return SDL_PIXELFORMAT_INDEX8;
218 return SDL_PIXELFORMAT_INDEX8;
223 SDL_SaveBMP(
surface_.get(), filename.data());
231 const std::vector<uint8_t> &data) {
236 const std::vector<uint8_t> &data) {
238 SDL_Log(
"Bitmap data is empty\n");
249 SDL_Log(
"Data provided to Bitmap is empty.\n");
253 surface_ = std::shared_ptr<SDL_Surface>{
255 GetSnesPixelFormat(format)),
258 SDL_Log(
"SDL_CreateRGBSurfaceWithFormat failed: %s\n", SDL_GetError());
267 surface_ = std::unique_ptr<SDL_Surface, SDL_Surface_Deleter>(
269 GetSnesPixelFormat(format)),
274 if (!apply_palette.ok()) {
275 SDL_Log(
"Failed to apply palette: %s\n", apply_palette.message().data());
282 SDL_Log(
"Invalid texture dimensions: width=%d, height=%d\n",
width_,
287 texture_ = std::shared_ptr<SDL_Texture>{
288 SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB888,
292 SDL_Log(
"SDL_CreateTextureFromSurface failed: %s\n", SDL_GetError());
296 SDL_ConvertSurfaceFormat(
surface_.get(), SDL_PIXELFORMAT_ARGB8888, 0),
299 SDL_Log(
"SDL_ConvertSurfaceFormat failed: %s\n", SDL_GetError());
312 SDL_ConvertSurfaceFormat(
surface_.get(), SDL_PIXELFORMAT_ARGB8888, 0);
317 SDL_Log(
"SDL_ConvertSurfaceFormat failed: %s\n", SDL_GetError());
329 return absl::FailedPreconditionError(
330 "Surface is null. Palette not applied");
333 return absl::FailedPreconditionError(
334 "Surface format or palette is null. Palette not applied.");
340 return absl::InternalError(
"Failed to get SDL palette");
344 for (
size_t i = 0; i <
palette.size(); ++i) {
353 return absl::OkStatus();
358 auto start_index = palette_id * 8;
363 if (pal_color.is_transparent()) {
364 surface_->format->palette->colors[i].r = 0;
365 surface_->format->palette->colors[i].g = 0;
366 surface_->format->palette->colors[i].b = 0;
367 surface_->format->palette->colors[i].a = 0;
369 surface_->format->palette->colors[i].r = pal_color.rgb().x;
370 surface_->format->palette->colors[i].g = pal_color.rgb().y;
371 surface_->format->palette->colors[i].b = pal_color.rgb().z;
372 surface_->format->palette->colors[i].a = pal_color.rgb().w;
377 return absl::OkStatus();
381 size_t index,
int length) {
382 if (index < 0 || index >=
palette.size()) {
383 return absl::InvalidArgumentError(
"Invalid palette index");
386 if (length < 0 || length >
palette.size()) {
387 return absl::InvalidArgumentError(
"Invalid palette length");
390 if (index + length >
palette.size()) {
391 return absl::InvalidArgumentError(
"Palette index + length exceeds size");
395 return absl::FailedPreconditionError(
396 "Surface is null. Palette not applied");
399 auto start_index = index * 7;
401 std::vector<ImVec4> colors;
402 colors.push_back(ImVec4(0, 0, 0, 0));
403 for (
int i = start_index; i < start_index + 7; ++i) {
405 colors.push_back(pal_color.rgb());
410 for (
auto &each : colors) {
411 surface_->format->palette->colors[i].r = each.x;
412 surface_->format->palette->colors[i].g = each.y;
413 surface_->format->palette->colors[i].b = each.z;
414 surface_->format->palette->colors[i].a = each.w;
419 return absl::OkStatus();
424 for (
size_t i = 0; i <
palette.size(); ++i) {
434 std::vector<uint8_t> &tile_data,
435 int &tile_data_offset) {
437 int tile_x = (x * 8) %
width_;
438 int tile_y = (y * 8) %
height_;
439 for (
int i = 0; i < 8; i++) {
440 int row_offset = tile_offset + ((tile_y + i) *
width_);
441 for (
int j = 0; j < 8; j++) {
442 int pixel_offset = row_offset + (tile_x + j);
443 int pixel_value =
data_[pixel_offset];
444 tile_data[tile_data_offset] = pixel_value;
451 std::vector<uint8_t> &tile_data,
452 int &tile_data_offset) {
453 for (
int ty = 0; ty < 16; ty++) {
454 for (
int tx = 0; tx < 16; tx++) {
456 int pixel_x = tile_x + tx;
457 int pixel_y = tile_y + ty;
458 int pixel_offset = (pixel_y *
width_) + pixel_x;
459 int pixel_value =
data_[pixel_offset];
462 tile_data[tile_data_offset++] = pixel_value;
470 sdl_color.r =
static_cast<Uint8
>(color.x * 255);
471 sdl_color.g =
static_cast<Uint8
>(color.y * 255);
472 sdl_color.b =
static_cast<Uint8
>(color.z * 255);
473 sdl_color.a =
static_cast<Uint8
>(color.w * 255);
477 SDL_MapRGB(
surface_->format, sdl_color.r, sdl_color.g, sdl_color.b);