mirror of
https://github.com/deater/dos33fsprogs.git
synced 2024-09-04 00:29:17 +00:00
879 lines
21 KiB
C
879 lines
21 KiB
C
/* box_convert */
|
|
|
|
/* Try to automate part of the annoyingly tedious rotoscoping process */
|
|
|
|
/* For input assumes a 40x48 (or 80x48, double wide) PNG file */
|
|
/* with the Apple II palette */
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdarg.h>
|
|
|
|
#include "loadpng.h"
|
|
|
|
#include "box_sizes.c"
|
|
|
|
static int debug=0;
|
|
|
|
static 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 */
|
|
};
|
|
|
|
/* There's probably an algorithmic way of generating this at run time */
|
|
/* but I was too lazy to implement it */
|
|
/* We only do 4. All 16 would be prohibitive. Maybe a happy medium? */
|
|
static int permutations[24][4]={
|
|
{1,2,3,4},
|
|
{2,1,3,4},
|
|
{3,1,2,4},
|
|
{1,3,2,4},
|
|
{2,3,1,4},
|
|
{3,2,1,4},
|
|
{3,2,4,1},
|
|
{2,3,4,1},
|
|
{4,3,2,1},
|
|
{3,4,2,1},
|
|
{2,4,3,1},
|
|
{4,2,3,1},
|
|
{4,1,3,2},
|
|
{1,4,3,2},
|
|
{3,4,1,2},
|
|
{4,3,1,2},
|
|
{1,3,4,2},
|
|
{3,1,4,2},
|
|
{2,1,4,3},
|
|
{1,2,4,3},
|
|
{4,2,1,3},
|
|
{2,4,1,3},
|
|
{1,4,2,3},
|
|
{4,1,2,3},
|
|
};
|
|
|
|
|
|
/* 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
|
|
#define ACTION_BOX_ADD 0x9
|
|
#define ACTION_BOX_ADD_LSAME 0xA
|
|
#define ACTION_BOX_ADD_RSAME 0xB
|
|
|
|
|
|
#if 0
|
|
static char action_names[9][16]={
|
|
"END","CLEAR","BOX","HLIN","VLIN","PLOT",
|
|
"HLIN_ADD","HLIN_ADD_LSAME","HLIN_ADD_RSAME"
|
|
};
|
|
#endif
|
|
|
|
#define MAX_PRIMITIVES 4096
|
|
static struct primitive_list_t {
|
|
int type;
|
|
int color;
|
|
int x1,y1,x2,y2;
|
|
} primitive_list[MAX_PRIMITIVES];
|
|
|
|
static int framebuffer[40][48];
|
|
static int framebuffer_saved[40][48];
|
|
static int background_color=0;
|
|
|
|
/* Not used anymore, included for historical reasons */
|
|
int create_using_plots(void) {
|
|
|
|
int current_primitive=0;
|
|
int row,col;
|
|
|
|
/* Initial Implementation, All Plots */
|
|
|
|
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++;
|
|
|
|
}
|
|
}
|
|
return current_primitive;
|
|
}
|
|
|
|
static unsigned char *image;
|
|
|
|
static struct color_lookup_t {
|
|
int color;
|
|
int count;
|
|
} color_lookup[16]={
|
|
{0,0},{1,0},{2,0},{3,0},{4,0},{5,0},{6,0},{7,0},{8,0},
|
|
{9,0},{10,0},{11,0},{12,0},{13,0},{14,0},{15,0}
|
|
};
|
|
|
|
static struct color_lookup_t color_backup[16];
|
|
|
|
/* Permute the top 4 colors in the color list histogram */
|
|
/* We do this to see if the resulting data is more compact */
|
|
/* We skip the black background, it might be interesting to include that */
|
|
/* as a normal color */
|
|
static void permute_colors(int which) {
|
|
|
|
int i;
|
|
|
|
for(i=0;i<4;i++) {
|
|
|
|
color_lookup[i+1].color=color_backup[permutations[which][i]].color;
|
|
color_lookup[i+1].count=color_backup[permutations[which][i]].count;
|
|
|
|
}
|
|
}
|
|
|
|
/* Not used anymore, included for historical reasons */
|
|
int create_using_hlins(void) {
|
|
|
|
int current_primitive=0;
|
|
int row,col,start_x;
|
|
int prev_color;
|
|
int len;
|
|
|
|
for(row=0;row<48;row++) {
|
|
prev_color=framebuffer[0][row]; len=0; start_x=0;
|
|
for(col=0;col<40;col++) {
|
|
if (framebuffer[col][row]!=prev_color) {
|
|
primitive_list[current_primitive].color=
|
|
prev_color;
|
|
primitive_list[current_primitive].x1=start_x;
|
|
primitive_list[current_primitive].x2=start_x+len;
|
|
primitive_list[current_primitive].y1=row;
|
|
primitive_list[current_primitive].type=ACTION_HLIN;
|
|
current_primitive++;
|
|
len=0;
|
|
prev_color=framebuffer[col][row];
|
|
start_x=col;
|
|
}
|
|
else {
|
|
len++;
|
|
}
|
|
|
|
}
|
|
}
|
|
return current_primitive;
|
|
}
|
|
|
|
/* Not used anymore, included for historical reasons */
|
|
int create_using_hlins_by_color(void) {
|
|
|
|
int current_primitive=0;
|
|
int row,col,start_x;
|
|
int current_color,prev_color;
|
|
int len,color;
|
|
|
|
for(color=0;color<16;color++) {
|
|
current_color=color_lookup[color].color;
|
|
|
|
if (current_color==background_color) continue;
|
|
|
|
for(row=0;row<48;row++) {
|
|
prev_color=framebuffer[0][row]; len=0; start_x=0;
|
|
for(col=0;col<40;col++) {
|
|
if (framebuffer[col][row]!=prev_color) {
|
|
if (prev_color==current_color) {
|
|
primitive_list[current_primitive].color=
|
|
prev_color;
|
|
primitive_list[current_primitive].x1=start_x;
|
|
primitive_list[current_primitive].x2=start_x+len;
|
|
primitive_list[current_primitive].y1=row;
|
|
primitive_list[current_primitive].type=ACTION_HLIN;
|
|
current_primitive++;
|
|
}
|
|
len=0;
|
|
prev_color=framebuffer[col][row];
|
|
start_x=col;
|
|
}
|
|
else {
|
|
len++;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
return current_primitive;
|
|
}
|
|
|
|
/* Find the smallest rectangle that includes all of a certain color */
|
|
/* We calculate this because if we don't track and this and include */
|
|
/* Don't Cares, then the algorithm will make overly-huge rectangles */
|
|
/* that are bigger than needed and make subsequent rectangles */
|
|
/* pessimistic */
|
|
|
|
int find_max_color_extent(int current_color,int *color_minx,int *color_miny,
|
|
int *color_maxx,int *color_maxy) {
|
|
|
|
|
|
int xx,yy;
|
|
|
|
*color_minx=39;
|
|
*color_miny=47;
|
|
*color_maxx=0;
|
|
*color_maxy=0;
|
|
|
|
/* Find maximum extent of color */
|
|
for(yy=0;yy<48;yy++) {
|
|
for(xx=0;xx<40;xx++) {
|
|
if (current_color==framebuffer[xx][yy]) {
|
|
if (xx<*color_minx) *color_minx=xx;
|
|
if (xx>*color_maxx) *color_maxx=xx;
|
|
if (yy<*color_miny) *color_miny=yy;
|
|
if (yy>*color_maxy) *color_maxy=yy;
|
|
}
|
|
}
|
|
}
|
|
if (debug) fprintf(stderr,"Color %d: range %d,%d to %d,%d\n",
|
|
current_color,*color_minx,*color_miny,
|
|
*color_maxx,*color_maxy);
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/* The main routine */
|
|
int create_using_boxes(void) {
|
|
|
|
int current_primitive=0;
|
|
int row,col,box;
|
|
int current_color;
|
|
int color;
|
|
int color_minx,color_maxx,color_miny,color_maxy;
|
|
|
|
for(color=0;color<16;color++) {
|
|
current_color=color_lookup[color].color;
|
|
|
|
if (current_color==background_color) continue;
|
|
|
|
|
|
/* calculate maximum color extent */
|
|
find_max_color_extent(current_color,
|
|
&color_minx,&color_miny,
|
|
&color_maxx,&color_maxy);
|
|
|
|
/* Try all possible box sizes. */
|
|
/* Can be exhaustive as there are only 40x48 possibilities */
|
|
/* Table is pre-sorted by size */
|
|
for(box=0;box<NUM_BOX_SIZES;box++) {
|
|
|
|
int xx,yy,box_found,color_found,color_found2;
|
|
|
|
/* check to see if this box size is best fit for color */
|
|
for(row=0;row<48-box_sizes[box].y;row++) {
|
|
for(col=0;col<40-box_sizes[box].x;col++) {
|
|
box_found=1;
|
|
color_found=0;
|
|
color_found2=0;
|
|
|
|
for(yy=0;yy<box_sizes[box].y;yy++) {
|
|
for(xx=0;xx<box_sizes[box].x;xx++) {
|
|
|
|
/* Only a fit if color is included */
|
|
/* i.e. don't have one that's all don't cares */
|
|
if (framebuffer[xx+col][yy+row]==current_color) {
|
|
color_found=1;
|
|
}
|
|
|
|
/* If there's a color that is wrong, early exit */
|
|
if ((framebuffer[xx+col][yy+row]==background_color)||
|
|
(framebuffer[xx+col][yy+row]==0xff))
|
|
{
|
|
box_found=0;
|
|
break;
|
|
}
|
|
} // xx
|
|
|
|
/* early exit */
|
|
if (!box_found) break;
|
|
} // yy
|
|
|
|
/* This isn't a good fit if rectangle is bigger */
|
|
/* Than the minimal rectangle containing the colors */
|
|
if (( (col)>=color_minx)&&((col+box_sizes[box].x-1)<=color_maxx)&&
|
|
((row)>=color_miny)&&((row+box_sizes[box].y-1)<=color_maxy)) {
|
|
color_found2=1;
|
|
}
|
|
|
|
|
|
if ((box_found)&&(color_found)&&(color_found2)) {
|
|
if (debug) fprintf(stderr,"Found box c=%d %d,%d to %d,%d\n",
|
|
current_color,col,row,col+box_sizes[box].x-1,
|
|
row+box_sizes[box].y-1);
|
|
primitive_list[current_primitive].color=
|
|
current_color;
|
|
primitive_list[current_primitive].x1=col;
|
|
primitive_list[current_primitive].x2=col+
|
|
box_sizes[box].x-1;
|
|
primitive_list[current_primitive].y1=row;
|
|
primitive_list[current_primitive].y2=row+
|
|
box_sizes[box].y-1;
|
|
primitive_list[current_primitive].type=ACTION_BOX;
|
|
current_primitive++;
|
|
if (current_primitive>=MAX_PRIMITIVES) {
|
|
fprintf(stderr,"Error! Too many primitives: %d\n",current_primitive);
|
|
exit(1);
|
|
}
|
|
for(yy=0;yy<box_sizes[box].y;yy++) {
|
|
for(xx=0;xx<box_sizes[box].x;xx++) {
|
|
if(framebuffer[xx+col][yy+row]==current_color) {
|
|
framebuffer[xx+col][yy+row]=0xff;
|
|
}
|
|
}
|
|
}
|
|
find_max_color_extent(current_color,
|
|
&color_minx,&color_miny,
|
|
&color_maxx,&color_maxy);
|
|
|
|
}
|
|
|
|
|
|
} // col
|
|
} // row
|
|
} // box
|
|
} // current_color
|
|
return current_primitive;
|
|
}
|
|
|
|
/* Comparison routines for the qsort()s */
|
|
|
|
static int compare_type(const void *p1, const void *p2) {
|
|
|
|
struct primitive_list_t *first,*second;
|
|
|
|
first=(struct primitive_list_t *)p1;
|
|
second=(struct primitive_list_t *)p2;
|
|
|
|
return (first->type > second->type);
|
|
|
|
}
|
|
|
|
static int compare_y1(const void *p1, const void *p2) {
|
|
|
|
struct primitive_list_t *first,*second;
|
|
|
|
first=(struct primitive_list_t *)p1;
|
|
second=(struct primitive_list_t *)p2;
|
|
|
|
return (first->y1 > second->y1);
|
|
|
|
}
|
|
|
|
static int compare_color(const void *p1, const void *p2) {
|
|
|
|
struct color_lookup_t *first,*second;
|
|
|
|
first=(struct color_lookup_t *)p1;
|
|
second=(struct color_lookup_t *)p2;
|
|
|
|
return (first->count < second->count);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int generate_frame(int print_results) {
|
|
|
|
int i;
|
|
|
|
int current_color=0;
|
|
|
|
int max_primitive=0;
|
|
int previous_primitive=0;
|
|
int total_size=0;
|
|
|
|
|
|
|
|
// max_primitive=create_using_hlins();
|
|
// max_primitive=create_using_hlins_by_color();
|
|
max_primitive=create_using_boxes();
|
|
|
|
|
|
/* Optimize boxes to PLOT/VLIN/HLIN*/
|
|
for(i=0;i<max_primitive;i++) {
|
|
if (primitive_list[i].type==ACTION_BOX) {
|
|
if ((primitive_list[i].x1==primitive_list[i].x2) &&
|
|
(primitive_list[i].y1==primitive_list[i].y2)) {
|
|
primitive_list[i].type=ACTION_PLOT;
|
|
} else
|
|
if (primitive_list[i].x1==primitive_list[i].x2) {
|
|
primitive_list[i].type=ACTION_VLIN;
|
|
} else
|
|
if (primitive_list[i].y1==primitive_list[i].y2) {
|
|
primitive_list[i].type=ACTION_HLIN;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Sort each color by BOX/HLIN/ETC */
|
|
int old_color,last_color_start=0;
|
|
|
|
old_color=primitive_list[0].color;
|
|
for(i=0;i<max_primitive;i++) {
|
|
if ((primitive_list[i].color!=old_color)||(i==max_primitive-1)) {
|
|
if (debug) fprintf(stderr,"Sorting color %d from %d to %d\n",
|
|
old_color,last_color_start,i);
|
|
qsort(&(primitive_list[last_color_start]),i-last_color_start,
|
|
sizeof(struct primitive_list_t),compare_type);
|
|
last_color_start=i;
|
|
}
|
|
old_color=primitive_list[i].color;
|
|
}
|
|
|
|
/* Sort HLIN by Y1 */
|
|
int first_hlin=0,last_hlin=0,j,hlin_found;
|
|
|
|
old_color=primitive_list[0].color;
|
|
for(i=0;i<max_primitive;i++) {
|
|
if ((primitive_list[i].color!=old_color)||(i==max_primitive-1)) {
|
|
hlin_found=0;
|
|
first_hlin=0; last_hlin=0;
|
|
// fprintf(stderr,"Searching for HLIN in color %d from %d to %d\n",
|
|
// old_color,last_color_start,i);
|
|
for(j=last_color_start;j<i;j++) {
|
|
if (primitive_list[j].type==ACTION_HLIN) {
|
|
if (!hlin_found) {
|
|
first_hlin=j;
|
|
hlin_found=1;
|
|
}
|
|
last_hlin=j;
|
|
}
|
|
}
|
|
if (hlin_found) {
|
|
if (debug) fprintf(stderr,"Sorting color %d HLIN Y1 from %d to %d\n",
|
|
old_color,first_hlin,last_hlin);
|
|
// qsort(base, num_members,size_members,compare func
|
|
qsort(&(primitive_list[first_hlin]),last_hlin-first_hlin,
|
|
sizeof(struct primitive_list_t),compare_y1);
|
|
}
|
|
else {
|
|
// fprintf(stderr,"No HLIN in color %d\n",old_color);
|
|
}
|
|
last_color_start=i;
|
|
}
|
|
old_color=primitive_list[i].color;
|
|
}
|
|
|
|
/* Sort BOX by Y1 */
|
|
int first_box=0,last_box=0,box_found;
|
|
|
|
old_color=primitive_list[0].color;
|
|
for(i=0;i<max_primitive;i++) {
|
|
if ((primitive_list[i].color!=old_color)||(i==max_primitive-1)) {
|
|
box_found=0;
|
|
first_box=0; last_box=0;
|
|
// fprintf(stderr,"Searching for BOX in color %d from %d to %d\n",
|
|
// old_color,last_color_start,i);
|
|
for(j=last_color_start;j<i;j++) {
|
|
if (primitive_list[j].type==ACTION_BOX) {
|
|
if (!box_found) {
|
|
first_box=j;
|
|
box_found=1;
|
|
}
|
|
last_box=j;
|
|
}
|
|
}
|
|
if (box_found) {
|
|
if (debug) fprintf(stderr,"Sorting color %d BOX Y1 from %d to %d\n",
|
|
old_color,first_box,last_box);
|
|
// qsort(base, num_members,size_members,compare func
|
|
qsort(&(primitive_list[first_box]),last_box-first_box,
|
|
sizeof(struct primitive_list_t),compare_y1);
|
|
}
|
|
else {
|
|
// fprintf(stderr,"No BOX in color %d\n",old_color);
|
|
}
|
|
last_color_start=i;
|
|
}
|
|
old_color=primitive_list[i].color;
|
|
}
|
|
|
|
|
|
/* Optimize HLIN */
|
|
int previous_entry=0,previous_y1=0,previous_x1=0,previous_x2=0,previous_y2=0;
|
|
for(i=0;i<max_primitive;i++) {
|
|
if (primitive_list[i].type==ACTION_HLIN) {
|
|
|
|
if ( ((previous_entry==ACTION_HLIN)||(previous_entry==ACTION_HLIN_ADD) ||(previous_entry==ACTION_HLIN_ADD_LSAME)) &&
|
|
(previous_y1==primitive_list[i].y1-1) &&
|
|
(previous_x1==primitive_list[i].x1)) {
|
|
primitive_list[i].type=ACTION_HLIN_ADD_LSAME;
|
|
}
|
|
else
|
|
if ( ((previous_entry==ACTION_HLIN)||(previous_entry==ACTION_HLIN_ADD) ||(previous_entry==ACTION_HLIN_ADD_RSAME)) &&
|
|
(previous_y1==primitive_list[i].y1-1) &&
|
|
(previous_x2==primitive_list[i].x2)) {
|
|
primitive_list[i].type=ACTION_HLIN_ADD_RSAME;
|
|
}
|
|
else
|
|
if ( ((previous_entry==ACTION_HLIN) || (previous_entry==ACTION_HLIN_ADD) || (previous_entry==ACTION_PLOT)) &&
|
|
(previous_y1==primitive_list[i].y1-1)) {
|
|
primitive_list[i].type=ACTION_HLIN_ADD;
|
|
}
|
|
}
|
|
previous_entry=primitive_list[i].type;
|
|
previous_y1=primitive_list[i].y1;
|
|
previous_x1=primitive_list[i].x1;
|
|
previous_x2=primitive_list[i].x2;
|
|
}
|
|
|
|
|
|
/* Optimize BOX */
|
|
previous_entry=0,previous_y1=0,previous_y2=0,previous_x1=0,previous_x2=0;
|
|
for(i=0;i<max_primitive;i++) {
|
|
if (primitive_list[i].type==ACTION_BOX) {
|
|
|
|
if ( ((previous_entry==ACTION_BOX)||(previous_entry==ACTION_BOX_ADD) ||(previous_entry==ACTION_BOX_ADD_LSAME)) &&
|
|
(previous_y2==primitive_list[i].y1-1) &&
|
|
(previous_x1==primitive_list[i].x1)) {
|
|
primitive_list[i].type=ACTION_BOX_ADD_LSAME;
|
|
}
|
|
else
|
|
if ( ((previous_entry==ACTION_BOX)||(previous_entry==ACTION_BOX_ADD) ||(previous_entry==ACTION_BOX_ADD_RSAME)) &&
|
|
(previous_y2==primitive_list[i].y1-1) &&
|
|
(previous_x2==primitive_list[i].x2)) {
|
|
primitive_list[i].type=ACTION_BOX_ADD_RSAME;
|
|
}
|
|
else
|
|
if ( ((previous_entry==ACTION_BOX) || (previous_entry==ACTION_BOX_ADD)) &&
|
|
(previous_y2==primitive_list[i].y1-1)) {
|
|
primitive_list[i].type=ACTION_BOX_ADD;
|
|
}
|
|
}
|
|
previous_entry=primitive_list[i].type;
|
|
previous_x1=primitive_list[i].x1;
|
|
previous_y1=primitive_list[i].y1;
|
|
previous_x2=primitive_list[i].x2;
|
|
previous_y2=primitive_list[i].y2;
|
|
}
|
|
|
|
|
|
|
|
/* Dump results */
|
|
for(i=0;i<max_primitive;i++) {
|
|
if (primitive_list[i].color==0) continue;
|
|
|
|
if (current_color!=primitive_list[i].color) {
|
|
if (print_results) printf("\t.byte SET_COLOR | %s\n",
|
|
color_names[primitive_list[i].color]);
|
|
current_color=primitive_list[i].color;
|
|
total_size+=1;
|
|
}
|
|
|
|
switch(primitive_list[i].type) {
|
|
case ACTION_END:
|
|
break;
|
|
case ACTION_CLEAR:
|
|
break;
|
|
case ACTION_BOX:
|
|
if (primitive_list[i].type==previous_primitive) {
|
|
if (print_results) printf("\t.byte %d,%d,%d,%d\n",
|
|
primitive_list[i].x1,
|
|
primitive_list[i].y1,
|
|
primitive_list[i].x2,
|
|
primitive_list[i].y2);
|
|
total_size+=4;
|
|
}
|
|
else {
|
|
if (print_results) printf("\t.byte BOX,%d,%d,%d,%d\n",
|
|
primitive_list[i].x1,
|
|
primitive_list[i].y1,
|
|
primitive_list[i].x2,
|
|
primitive_list[i].y2);
|
|
total_size+=5;
|
|
previous_primitive=ACTION_BOX;
|
|
}
|
|
break;
|
|
case ACTION_HLIN:
|
|
if (primitive_list[i].type==previous_primitive) {
|
|
if (print_results) printf("\t.byte %d,%d,%d\n",
|
|
primitive_list[i].x1,
|
|
primitive_list[i].x2,
|
|
primitive_list[i].y1);
|
|
total_size+=3;
|
|
}
|
|
else {
|
|
if (print_results) printf("\t.byte HLIN,%d,%d,%d\n",
|
|
primitive_list[i].x1,
|
|
primitive_list[i].x2,
|
|
primitive_list[i].y1);
|
|
total_size+=4;
|
|
previous_primitive=ACTION_HLIN;
|
|
|
|
}
|
|
break;
|
|
case ACTION_VLIN:
|
|
if (primitive_list[i].type==previous_primitive) {
|
|
if (print_results) printf("\t.byte %d,%d,%d\n",
|
|
primitive_list[i].y1,
|
|
primitive_list[i].y2,
|
|
primitive_list[i].x1);
|
|
total_size+=3;
|
|
}
|
|
else {
|
|
if (print_results) printf("\t.byte VLIN,%d,%d,%d\n",
|
|
primitive_list[i].y1,
|
|
primitive_list[i].y2,
|
|
primitive_list[i].x1);
|
|
total_size+=4;
|
|
previous_primitive=ACTION_VLIN;
|
|
|
|
}
|
|
break;
|
|
case ACTION_PLOT:
|
|
if (primitive_list[i].type==previous_primitive) {
|
|
if (print_results) printf("\t.byte %d,%d\n",
|
|
primitive_list[i].x1,
|
|
primitive_list[i].y1);
|
|
total_size+=2;
|
|
}
|
|
else {
|
|
if (print_results) printf("\t.byte PLOT,%d,%d\n",
|
|
primitive_list[i].x1,
|
|
primitive_list[i].y1);
|
|
total_size+=3;
|
|
previous_primitive=ACTION_PLOT;
|
|
|
|
}
|
|
break;
|
|
case ACTION_HLIN_ADD:
|
|
if (primitive_list[i].type==previous_primitive) {
|
|
if (print_results) printf("\t.byte %d,%d\t; %d\n",
|
|
primitive_list[i].x1,
|
|
primitive_list[i].x2,
|
|
primitive_list[i].y1);
|
|
total_size+=2;
|
|
}
|
|
else {
|
|
if (print_results) printf("\t.byte HLIN_ADD,%d,%d\t; %d\n",
|
|
primitive_list[i].x1,
|
|
primitive_list[i].x2,
|
|
primitive_list[i].y1);
|
|
total_size+=3;
|
|
previous_primitive=ACTION_HLIN_ADD;
|
|
|
|
}
|
|
break;
|
|
case ACTION_HLIN_ADD_LSAME:
|
|
if (primitive_list[i].type==previous_primitive) {
|
|
if (print_results) printf("\t.byte %d\n",
|
|
primitive_list[i].x2);
|
|
total_size+=1;
|
|
}
|
|
else {
|
|
if (print_results) printf("\t.byte HLIN_ADD_LSAME,%d ; %d, %d, %d\n",
|
|
primitive_list[i].x2,
|
|
primitive_list[i].x1,
|
|
primitive_list[i].x2,
|
|
primitive_list[i].y1);
|
|
total_size+=2;
|
|
previous_primitive=ACTION_HLIN_ADD_LSAME;
|
|
|
|
}
|
|
break;
|
|
case ACTION_HLIN_ADD_RSAME:
|
|
if (primitive_list[i].type==previous_primitive) {
|
|
if (print_results) printf("\t.byte %d\t; %d %d %d\n",
|
|
primitive_list[i].x1,
|
|
primitive_list[i].x1,
|
|
primitive_list[i].x2,
|
|
primitive_list[i].y1);
|
|
total_size+=1;
|
|
}
|
|
else {
|
|
if (print_results) printf("\t.byte HLIN_ADD_RSAME,%d\t; %d %d %d\n",
|
|
primitive_list[i].x1,
|
|
primitive_list[i].x1,
|
|
primitive_list[i].x2,
|
|
primitive_list[i].y1);
|
|
total_size+=2;
|
|
previous_primitive=ACTION_HLIN_ADD_RSAME;
|
|
|
|
}
|
|
break;
|
|
case ACTION_BOX_ADD:
|
|
if (primitive_list[i].type==previous_primitive) {
|
|
if (print_results) printf("\t.byte %d,%d,%d\t; %d\n",
|
|
primitive_list[i].x1,
|
|
primitive_list[i].x2,
|
|
primitive_list[i].y2,
|
|
primitive_list[i].y1);
|
|
total_size+=3;
|
|
}
|
|
else {
|
|
if (print_results) printf("\t.byte BOX_ADD,%d,%d,%d\t; %d\n",
|
|
primitive_list[i].x1,
|
|
primitive_list[i].x2,
|
|
primitive_list[i].y2,
|
|
primitive_list[i].y1);
|
|
total_size+=4;
|
|
previous_primitive=ACTION_BOX_ADD;
|
|
|
|
}
|
|
break;
|
|
case ACTION_BOX_ADD_LSAME:
|
|
if (primitive_list[i].type==previous_primitive) {
|
|
if (print_results) printf("\t.byte %d,%d\n",
|
|
primitive_list[i].x2,
|
|
primitive_list[i].y2);
|
|
total_size+=2;
|
|
}
|
|
else {
|
|
if (print_results) printf("\t.byte BOX_ADD_LSAME,%d,%d ; %d, %d\n",
|
|
primitive_list[i].x2,
|
|
primitive_list[i].y2,
|
|
primitive_list[i].x1,
|
|
primitive_list[i].y1);
|
|
total_size+=3;
|
|
previous_primitive=ACTION_BOX_ADD_LSAME;
|
|
|
|
}
|
|
break;
|
|
case ACTION_BOX_ADD_RSAME:
|
|
if (primitive_list[i].type==previous_primitive) {
|
|
if (print_results) printf("\t.byte %d,%d\t; %d %d\n",
|
|
primitive_list[i].x1,
|
|
primitive_list[i].y2,
|
|
primitive_list[i].x2,
|
|
primitive_list[i].y1);
|
|
total_size+=2;
|
|
}
|
|
else {
|
|
if (print_results) printf("\t.byte BOX_ADD_RSAME,%d,%d\n",
|
|
primitive_list[i].x1,
|
|
primitive_list[i].y2);
|
|
total_size+=3;
|
|
previous_primitive=ACTION_BOX_ADD_RSAME;
|
|
|
|
}
|
|
break;
|
|
|
|
default:
|
|
fprintf(stderr,"Error unknown type!\n");
|
|
exit(1);
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
}
|
|
if (print_results) printf("\t.byte END\n");
|
|
total_size++;
|
|
|
|
if (print_results) printf("; total size = %d\n",total_size);
|
|
|
|
return total_size;
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
|
|
int xsize,ysize;
|
|
int row,col,pixel,i;
|
|
int minimal_size,minimal_which=0;
|
|
|
|
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);
|
|
}
|
|
|
|
if (debug) 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);
|
|
}
|
|
|
|
for(row=0;row<24;row++) {
|
|
for(col=0;col<40;col++) {
|
|
pixel=(image[row*40+col]);
|
|
color_lookup[pixel&0xf].count++;
|
|
color_lookup[(pixel>>4)&0xf].count++;
|
|
framebuffer[col][row*2]=pixel&0xf;
|
|
framebuffer[col][(row*2)+1]=(pixel>>4)&0xf;
|
|
}
|
|
}
|
|
|
|
memcpy(framebuffer_saved,framebuffer,40*48*sizeof(int));
|
|
|
|
qsort(&(color_lookup[1]),15,
|
|
sizeof(struct color_lookup_t),compare_color);
|
|
|
|
// printf("; Histogram\n");
|
|
// for(i=0;i<16;i++) {
|
|
// printf("; $%02X %s: %d\n",color_lookup[i].color,color_names[color_lookup[i].color],color_lookup[i].count);
|
|
// }
|
|
|
|
|
|
memcpy(color_backup,color_lookup,16*sizeof(struct color_lookup_t));
|
|
|
|
int result;
|
|
minimal_size=2096;
|
|
for(i=0;i<24;i++) {
|
|
permute_colors(i);
|
|
result=generate_frame(0);
|
|
fprintf(stderr,"%d: %d bytes\n",i,result);
|
|
if (result<minimal_size) {
|
|
minimal_size=result;
|
|
minimal_which=i;
|
|
}
|
|
|
|
/* reset for next attempt */
|
|
memcpy(framebuffer,framebuffer_saved,40*48*sizeof(int));
|
|
}
|
|
fprintf(stderr,"minimum = %d, %d bytes\n",minimal_which,minimal_size);
|
|
permute_colors(minimal_which);
|
|
generate_frame(1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|