31namespace png_internal {
33void PngWriteCallback(png_structp png_ptr, png_bytep data, png_size_t length) {
34 std::vector<uint8_t> *p = (std::vector<uint8_t> *)png_get_io_ptr(png_ptr);
35 p->insert(p->end(), data, data + length);
38void PngReadCallback(png_structp png_ptr, png_bytep outBytes,
39 png_size_t byteCountToRead) {
40 png_voidp io_ptr = png_get_io_ptr(png_ptr);
43 std::vector<uint8_t> *png_data =
44 reinterpret_cast<std::vector<uint8_t> *
>(io_ptr);
45 static size_t pos = 0;
47 if (pos + byteCountToRead <= png_data->size()) {
48 memcpy(outBytes, png_data->data() + pos, byteCountToRead);
49 pos += byteCountToRead;
51 png_error(png_ptr,
"Read error in PngReadCallback");
57bool ConvertSurfaceToPNG(SDL_Surface *surface, std::vector<uint8_t> &buffer) {
58 png_structp png_ptr = png_create_write_struct(
"1.6.40", NULL, NULL, NULL);
60 SDL_Log(
"Failed to create PNG write struct");
64 png_infop info_ptr = png_create_info_struct(png_ptr);
66 png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
67 SDL_Log(
"Failed to create PNG info struct");
71 if (setjmp(png_jmpbuf(png_ptr))) {
72 png_destroy_write_struct(&png_ptr, &info_ptr);
73 SDL_Log(
"Error during PNG write");
77 png_set_write_fn(png_ptr, &buffer, png_internal::PngWriteCallback, NULL);
82 int colortype = PNG_COLOR_MASK_COLOR;
85 if (surface->format->BytesPerPixel > 0 &&
86 surface->format->BytesPerPixel <= 8 && (pal = surface->format->palette)) {
87 SDL_Log(
"Writing PNG image with palette");
88 colortype |= PNG_COLOR_MASK_PALETTE;
89 pal_ptr = (png_colorp)malloc(pal->ncolors *
sizeof(png_color));
90 for (i = 0; i < pal->ncolors; i++) {
91 pal_ptr[i].red = pal->colors[i].r;
92 pal_ptr[i].green = pal->colors[i].g;
93 pal_ptr[i].blue = pal->colors[i].b;
95 png_set_PLTE(png_ptr, info_ptr, pal_ptr, pal->ncolors);
99 if (surface->format->Amask) {
100 colortype |= PNG_COLOR_MASK_ALPHA;
103 auto depth = surface->format->BitsPerPixel;
106 png_set_IHDR(png_ptr, info_ptr, surface->w, surface->h, depth, colortype,
107 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
108 PNG_FILTER_TYPE_DEFAULT);
110 png_set_bgr(png_ptr);
113 std::vector<png_bytep> row_pointers(surface->h);
114 for (
int y = 0; y < surface->h; ++y) {
115 row_pointers[y] = (png_bytep)(surface->pixels) + y * surface->pitch;
118 png_set_rows(png_ptr, info_ptr, row_pointers.data());
120 SDL_Log(
"Writing PNG image...");
121 png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
122 SDL_Log(
"PNG image write complete");
124 png_destroy_write_struct(&png_ptr, &info_ptr);
129void ConvertPngToSurface(
const std::vector<uint8_t> &png_data,
130 SDL_Surface **outSurface) {
131 std::vector<uint8_t> data(png_data);
132 png_structp png_ptr = png_create_read_struct(
"1.6.40", NULL, NULL, NULL);
134 throw std::runtime_error(
"Failed to create PNG read struct");
137 png_infop info_ptr = png_create_info_struct(png_ptr);
139 png_destroy_read_struct(&png_ptr, NULL, NULL);
140 throw std::runtime_error(
"Failed to create PNG info struct");
143 if (setjmp(png_jmpbuf(png_ptr))) {
144 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
145 throw std::runtime_error(
"Error during PNG read");
149 png_set_read_fn(png_ptr, &data, png_internal::PngReadCallback);
152 png_read_info(png_ptr, info_ptr);
154 uint32_t width = png_get_image_width(png_ptr, info_ptr);
155 uint32_t height = png_get_image_height(png_ptr, info_ptr);
156 png_byte color_type = png_get_color_type(png_ptr, info_ptr);
157 png_byte bit_depth = png_get_bit_depth(png_ptr, info_ptr);
163 png_read_update_info(png_ptr, info_ptr);
166 std::vector<uint8_t> raw_data(width * height *
168 std::vector<png_bytep> row_pointers(height);
169 for (
size_t y = 0; y < height; y++) {
170 row_pointers[y] = raw_data.data() + y * width * 4;
173 png_read_image(png_ptr, row_pointers.data());
174 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
177 *outSurface = SDL_CreateRGBSurfaceWithFormat(0, width, height, 32,
178 SDL_PIXELFORMAT_RGBA32);
179 if (*outSurface ==
nullptr) {
180 SDL_Log(
"SDL_CreateRGBSurfaceWithFormat failed: %s\n", SDL_GetError());
185 SDL_LockSurface(*outSurface);
186 memcpy((*outSurface)->pixels, raw_data.data(), raw_data.size());
187 SDL_UnlockSurface(*outSurface);
189 SDL_Log(
"Successfully created SDL_Surface from PNG data");
192std::vector<uint8_t> Bitmap::GetPngData() {
202 for (
int i = 0; i < 8; i++) {
203 palette->colors[i].r = i * 31;
204 palette->colors[i].g = i * 31;
205 palette->colors[i].b = i * 31;
212 return SDL_PIXELFORMAT_INDEX8;
220 return SDL_PIXELFORMAT_INDEX8;
225 SDL_SaveBMP(
surface_.get(), filename.data());
233 const std::vector<uint8_t> &data) {
238 const std::vector<uint8_t> &data) {
240 SDL_Log(
"Bitmap data is empty\n");
251 SDL_Log(
"Data provided to Bitmap is empty.\n");
255 surface_ = std::shared_ptr<SDL_Surface>{
257 GetSnesPixelFormat(format)),
260 SDL_Log(
"SDL_CreateRGBSurfaceWithFormat failed: %s\n", SDL_GetError());
269 surface_ = std::unique_ptr<SDL_Surface, SDL_Surface_Deleter>(
271 GetSnesPixelFormat(format)),
276 if (!apply_palette.ok()) {
277 SDL_Log(
"Failed to apply palette: %s\n", apply_palette.message().data());
284 SDL_Log(
"Invalid texture dimensions: width=%d, height=%d\n",
width_,
289 texture_ = std::shared_ptr<SDL_Texture>{
290 SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB888,
294 SDL_Log(
"SDL_CreateTextureFromSurface failed: %s\n", SDL_GetError());
298 SDL_ConvertSurfaceFormat(
surface_.get(), SDL_PIXELFORMAT_ARGB8888, 0),
301 SDL_Log(
"SDL_ConvertSurfaceFormat failed: %s\n", SDL_GetError());
314 SDL_ConvertSurfaceFormat(
surface_.get(), SDL_PIXELFORMAT_ARGB8888, 0);
319 SDL_Log(
"SDL_ConvertSurfaceFormat failed: %s\n", SDL_GetError());
324 if (use_sdl_update) {
335 texture_ = std::shared_ptr<SDL_Texture>{
336 SDL_CreateTextureFromSurface(renderer.get(),
surface_.get()),
341 texture_ = std::shared_ptr<SDL_Texture>{
342 SDL_CreateTextureFromSurface(renderer.get(),
surface_.get()),
348 return absl::FailedPreconditionError(
349 "Surface is null. Palette not applied");
352 return absl::FailedPreconditionError(
353 "Surface format or palette is null. Palette not applied.");
359 return absl::InternalError(
"Failed to get SDL palette");
363 for (
size_t i = 0; i <
palette.size(); ++i) {
372 return absl::OkStatus();
377 auto start_index = palette_id * 8;
382 if (pal_color.is_transparent()) {
383 surface_->format->palette->colors[i].r = 0;
384 surface_->format->palette->colors[i].g = 0;
385 surface_->format->palette->colors[i].b = 0;
386 surface_->format->palette->colors[i].a = 0;
388 surface_->format->palette->colors[i].r = pal_color.rgb().x;
389 surface_->format->palette->colors[i].g = pal_color.rgb().y;
390 surface_->format->palette->colors[i].b = pal_color.rgb().z;
391 surface_->format->palette->colors[i].a = pal_color.rgb().w;
396 return absl::OkStatus();
400 size_t index,
int length) {
401 if (index < 0 || index >=
palette.size()) {
402 return absl::InvalidArgumentError(
"Invalid palette index");
405 if (length < 0 || length >
palette.size()) {
406 return absl::InvalidArgumentError(
"Invalid palette length");
409 if (index + length >
palette.size()) {
410 return absl::InvalidArgumentError(
"Palette index + length exceeds size");
414 return absl::FailedPreconditionError(
415 "Surface is null. Palette not applied");
418 auto start_index = index * 7;
420 std::vector<ImVec4> colors;
421 colors.push_back(ImVec4(0, 0, 0, 0));
422 for (
int i = start_index; i < start_index + 7; ++i) {
424 colors.push_back(pal_color.rgb());
429 for (
auto &each : colors) {
430 surface_->format->palette->colors[i].r = each.x;
431 surface_->format->palette->colors[i].g = each.y;
432 surface_->format->palette->colors[i].b = each.z;
433 surface_->format->palette->colors[i].a = each.w;
438 return absl::OkStatus();
443 for (
size_t i = 0; i <
palette.size(); ++i) {
453 std::vector<uint8_t> &tile_data,
454 int &tile_data_offset) {
456 int tile_x = (x * 8) %
width_;
457 int tile_y = (y * 8) %
height_;
458 for (
int i = 0; i < 8; i++) {
459 int row_offset = tile_offset + ((tile_y + i) *
width_);
460 for (
int j = 0; j < 8; j++) {
461 int pixel_offset = row_offset + (tile_x + j);
462 int pixel_value =
data_[pixel_offset];
463 tile_data[tile_data_offset] = pixel_value;
470 std::vector<uint8_t> &tile_data,
471 int &tile_data_offset) {
473 for (
int i = 0; i < 16; i++) {
474 int row_offset = tile_offset + ((i / 8) * (
width_ * 8));
475 for (
int j = 0; j < 16; j++) {
477 row_offset + ((j / 8) * 8) + ((i % 8) *
width_) + (j % 8);
478 int pixel_value =
data_[pixel_offset];
479 tile_data[tile_data_offset] = pixel_value;
486 std::vector<uint8_t> &tile_data,
487 int &tile_data_offset) {
488 for (
int ty = 0; ty < 16; ty++) {
489 for (
int tx = 0; tx < 16; tx++) {
491 int pixel_x = tile_x + tx;
492 int pixel_y = tile_y + ty;
493 int pixel_offset = pixel_y *
width_ + pixel_x;
494 int pixel_value =
data_[pixel_offset];
497 tile_data[tile_data_offset++] = pixel_value;
505 sdl_color.r =
static_cast<Uint8
>(color.x * 255);
506 sdl_color.g =
static_cast<Uint8
>(color.y * 255);
507 sdl_color.b =
static_cast<Uint8
>(color.z * 255);
508 sdl_color.a =
static_cast<Uint8
>(color.w * 255);
512 SDL_MapRGB(
surface_->format, sdl_color.r, sdl_color.g, sdl_color.b);