How do I use a color palette with a .PNG?

Unlikely. Compressing is a relatively expensive operation, but extracting is fast.

Wouldn’t PhysicsFS work just as well as zlib? Or are there some extra reasons to use it that I don’t know about? (PhysicsFS doesn’t provide any binaries either…)

Wouldn’t PhysicsFS work just as well as zlib? Or are there some extra reasons to use it that I don’t know about? (PhysicsFS doesn’t provide any binaries either…)

The nice thing about PhysicsFS is that (with physfsrwops.h) you can treat files from the archive as SDL RWops, that you can feed into SDL_Image (IMG_Load_RW()).

But you could of course also use zlib (with its minizip library that handles zips) directly and either use zlib to decompress files from a zip archive into a memory buffer that you feed into SDL_Image, or you write your own glue code between minizip and SDL RWops

1 Like

For anyone seeing this in the future, this is what I did to get it working:

  1. I had to convert the .PNG to a .BMP.
  2. I used Gimp to turn it into a palleted .BMP by doing Image → Mode → Indexed…, then selecting “Generate optimum palette”, and setting "Maximum number of colors: " to 255.
  3. Then, I selected Colors → Map → Rearrange Colormap, and I noted down the palette colors for the actual code. The number on the color directly maps to the index on the palette list.
  4. Then, still in Gimp, I exported it by doing File → Export As… → “[insert image name here].bmp”
  5. I put the exported .BMP file into a .zip file, and put that in the same directory as the project.
  6. Finally, I wrote this code:
#include <stdio.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include "physfs.h" //must compile yourself
#include "physfsrwops.h" //had to compile seperately

int main(int argc, char* argv[]) {
//... (initialization of stuff)

char *zipname = "resources.zip"; //set this to whatever the zip is called
char *filename = "image.bmp"; //set this to whatever the image is called
//.BMP image "image.bmp" is in .ZIP file "resources.zip"

//some code for the PhysicsFS, TL;DR it lets me load stuff from .ZIP files
PHYSFS_init(argv[0]);
if (PHYSFS_addToSearchPath(zipname, 1)) {
    if (PHYSFS_exists(filename)) {
        fprintf(stderr, "File %s found successfully in .zip file: %s.\n", filename, zipname);
    } else {
        fprintf(stderr, "File %s not found in .zip file: %s.\n", filename, zipname);
        return -1;
    }
} else {
    fprintf(stderr, ".zip file not found: %s.\n", zipname);
    return -1;
}

IMG_Init(IMG_INIT_PNG)
SDL_RWops * rwop = PHYSFSRWOPS_openRead(filename);
SDL_Surface* img_surface = SDL_LoadBMP_RW(rwop, 1);

SDL_Color colors[2];
colors[0] = (SDL_Color) {r: 255, g: 0, b: 0, a: 255};
colors[1] = (SDL_Color) {r: 0, g: 0, b: 255, a: 255};
SDL_SetPaletteColors(img_surface->format->palette, colors, 0, 2);
SDL_Texture* img_texture = SDL_CreateTextureFromSurface(renderer, img_surface);

//... (use the texture here)

SDL_FreeSurface(img_surface);

}

More information on how to install PhysicsFS can be found Here.
Note: PhysicsFS is not required for this, but I would highly recommend it, because of the higher file size of .BMP files compared to .PNG files. If you still wish to not use it, replace the line:
SDL_RWops * rwop = PHYSFSRWOPS_openRead(filename);
with:
SDL_RWops * rwop = SDL_RWFromFile(filename, "r");
and then delete any of the PhysicsFS code.