about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2019-03-27 14:27:00 -0400
committerJune McEnroe <june@causal.agency>2019-03-27 14:27:00 -0400
commit154f94d53dc73fad3622b6497fc85e9b93f824b7 (patch)
treec0d212dfef5d257f6183da01326580122f9a8f8a
parentAdd flags to dump (diff)
downloadcards-154f94d53dc73fad3622b6497fc85e9b93f824b7.tar.gz
cards-154f94d53dc73fad3622b6497fc85e9b93f824b7.zip
Add Cards_Invert
-rw-r--r--cards.c45
-rw-r--r--cards.h1
-rw-r--r--dump.c10
3 files changed, 55 insertions, 1 deletions
diff --git a/cards.c b/cards.c
index 174b081..29aa7a4 100644
--- a/cards.c
+++ b/cards.c
@@ -358,6 +358,51 @@ fail:
 	return NULL;
 }
 
+int invertPalette(SDL_Surface *surface) {
+	const SDL_Palette *palette = surface->format->palette;
+	SDL_Palette *invert = SDL_AllocPalette(palette->ncolors);
+	if (!invert) return -1;
+	for (int i = 0; i < invert->ncolors; ++i) {
+		invert->colors[i].r = ~palette->colors[i].r;
+		invert->colors[i].g = ~palette->colors[i].g;
+		invert->colors[i].b = ~palette->colors[i].b;
+		invert->colors[i].a =  palette->colors[i].a;
+	}
+	if (SDL_SetSurfacePalette(surface, invert) < 0) return -1;
+	SDL_FreePalette(invert);
+	return 0;
+}
+
+int invertPixels(SDL_Surface *surface) {
+	if (SDL_LockSurface(surface) < 0) return -1;
+	Uint8 *pixels = surface->pixels;
+	for (int y = 0; y < surface->h; ++y) {
+		Uint32 *row = (Uint32 *)&pixels[y * surface->pitch];
+		for (int x = 0; x < surface->w; ++x) {
+			Uint32 color = ~row[x] & ~surface->format->Amask;
+			Uint32 alpha = row[x] & surface->format->Amask;
+			row[x] = color | alpha;
+		}
+	}
+	SDL_UnlockSurface(surface);
+	return 0;
+}
+
+int Cards_Invert(struct Cards *cards) {
+	for (int i = 0; i < Cards_Count; ++i) {
+		if (!cards->surfaces[i]) continue;
+		if (cards->surfaces[i]->format->palette) {
+			if (invertPalette(cards->surfaces[i]) < 0) return -1;
+		} else if (cards->surfaces[i]->format->BytesPerPixel == 4) {
+			if (invertPixels(cards->surfaces[i]) < 0) return -1;
+		} else {
+			SDL_SetError("unexpected surface format");
+			return -1;
+		}
+	}
+	return 0;
+}
+
 void Cards_Free(struct Cards *cards) {
 	for (int i = 0; i < Cards_Count; ++i) {
 		if (!cards->surfaces[i]) continue;
diff --git a/cards.h b/cards.h
index 0ed1b8f..8cd99c4 100644
--- a/cards.h
+++ b/cards.h
@@ -62,6 +62,7 @@ enum Cards_Flags {
 };
 
 struct Cards *Cards_Load(SDL_RWops *rw, enum Cards_Flags flags);
+int Cards_Invert(struct Cards *cards);
 void Cards_Free(struct Cards *cards);
 
 #endif
diff --git a/dump.c b/dump.c
index 5ad4456..474af92 100644
--- a/dump.c
+++ b/dump.c
@@ -15,6 +15,7 @@
  */
 
 #include <err.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <sysexits.h>
@@ -26,12 +27,14 @@
 
 int main(int argc, char *argv[]) {
 	enum Cards_Flags flags = 0;
+	bool invert = false;
 
 	int opt;
-	while (0 < (opt = getopt(argc, argv, "abk"))) {
+	while (0 < (opt = getopt(argc, argv, "abik"))) {
 		switch (opt) {
 			break; case 'a': flags |= Cards_AlphaCorners;
 			break; case 'b': flags |= Cards_BlackBorders;
+			break; case 'i': invert = true;
 			break; case 'k': flags |= Cards_ColorKey;
 			break; default:  return EX_USAGE;
 		}
@@ -49,6 +52,11 @@ int main(int argc, char *argv[]) {
 	if (!cards) errx(EX_DATAERR, "Cards_Load: %s", SDL_GetError());
 	SDL_RWclose(rw);
 
+	if (invert) {
+		int error = Cards_Invert(cards);
+		if (error) errx(EX_DATAERR, "Cards_Invert: %s", SDL_GetError());
+	}
+
 	for (int i = 0; i < Cards_Count; ++i) {
 		if (!cards->surfaces[i]) continue;
 		char name[sizeof("00.bmp")];