summaryrefslogtreecommitdiff
path: root/png8.c
diff options
context:
space:
mode:
authorIan C <ianc@noddybox.co.uk>2016-11-28 16:00:48 +0000
committerIan C <ianc@noddybox.co.uk>2016-11-28 16:00:48 +0000
commit112ae49145da644f0e6a682d5e45be23cfd3d44b (patch)
treee8fad7a030667ee02dc0b25b021342509dc4435c /png8.c
parent119fd651b00b94350ae97ae4fdceeffa6d4f71e2 (diff)
Initial seemingly working version.
Diffstat (limited to 'png8.c')
-rwxr-xr-xpng8.c275
1 files changed, 272 insertions, 3 deletions
diff --git a/png8.c b/png8.c
index 6022562..6db1769 100755
--- a/png8.c
+++ b/png8.c
@@ -41,7 +41,8 @@
#define FALSE (0)
#endif
-#define IS_BLACK(ul) (((ul) && 0x00FFFFFFul) == 0)
+#define COLOUR(ul) ((ul) & 0x00FFFFFFul)
+#define IS_BLACK(ul) (COLOUR(ul) == 0)
#define IS_TRANS(ul) (((ul) && 0xFF000000ul) == 0)
@@ -92,9 +93,15 @@ static void Help(void)
"-1 - Produce a monochrome sprite data set (e.g. Spectrum).\n"
"-4 - Produce a 4-colour sprite data set (e.g. Commodore 64).\n"
"\nOptional switches:\n"
-"-s - Treat black the same as a transparent pixel.\n"
+"-b - Don't treat black the same as a transparent pixel.\n"
"-p <text> - Use <text> in place of 'byte' for output.\n"
-"-i - For monochrome data, produce pre-shifted values.\n"
+"-s - For monochrome data, produce pre-shifted values.\n"
+"-w <width> - Set the sprite width to <width>. This must be a multiple of 8.\n"
+"-d - Don't use double-width pixels in 4 colour mode.\n"
+"-c0 - Set colour 0 to RGB value RRGGBB, expressed as a hex number.\n"
+"-c1 - Set colour 1 to RGB value RRGGBB, expressed as a hex number.\n"
+"-c2 - Set colour 2 to RGB value RRGGBB, expressed as a hex number.\n"
+"-c3 - Set colour 3 to RGB value RRGGBB, expressed as a hex number.\n"
"";
fprintf(stderr,"%s\n", help);
@@ -116,6 +123,18 @@ static void Exit(const char *fmt, ...)
}
+static void Warning(const char *fmt, ...)
+{
+ va_list va;
+
+ fprintf(stderr, "WARNING: ");
+
+ va_start(va, fmt);
+ vfprintf(stderr, fmt, va);
+ va_end(va);
+}
+
+
static void *Malloc(size_t size)
{
void *p = malloc(size);
@@ -138,6 +157,84 @@ static ulong RGBA(png_byte r, png_byte g, png_byte b, png_byte a)
}
+static void PrintSpriteData(const char *opcode,
+ ulong sprite_data[],
+ int max,
+ int pre_shift)
+{
+ int f;
+
+ printf("\t%s ", opcode);
+
+ for(f = 0; f < max; f++)
+ {
+ if (f)
+ {
+ printf(",");
+ }
+
+ printf("%lu", sprite_data[f]);
+ }
+
+ if (pre_shift)
+ {
+ printf(",0");
+ }
+
+ printf("\n");
+}
+
+
+static void PrintSpriteDataShifted(const char *opcode,
+ ulong sprite_data[],
+ int max)
+{
+ int s;
+ int f;
+ ulong data[8][5] = {0};
+
+ for(s = 1; s < 8; s++)
+ {
+ for(f = 0; f <= max; f++)
+ {
+ if (f == max)
+ {
+ data[s][f] = (sprite_data[f-1] << (8 - s)) & 0xff;
+ }
+ else if (f)
+ {
+ data[s][f] =
+ ((sprite_data[f] >> s) | (sprite_data[f-1] << (8 - s)))
+ & 0xff;
+ }
+ else
+ {
+ data[s][f] = sprite_data[f] >> s;
+ }
+ }
+ }
+
+ max++;
+
+ for(s = 1; s < 8; s++)
+ {
+ printf("\t%s ", opcode);
+
+ for(f = 0; f < max; f++)
+ {
+ if (f)
+ {
+ printf(",");
+ }
+
+ printf("%lu", data[s][f]);
+ }
+
+ printf("\n");
+ }
+}
+
+
/* ---------------------------------------- MAIN
*/
int main(int argc, char *argv[])
@@ -151,6 +248,11 @@ int main(int argc, char *argv[])
const char *opcode = "byte";
output_type_t output = OUTPUT_Undefined;
int pre_shift = FALSE;
+ int use_black = TRUE;
+ int sprite_width = 8;
+ int pix_per_byte = 8;
+ int step = 1;
+ ulong col[4] = {0, 0xff0000ul, 0x00ff00ul, 0x0000fful};
int f;
FILE *fp;
char header[8];
@@ -171,6 +273,74 @@ int main(int argc, char *argv[])
case '4':
output = OUTPUT_4Col;
+ sprite_width = 24;
+ step = 2;
+ pix_per_byte = 4;
+ pre_shift = FALSE;
+ break;
+
+ case 'b':
+ use_black = FALSE;
+ break;
+
+ case 's':
+ if (output != OUTPUT_4Col)
+ {
+ pre_shift = TRUE;
+ }
+ break;
+
+ case 'd':
+ step = 1;
+ break;
+
+ case 'c':
+ {
+ int c = argv[f][2] - '0';
+
+ if (argv[++f] && c >= 0 && c <= 3)
+ {
+ col[c] = strtoul(argv[f], NULL, 16);
+ }
+ else
+ {
+ Usage();
+ }
+
+ break;
+ }
+
+ case 'p':
+ if (argv[++f])
+ {
+ opcode = argv[f];
+ }
+ else
+ {
+ Usage();
+ }
+ break;
+
+ case 'w':
+ if (argv[++f])
+ {
+ sprite_width = atoi(argv[f]);
+
+ if (sprite_width % 8)
+ {
+ Exit("Sprite width must be a multiple of 8.\n");
+ }
+
+ if (sprite_width < 8 || sprite_width > 32)
+ {
+ Exit("Sprite width mustn't be greater than "
+ "32 or less than 8.\n");
+ }
+ }
+ else
+ {
+ Usage();
+ }
break;
default:
@@ -224,6 +394,22 @@ int main(int argc, char *argv[])
colour_depth = png_get_bit_depth(png, png_info);
num_passes = png_set_interlace_handling(png);
+ if (width < sprite_width * step)
+ {
+ Exit("Width %d less than sprite width %d\n", width,
+ sprite_width * step);
+ }
+
+ if (width % (sprite_width * step))
+ {
+ Warning("Width not a multiple of %d.\n", sprite_width * step);
+ }
+
+ if (sprite_width > 16 && output == OUTPUT_4Col)
+ {
+ Exit("Width must be 16 or less in 4-colour mode.\n");
+ }
+
if (colour_type != PNG_COLOR_TYPE_RGBA)
{
Exit("PNG must be an RGB image with an alpha channel.\n");
@@ -247,6 +433,89 @@ int main(int argc, char *argv[])
fclose(fp);
+ for(f = 0; f < width/(sprite_width*step); f++)
+ {
+ int x,y;
+ int bx;
+
+ printf("sprite_%d:\n", f);
+
+ bx = sprite_width * step * f * 4;
+
+ for(y = 0; y < height; y++)
+ {
+ ulong sprite_data[4] = {0};
+ int i = 0;
+
+ for(x = 0; x < sprite_width; x++)
+ {
+ ulong pcol = RGBA(data[y][bx + x * 4 * step + 0],
+ data[y][bx + x * 4 * step + 1],
+ data[y][bx + x * 4 * step + 2],
+ data[y][bx + x * 4 * step + 3]);
+
+ if ((x) && (x % pix_per_byte) == 0)
+ {
+ i++;
+ }
+
+ switch(output)
+ {
+ case OUTPUT_Mono:
+ if (IS_TRANS(pcol) || (use_black && IS_BLACK(pcol)))
+ {
+ sprite_data[i] <<= 1ul;
+ sprite_data[i] |= 0;
+ }
+ else
+ {
+ sprite_data[i] <<= 1ul;
+ sprite_data[i] |= 1;
+ }
+ break;
+
+ case OUTPUT_4Col:
+ if (COLOUR(pcol) == col[1])
+ {
+ sprite_data[i] <<= 2ul;
+ sprite_data[i] |= 0x01;
+ }
+ else if (COLOUR(pcol) == col[2])
+ {
+ sprite_data[i] <<= 2ul;
+ sprite_data[i] |= 0x02;
+ }
+ else if (COLOUR(pcol) == col[3])
+ {
+ sprite_data[i] <<= 2ul;
+ sprite_data[i] |= 0x03;
+ }
+ else
+ {
+ sprite_data[i] <<= 2ul;
+ sprite_data[i] |= 0;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if ((x) && (x % pix_per_byte) == 0)
+ {
+ i++;
+ }
+
+ PrintSpriteData(opcode, sprite_data, i, pre_shift);
+
+ if (pre_shift)
+ {
+ PrintSpriteDataShifted(opcode, sprite_data, i);
+ }
+ }
+ }
+
for(f = 0; f < height; f++)
{
free(data[f]);