From cfe857dff1673eaca4988a3a2753b9211980d19b Mon Sep 17 00:00:00 2001 From: Vince Weaver Date: Sat, 30 Sep 2023 00:50:37 -0400 Subject: [PATCH] second: work on automatic conversion --- demos/second/part18_3d/auto/Makefile | 24 + demos/second/part18_3d/auto/NOTES | 18 + demos/second/part18_3d/auto/box_convert.c | 179 ++++++++ demos/second/part18_3d/auto/loadpng.c | 527 ++++++++++++++++++++++ demos/second/part18_3d/auto/loadpng.h | 11 + 5 files changed, 759 insertions(+) create mode 100644 demos/second/part18_3d/auto/Makefile create mode 100644 demos/second/part18_3d/auto/NOTES create mode 100644 demos/second/part18_3d/auto/box_convert.c create mode 100644 demos/second/part18_3d/auto/loadpng.c create mode 100644 demos/second/part18_3d/auto/loadpng.h diff --git a/demos/second/part18_3d/auto/Makefile b/demos/second/part18_3d/auto/Makefile new file mode 100644 index 00000000..ac268c36 --- /dev/null +++ b/demos/second/part18_3d/auto/Makefile @@ -0,0 +1,24 @@ +CC = gcc +CFLAGS = -g -Wall -O2 + +all: box_convert + +### + +loadpng.o: loadpng.c loadpng.h + $(CC) $(CFLAGS) -c loadpng.c + + +### + +box_convert: box_convert.o loadpng.o + $(CC) $(LFLAGS) -o box_convert box_convert.o loadpng.o -lpng + +box_convert.o: box_convert.c loadpng.h + $(CC) $(CFLAGS) -c box_convert.c + +### + +clean: + rm -f *~ *.o box_convert + diff --git a/demos/second/part18_3d/auto/NOTES b/demos/second/part18_3d/auto/NOTES new file mode 100644 index 00000000..5f6954c7 --- /dev/null +++ b/demos/second/part18_3d/auto/NOTES @@ -0,0 +1,18 @@ +frame50 as benchmark: + + raw binary is 1024 bytes (2048 pixels) + +hand-crafted: + + 25e0 - 24d8 = 264 bytes + +todo, compressed: + + ??? + + +try1: all plots, even zeros + + 2c2 - 20c2 = 7680 bytes (4 bytes each pixel) + +try2: all plots, don't write black pixels + + 2c2 - 147b = 4537 bytes + +try3: only do color if it changes + + 2c2 - 1137 = 3701 bytes diff --git a/demos/second/part18_3d/auto/box_convert.c b/demos/second/part18_3d/auto/box_convert.c new file mode 100644 index 00000000..150599f8 --- /dev/null +++ b/demos/second/part18_3d/auto/box_convert.c @@ -0,0 +1,179 @@ +/* box_convert */ + +/* Try to automate the loser conversion process */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "loadpng.h" + +int main(int argc, char **argv) { + + int row=0; + int col=0; + int pixel; + int i; + + unsigned char *image; + int xsize,ysize; + + if (argc<1) { + fprintf(stderr,"Usage:\t%s INFILE\n",argv[0]); + exit(-1); + } + + if (loadpng(argv[1],&image,&xsize,&ysize,PNG_WHOLETHING)<0) { + fprintf(stderr,"Error loading png!\n"); + exit(-1); + } + + fprintf(stderr,"Loaded image %d by %d\n",xsize,ysize); + + if (ysize!=48) { + fprintf(stderr,"Error! Ysize must be 48!\n"); + exit(1); + } + + if (xsize==40) { + + } + else if (xsize==80) { + + } + else { + fprintf(stderr,"Error! Improper xsize %d!\n",xsize); + exit(1); + } + + +char color_names[16][16]={ + "BLACK", /* $00 */ + "RED", /* $01 */ + "DARK_BLUE", /* $02 */ + "MAGENTA", /* $03 */ + "GREEN", /* $04 */ + "GREY1", /* $05 */ + "MEDIUM_BLUE", /* $06 */ + "LIGHT_BLUE", /* $07 */ + "BROWN", /* $08 */ + "ORANGE", /* $09 */ + "GREY2", /* $0A */ + "PINK", /* $0B */ + "LIGHT_GREEN", /* $0C */ + "YELLOW", /* $0D */ + "AQUA", /* $0E */ + "WHITE", /* $0F */ +}; + + +/* SET_COLOR = $C0 */ + +#define ACTION_END 0x0 +#define ACTION_CLEAR 0x1 +#define ACTION_BOX 0x2 +#define ACTION_HLIN 0x3 +#define ACTION_VLIN 0x4 +#define ACTION_PLOT 0x5 +#define ACTION_HLIN_ADD 0x6 +#define ACTION_HLIN_ADD_LSAME 0x7 +#define ACTION_HLIN_ADD_RSAME 0x8 + +char action_names[9][16]={ + "END","CLEAR","BOX","HLIN","VLIN","PLOT", + "HLIN_ADD","HLIN_ADD_LSAME","HLIN_ADD_RSAME" +}; + + int color_count[16]; + int framebuffer[40][48]; + int current_color=0; + + struct { + int type; + int color; + int x1,y1,x2,y2; + } primitive_list[4096]; + + int current_primitive=0; + + memset(color_count,0,16*sizeof(int)); + + for(row=0;row<24;row++) { + for(col=0;col<40;col++) { + pixel=(image[row*40+col]); + color_count[pixel&0xf]++; + color_count[(pixel>>4)&0xf]++; + framebuffer[col][row*2]=pixel&0xf; + framebuffer[col][(row*2)+1]=(pixel>>4)&0xf; + } + } + + /* TODO: sort */ + printf("; Histogram\n"); + for(i=0;i<16;i++) { + printf("; $%02X %s: %d\n",i,color_names[i],color_count[i]); + } + + /* Initial Implementation, All Plots */ + current_primitive=0; + for(row=0;row<48;row++) { + for(col=0;col<40;col++) { + primitive_list[current_primitive].color=framebuffer[col][row]; + primitive_list[current_primitive].x1=col; + primitive_list[current_primitive].y1=row; + primitive_list[current_primitive].type=ACTION_PLOT; + current_primitive++; + + } + } + + /* Dump results */ + for(i=0;i +#include + +#include +#include +#include +#include +#include + +#include +#include "loadpng.h" + +static int convert_color(int color, char *filename) { + + int c=0; + + switch(color) { + case 0x000000: c=0; break; /* black */ + case 0xe31e60: c=1; break; /* magenta */ + case 0x604ebd: c=2; break; /* dark blue */ + case 0xff44fd: c=3; break; /* purple */ + case 0x00a360: c=4; break; /* dark green */ + case 0x9c9c9c: c=5; break; /* grey 1 */ + case 0x14cffd: c=6; break; /* medium blue */ + case 0xd0c3ff: c=7; break; /* light blue */ + case 0x607203: c=8; break; /* brown */ + case 0xff6a3c: c=9; break; /* orange */ + case 0x9d9d9d: c=10; break; /* grey 2 */ + case 0xffa0d0: c=11; break; /* pink */ + case 0x14f53c: c=12; break; /* bright green */ + case 0xd0dd8d: c=13; break; /* yellow */ + case 0x72ffd0: c=14; break; /* aqua */ + case 0xffffff: c=15; break; /* white */ + default: + fprintf(stderr,"Unknown color %x, file %s\n", + color,filename); + exit(-1); + break; + } + + return c; +} + +/* expects a PNG where the xsize is either 40 or 80 or 280 */ +/* if it is 80, it skips every other */ +/* if 280, it skips every 7 */ + +/* why do that? when editing an image the aspect ratio looks better if */ +/* it is an 80 wide picture */ + +/* xsize, ysize is the size of the result, not size of */ +/* the input image */ +int loadpng(char *filename, unsigned char **image_ptr, int *xsize, int *ysize, + int png_type) { + + int x,y,ystart,yadd,xadd; + int color; + FILE *infile; + int debug=0; + unsigned char *image,*out_ptr; + int width, height; + int a2_color; + + png_byte bit_depth; + png_structp png_ptr; + png_infop info_ptr; + png_bytep *row_pointers; + png_byte color_type; + + unsigned char header[8]; + + /* open file and test for it being a png */ + infile = fopen(filename, "rb"); + if (infile==NULL) { + fprintf(stderr,"Error! Could not open %s\n",filename); + return -1; + } + + /* Check the header */ + fread(header, 1, 8, infile); + if (png_sig_cmp(header, 0, 8)) { + fprintf(stderr,"Error! %s is not a PNG file\n",filename); + return -1; + } + + /* initialize stuff */ + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) { + fprintf(stderr,"Error create_read_struct\n"); + exit(-1); + } + + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + fprintf(stderr,"Error png_create_info_struct\n"); + exit(-1); + } + + png_init_io(png_ptr, infile); + png_set_sig_bytes(png_ptr, 8); + + png_read_info(png_ptr, info_ptr); + + width = png_get_image_width(png_ptr, info_ptr); + height = png_get_image_height(png_ptr, info_ptr); + + /* get the xadd */ + if (width==40) { + *xsize=40; + xadd=1; + yadd=1; + } + else if (width==80) { + if (png_type==PNG_NO_ADJUST) { + *xsize=80; + xadd=1; + } + else { + *xsize=40; + xadd=2; + } + yadd=1; + } + else if (width==280) { + *xsize=40; + xadd=7; + yadd=4; /* FIXME: check we are 192 in ysize */ + } + else if (width==16) { + *xsize=16; + xadd=1; + yadd=1; + } + else { + fprintf(stderr,"Unsupported width %d\n",width); + return -1; + } + + if ((png_type==PNG_WHOLETHING) || (png_type==PNG_NO_ADJUST)) { + *ysize=height; + ystart=0; + yadd*=2; + } + else if (png_type==PNG_ODDLINES) { + *ysize=height/2; + ystart=1; + yadd*=4; + } + else if (png_type==PNG_EVENLINES) { + *ysize=height/2; + ystart=0; + yadd*=4; + } + else if (png_type==PNG_RAW) { + /* FIXME, not working */ + *ysize=height; + ystart=0; + yadd=1; + } + else { + fprintf(stderr,"Unknown PNG type\n"); + return -1; + } + + color_type = png_get_color_type(png_ptr, info_ptr); + bit_depth = png_get_bit_depth(png_ptr, info_ptr); + + if (debug) { + printf("PNG: width=%d height=%d depth=%d\n",width,height,bit_depth); + if (color_type==PNG_COLOR_TYPE_RGB) printf("Type RGB\n"); + else if (color_type==PNG_COLOR_TYPE_RGB_ALPHA) printf("Type RGBA\n"); + else if (color_type==PNG_COLOR_TYPE_PALETTE) printf("Type palette\n"); + printf("Generating output size %d x %d\n",*xsize,*ysize); + } + +// number_of_passes = png_set_interlace_handling(png_ptr); + png_read_update_info(png_ptr, info_ptr); + + row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height); + for (y=0; y>4); + } + a2_color&=0xf; + + /* bottom color */ + color=row_pointers[y+(yadd/2)][x/2]; + if (x%2==0) { + color=(color>>4); + } + color&=0xf; + + a2_color|=(color<<4); + + if (debug) { + printf("%x ",a2_color); + } + + *out_ptr=a2_color; + out_ptr++; + + } + } + if (debug) printf("\n"); + } + } + else { + printf("Unknown color type\n"); + } + + /* Stripe test image */ +// for(x=0;x<40;x++) for(y=0;y<40;y++) image[(y*width)+x]=y%16; + +/* + Addr Row /80 %40 + $400 0 0 0 0 + $428 28 16 0 + $450 50 32 0 + $480 80 2 1 + $4A8 a8 18 1 + $4D0 d0 34 1 + $500 100 3 2 + 0,0 0,1 0,2....0,39 16,0 16,1 ....16,39 32,0..32,39, X X X X X X X X +*/ + + *image_ptr=image; + + return 0; +} + + + +/* for 80 column mode or double-lores */ +int loadpng80(char *filename, unsigned char **image_ptr, int *xsize, int *ysize, + int png_type) { + + int x,y,ystart,yadd,xadd; + int color; + FILE *infile; + int debug=0; + unsigned char *image,*out_ptr; + int width, height; + int a2_color; + + png_byte bit_depth; + png_structp png_ptr; + png_infop info_ptr; + png_bytep *row_pointers; + png_byte color_type; + + unsigned char header[8]; + + /* open file and test for it being a png */ + infile = fopen(filename, "rb"); + if (infile==NULL) { + fprintf(stderr,"Error! Could not open %s\n",filename); + return -1; + } + + /* Check the header */ + fread(header, 1, 8, infile); + if (png_sig_cmp(header, 0, 8)) { + fprintf(stderr,"Error! %s is not a PNG file\n",filename); + return -1; + } + + /* initialize stuff */ + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) { + fprintf(stderr,"Error create_read_struct\n"); + exit(-1); + } + + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + fprintf(stderr,"Error png_create_info_struct\n"); + exit(-1); + } + + png_init_io(png_ptr, infile); + png_set_sig_bytes(png_ptr, 8); + + png_read_info(png_ptr, info_ptr); + + width = png_get_image_width(png_ptr, info_ptr); + height = png_get_image_height(png_ptr, info_ptr); + + if (width==80) { + *xsize=80; + xadd=1; + } + else { + fprintf(stderr,"Unsupported width %d\n",width); + return -1; + } + + if (png_type==PNG_WHOLETHING) { + *ysize=height; + ystart=0; + yadd=2; + } + else if (png_type==PNG_ODDLINES) { + *ysize=height/2; + ystart=1; + yadd=4; + } + else if (png_type==PNG_EVENLINES) { + *ysize=height/2; + ystart=0; + yadd=4; + } + else { + fprintf(stderr,"Unknown PNG type\n"); + return -1; + } + + color_type = png_get_color_type(png_ptr, info_ptr); + bit_depth = png_get_bit_depth(png_ptr, info_ptr); + + if (debug) { + printf("PNG: width=%d height=%d depth=%d\n",width,height,bit_depth); + if (color_type==PNG_COLOR_TYPE_RGB) printf("Type RGB\n"); + else if (color_type==PNG_COLOR_TYPE_RGB_ALPHA) printf("Type RGBA\n"); + else if (color_type==PNG_COLOR_TYPE_PALETTE) printf("Type palette\n"); + printf("Generating output size %d x %d\n",*xsize,*ysize); + } + +// number_of_passes = png_set_interlace_handling(png_ptr); + png_read_update_info(png_ptr, info_ptr); + + row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height); + for (y=0; y>4); + } + a2_color&=0xf; + + /* bottom color */ + color=row_pointers[y+(yadd/2)][x/2]; + if (x%2==0) { + color=(color>>4); + } + color&=0xf; + + a2_color|=(color<<4); + + if (debug) { + printf("%x ",a2_color); + } + + *out_ptr=a2_color; + out_ptr++; + + } + } + if (debug) printf("\n"); + } + } + else { + printf("Unknown color type\n"); + } + + /* Stripe test image */ +// for(x=0;x<40;x++) for(y=0;y<40;y++) image[(y*width)+x]=y%16; + +/* + Addr Row /80 %40 + $400 0 0 0 0 + $428 28 16 0 + $450 50 32 0 + $480 80 2 1 + $4A8 a8 18 1 + $4D0 d0 34 1 + $500 100 3 2 + 0,0 0,1 0,2....0,39 16,0 16,1 ....16,39 32,0..32,39, X X X X X X X X +*/ + + *image_ptr=image; + + return 0; +} + + diff --git a/demos/second/part18_3d/auto/loadpng.h b/demos/second/part18_3d/auto/loadpng.h new file mode 100644 index 00000000..5bf5d324 --- /dev/null +++ b/demos/second/part18_3d/auto/loadpng.h @@ -0,0 +1,11 @@ +#define PNG_WHOLETHING 0 +#define PNG_ODDLINES 1 +#define PNG_EVENLINES 2 +#define PNG_RAW 3 +#define PNG_NO_ADJUST 4 + +int loadpng(char *filename, unsigned char **image_ptr, int *xsize, int *ysize, + int png_type); +int loadpng80(char *filename, unsigned char **image_ptr, int *xsize, int *ysize, + int png_type); +