#include #include "stdio.h" #include "stdlib.h" #include "math.h" /* Thomson vitamotion devkit TGA to RAW image converter with palette editing b tga converter to various formats: */ #define SIZEX (8+320+8+64+8+320+8) #define SIZEY (8+200+8+16*4+8) /* * palette tables 8bit <> 4bit with gamma (thomson specific) */ static int my_gamma[16]={0,100,127,147,163,179,191,203,215,223,231,239,243,247,251,255}; static int seuils[17]={0,50,114,137,155,171,185,197,209,219,227,235,241,245,249,253,257}; char error_str[1024]; enum {MODE160x16,MODE320x4,MODE640x2,MODE_TO7} to8_mode; int pal_conv(int v) { int i; for (i=0;i<16;i++) { if (v16) { sprintf(error_str,"[ERROR] too many colors %d max 16\n",col_num); return -1; } to8_mode=MODE160x16; } if (header.width==320) { if (col_num>16) { sprintf(error_str,"[ERROR] too many colors %d max 4\n",col_num); return -1; } if (col_num>4) { to8_mode=MODE_TO7; } else { to8_mode=MODE320x4; } } if (header.width==640) { if (col_num>2) { sprintf(error_str,"[ERROR] too many colors %d max 2\n",col_num); return -1; } to8_mode=MODE640x2; } for (i=0;i<16;i++) palette_to[i]=0; for (i=0;i>16)<<8; palette_to[i]|=pal_conv((palette_24b[i]&0xFF00)>>8)<<4; palette_to[i]|=pal_conv((palette_24b[i]&0xFF)); palette_24b_limited[i]=pal_conv2((palette_24b[i]&0xFF0000)>>16)<<16; palette_24b_limited[i]|=pal_conv2((palette_24b[i]&0xFF00)>>8)<<8; palette_24b_limited[i]|=pal_conv2((palette_24b[i]&0xFF)); fprintf(stderr,"[INFO] palette[%d]=%03x\n",i,palette_to[i]); } } int output_to8(char *colname,char *ptname) { int n=0,i,j; /* ouput in 2 files raw data 8kb each (palette at end) */ FILE *COL; FILE *PT; COL=fopen(colname,"wb"); PT=fopen(ptname,"wb"); if ((COL==NULL) || (PT==NULL)) return -1; switch (to8_mode) { case MODE160x16: // on modifie les pixels 2 par 2 for (i=0;i>8,PT); fputc((palette_to[i]&0xFF),PT); fputc((palette_to[i]&0xFF00)>>8,COL); fputc((palette_to[i]&0xFF),COL); } break; case MODE320x4: { int ptval=0; int colval=0; for (i=0;i>1); colval=(colval<<1)|(j&0x01); if (i%8==7) { fputc(ptval&0xFF,PT); fputc(colval&0xFF,COL); } } for (i=0;i<4;i++) { fputc((palette_to[i]&0xFF00)>>8,PT); fputc((palette_to[i]&0xFF),PT); fputc((palette_to[i]&0xFF00)>>8,COL); fputc((palette_to[i]&0xFF),COL); } } break; case MODE_TO7: { int ptval=0; int colval=0; int fondrgb; int seg[8]; int forme_val=0; /* pour chaque segment de 8 on recherche les 2 couleurs et on reconstruit forme et color */ for (i=0;i16) break; fputc(ptval&0xFF,PT); fputc(colval&0xFF,COL); } for (i=0;i<16;i++) { fputc((palette_to[i]&0xFF00)>>8,PT); fputc((palette_to[i]&0xFF),PT); fputc((palette_to[i]&0xFF00)>>8,COL); fputc((palette_to[i]&0xFF),COL); } } break; } fclose(PT); fclose(COL); return 0; } int output_tga(char *fname) { FILE *fptr; int i; int j; int col; /* Write the result as a uncompressed TGA */ if ((fptr = fopen(fname,"w")) == NULL) { fprintf(stderr,"Failed to open outputfile\n"); return -1; } putc(0,fptr); putc(0,fptr); putc(2,fptr); /* uncompressed RGB */ putc(0,fptr); putc(0,fptr); putc(0,fptr); putc(0,fptr); putc(0,fptr); putc(0,fptr); putc(0,fptr); /* X origin */ putc(0,fptr); putc(0,fptr); /* y origin */ putc((header.width & 0x00FF),fptr); putc((header.width & 0xFF00) / 256,fptr); putc((header.height & 0x00FF),fptr); putc((header.height & 0xFF00) / 256,fptr); putc(32,fptr); /* 24 bit bitmap */ putc(0,fptr); for (i=0;i>16 ),fptr); putc(((palette_24b_limited[j]&0xFF00)>>8 ),fptr); putc(((palette_24b_limited[j]&0xFF) ),fptr); putc(pixels[i].a,fptr); } fclose(fptr); return 0; } void MergeBytes(PIXEL *pixel,unsigned char *p,int bytes) { if (bytes == 4) { pixel->r = p[2]; pixel->b = p[0]; pixel->g = p[1]; pixel->a = p[3]; } else if (bytes == 3) { pixel->r = p[2]; pixel->g = p[1]; pixel->b = p[0]; pixel->a = 0; } else if (bytes == 2) { pixel->r = (p[1] & 0x7c) << 1; pixel->g = ((p[1] & 0x03) << 6) | ((p[0] & 0xe0) >> 2); pixel->b = (p[0] & 0x1f) << 3; pixel->a = (p[1] & 0x80); } } /* * ============================================================================================ * allegro GUI stuff :) * ============================================================================================ */ static BITMAP *left_image,* right_image, *left_pal,*right_pal; void init() { int depth, res; FONT *myfont; allegro_init(); myfont = load_font("8x14t.pcx", NULL, NULL); install_keyboard(); install_sound(DIGI_AUTODETECT,MIDI_AUTODETECT,NULL); depth = desktop_color_depth(); if (depth == 0) depth = 16; set_color_depth(depth); #ifdef WIN32 res = set_gfx_mode(GFX_DIRECTX_WIN, SIZEX, SIZEY, 0, 0); #else res = set_gfx_mode(GFX_AUTODETECT_WINDOWED, SIZEX, SIZEY, 0, 0); #endif if (res != 0) { allegro_message(allegro_error); exit(-1); } if (myfont) { font=myfont; } install_timer(); install_mouse(); left_image=create_bitmap(320,200); right_image=create_bitmap(320,200); left_pal=create_bitmap(16,256); right_pal=create_bitmap(16,256); } int redraw_right(void) { int i,val,j; for (i=0;i>8, (palette_24b_limited[j]&0xFF0000)>>16 ) ); putpixel(right_image,(i%160)*2+1,i/160,makecol((palette_24b_limited[j]&0xFF), (palette_24b_limited[j]&0xFF00)>>8, (palette_24b_limited[j]&0xFF0000)>>16 ) ); break; case MODE320x4: case MODE_TO7: putpixel(right_image,i%320,i/320,makecol((palette_24b_limited[j]&0xFF), (palette_24b_limited[j]&0xFF00)>>8, (palette_24b_limited[j]&0xFF0000)>>16 ) ); break; case MODE640x2: { int j2,val2; int r,g,b; val2=(pixels[i+1].b<<16)|(pixels[i+1].g<<8)|(pixels[i+1].r); // on retrouve l'index dans la palette dans j for (j2=0;j2<16;j2++) { if (val2==palette_24b[j2]) break; } r=((palette_24b_limited[j]&0xFF)+(palette_24b_limited[j2]&0xFF))/2; g=((palette_24b_limited[j]&0xFF00)+(palette_24b_limited[j2]&0xFF00))/2; b=((palette_24b_limited[j]&0xFF0000)+(palette_24b_limited[j2]&0xFF0000))/2; putpixel(right_image,(i%640)/2,i/640,makecol(r,g>>8,b>>16 ) ); } i++; break; } } } /* * The COLOR dialog */ BITMAP *colors[16]; #define COLOR0 1 #define COLOR15 (1+15) #define SLIDER_R 18 #define SLIDER_G 19 #define SLIDER_B 20 #define EXIT_BUTTON 23 #define PREVIEW 21 char info[256]="index:0 val:000"; int slider_cb(void *dp3, int d2); DIALOG color_dialog[] = { /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) */ { d_shadow_box_proc, 0, 0, SIZEX, SIZEY, 0, 0, 0, D_DISABLED, 0, 0, (void*)NULL, NULL, NULL }, { d_icon_proc, 8, 8, 16, 16, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, { d_icon_proc, 8, 8+1*16, 16, 16, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, { d_icon_proc, 8, 8+2*16, 16, 16, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, { d_icon_proc, 8, 8+3*16, 16, 16, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, { d_icon_proc, 8, 8+4*16, 16, 16, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, { d_icon_proc, 8, 8+5*16, 16, 16, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, { d_icon_proc, 8, 8+6*16, 16, 16, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, { d_icon_proc, 8, 8+7*16, 16, 16, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, { d_icon_proc, 8, 8+8*16, 16, 16, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, { d_icon_proc, 8, 8+9*16, 16, 16, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, { d_icon_proc, 8, 8+10*16, 16, 16, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, { d_icon_proc, 8, 8+11*16, 16, 16, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, { d_icon_proc, 8, 8+12*16, 16, 16, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, { d_icon_proc, 8, 8+13*16, 16, 16, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, { d_icon_proc, 8, 8+14*16, 16, 16, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, { d_icon_proc, 8, 8+15*16, 16, 16, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, { d_icon_proc, 8+16+8, 8, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, // current col { d_slider_proc, 8+16+8, 8+16+8, 16*16, 16, 0, 0, 0, 0, 15, 0, NULL ,&slider_cb,NULL}, { d_slider_proc, 8+16+8, 8+16+8+16+8, 16*16, 16, 0, 0, 0, 0, 15, 0, NULL,&slider_cb,NULL }, { d_slider_proc, 8+16+8, 8+16+8+16+8+16+8, 16*16, 16, 0, 0, 0, 0, 15, 0, NULL,&slider_cb,NULL }, { d_icon_proc, 8+320+8+64+8, 8, 320, 200, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, { d_text_proc, 8+16+8+16+8, 8, 8*20, 8, 0, 0, 0, 0, 0, 0, info, NULL, NULL }, { d_button_proc, 8+16+8, 8+16+8+16+8+16+8+16+8, 8*16, 16, 0, 0, 0, D_EXIT, 0, 0, "RETURN", NULL, NULL }, { d_text_proc, 8+16+8+256+8, 8+16+8, 8*8, 16, 0, 0, 0, D_EXIT, 0, 0, "Red" ,NULL,NULL}, { d_text_proc, 8+16+8+256+8, 8+16+8+16+8, 8*8, 16, 0, 0, D_EXIT, 0, 0, 0, "Green",NULL,NULL }, { d_text_proc, 8+16+8+256+8, 8+16+8+16+8+16+8, 8*8, 16, 0, D_EXIT, 0, 0, 0, 0, "Blue",NULL,NULL }, { d_yield_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } }; static current_col=0; void info_rebuild(int current_col) { sprintf(info,"index:%02d val:%01X%01X%01X", current_col, pal_conv(palette_24b_limited[current_col]&0xFF), pal_conv((palette_24b_limited[current_col]&0xFF00)>>8), pal_conv((palette_24b_limited[current_col]&0xFF0000)>>16)); } int slider_cb(void *dp3, int d2) { int red,green,blue; int x,y; red=my_gamma[color_dialog[SLIDER_R].d2]; green=my_gamma[color_dialog[SLIDER_G].d2]; blue=my_gamma[color_dialog[SLIDER_B].d2]; palette_24b_limited[current_col]=red|(green<<8)|(blue<<16); int col=makecol((palette_24b_limited[current_col]&0xFF),(palette_24b_limited[current_col]&0xFF00)>>8,(palette_24b_limited[current_col]&0xFF0000)>>16); for (y=0;y<16;y++) for (x=0;x<16;x++) { putpixel(colors[current_col],x,y,col); } redraw_right(); info_rebuild(current_col); return D_REDRAW; } int color_dialog_do(void) { int ret; int i,x,y; static int first=1; int end=0; if (first) { for (i=0;i<16;i++) { colors[i]=create_bitmap(16,16); color_dialog[i+1].dp = colors[i]; } first=0; } do { // couleur courante color_dialog[16+1].dp = colors[current_col]; redraw_right(); color_dialog[PREVIEW].dp = right_image; for (i=0;i<16;i++) { int col=makecol((palette_24b_limited[i]&0xFF),(palette_24b_limited[i]&0xFF00)>>8,(palette_24b_limited[i]&0xFF0000)>>16); for (y=0;y<16;y++) for (x=0;x<16;x++) { putpixel(colors[i],x,y,col); } } color_dialog[SLIDER_R].d2=pal_conv(palette_24b_limited[current_col]&0xFF); color_dialog[SLIDER_G].d2=pal_conv((palette_24b_limited[current_col]&0xFF00)>>8); color_dialog[SLIDER_B].d2=pal_conv((palette_24b_limited[current_col]&0xFF0000)>>16); info_rebuild(current_col); /* set up colors */ gui_fg_color = makecol(0, 0, 0); gui_mg_color = makecol(128, 128, 128); gui_bg_color = makecol(200, 200, 200); set_dialog_color (color_dialog, gui_fg_color, gui_bg_color); clear_keybuf(); ret=popup_dialog(color_dialog,-1); if ((ret>=COLOR0) && (ret<=COLOR15)) { current_col=ret-COLOR0; } if (ret==EXIT_BUTTON) { end=1; } } while (!end); return 0; } /* * The Main dialog */ #define LEFT_ICON 1 #define RIGHT_ICON 2 #define LEFT_PAL 3 #define RIGHT_PAL 4 #define MAIN_LOAD 5 #define MAIN_EXIT 6 #define MAIN_SAVE_TGA 7 #define MAIN_SAVE_TO8 8 #define MAIN_EDIT_PALETTE 9 DIALOG main_dialog[] = { /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) */ { d_shadow_box_proc, 0, 0, SIZEX, SIZEY, 0, 0, 0, D_DISABLED, 0, 0, (void*)NULL, NULL, NULL }, { d_icon_proc, 8, 8, 320, 200, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, { d_icon_proc, 8+320+8+64+8, 8, 320, 200, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, { d_icon_proc, 8+320+8, 8, 16, 256, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, { d_icon_proc, 8+320+8+48, 8, 16, 256, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, { d_button_proc, 8, 8+200+8, 8*16, 16, 0, 0, 0, D_EXIT, 0, 0, "LOAD TGA", NULL, NULL }, { d_button_proc, 8, 8+200+8+16+8, 8*16, 16, 0, 0, 0, D_EXIT, 0, 0, "EXIT", NULL, NULL }, { d_button_proc, 8+320+8+64+8, 8+200+8, 8*16, 16, 0, 0, 0, D_EXIT, 0, 0, "SAVE TGA", NULL, NULL }, { d_button_proc, 8+320+8+64+8, 8+200+8+16+8, 8*16, 16, 0, 0, 0, D_EXIT, 0, 0, "SAVE TO8", NULL, NULL }, { d_button_proc, 8+320+8+64+8, 8+200+8+16+8+16+8, 8*16, 16, 0, 0, 0, D_EXIT, 0, 0, "EDIT PALETTE", NULL, NULL }, { d_yield_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } }; char memo_path[6*1024]="\0"; int main_dialog_do(void) { int ret; int i,x,y; /* set up colors */ gui_fg_color = makecol(0, 0, 0); gui_mg_color = makecol(128, 128, 128); gui_bg_color = makecol(200, 200, 200); set_dialog_color (main_dialog, gui_fg_color, gui_bg_color); main_dialog[LEFT_ICON].dp = left_image; main_dialog[RIGHT_ICON].dp = right_image; main_dialog[LEFT_PAL].dp = left_pal; main_dialog[RIGHT_PAL].dp = right_pal; clear_keybuf(); ret=do_dialog(main_dialog,-1); /* action on left click */ if ((ret==LEFT_ICON) || (ret==MAIN_LOAD)) { char path[6*1024]; strcpy(path,memo_path); file_select_ex("Load a TGA 320x200 image", path, NULL, 1024, 512, 256); if (my_load_tga(path)!=-1) { i=0; for (y=0;y<200;y++) for (x=0;x<320;x++) { switch (to8_mode) { case MODE160x16: putpixel(left_image,x,y,makecol(pixels[i].r,pixels[i].g,pixels[i].b)); putpixel(left_image,x+1,y,makecol(pixels[i].r,pixels[i].g,pixels[i].b)); x++; // note this ;) ok, not very nice... i++; break; case MODE_TO7: case MODE320x4: putpixel(left_image,x,y,makecol(pixels[i].r,pixels[i].g,pixels[i].b)); i++; break; case MODE640x2: putpixel(left_image,x,y,makecol((pixels[i].r+pixels[i+1].r)/2, (pixels[i].g+pixels[i+1].g)/2, (pixels[i].b+pixels[i+1].b)/2)); i+=2; break; } } for (i=0;i<16;i++) for (y=0;y<16;y++) for (x=0;x<16;x++) { putpixel(left_pal,x,y+16*i,makecol((palette_24b[i]&0xFF),(palette_24b[i]&0xFF00)>>8,(palette_24b[i]&0xFF0000)>>16 ) ); putpixel(right_pal,x,y+16*i,makecol((palette_24b_limited[i]&0xFF),(palette_24b_limited[i]&0xFF00)>>8,(palette_24b_limited[i]&0xFF0000)>>16 ) ); } redraw_right(); } else { alert(error_str,"" , NULL, "OK", NULL, 0, 0); } strcpy(memo_path,dirname(path)); /* after use of path ;) */ strcat(memo_path,"/"); } // of if ret==LEFT_ICON if ((ret==RIGHT_PAL) || (ret==MAIN_EDIT_PALETTE)) { color_dialog_do(); redraw_right(); for (i=0;i<16;i++) for (y=0;y<16;y++) for (x=0;x<16;x++) { putpixel(left_pal,x,y+16*i,makecol((palette_24b[i]&0xFF),(palette_24b[i]&0xFF00)>>8,(palette_24b[i]&0xFF0000)>>16 ) ); putpixel(right_pal,x,y+16*i,makecol((palette_24b_limited[i]&0xFF),(palette_24b_limited[i]&0xFF00)>>8,(palette_24b_limited[i]&0xFF0000)>>16 ) ); } for (i=0;i<16;i++) { palette_to[i]=pal_conv((palette_24b_limited[i]&0xFF0000)>>16)<<8; palette_to[i]|=pal_conv((palette_24b_limited[i]&0xFF00)>>8)<<4; palette_to[i]|=pal_conv((palette_24b_limited[i]&0xFF)); } } if ((ret==MAIN_EXIT) && (alert("Quit?","" , NULL, "OK", "NO", 0, 0)==1)) { return -1; } if (ret==MAIN_SAVE_TGA) { char path[6*1024]; strcpy(path,memo_path); file_select_ex("Save a TGA 320x200 image", path, NULL, 1024, 512, 256); if ((access(path,F_OK)!=-1) && (alert("Replace file?","",NULL,"Yes","No",0,0)==2) ) return 0; if (output_tga(path)!=0) alert("Save TGA failed !","",NULL,"Ok",NULL,0,0); strcpy(memo_path,dirname(path)); /* after use of path ;) */ strcat(memo_path,"/"); } if (ret==MAIN_SAVE_TO8) { char path[6*1024]; strcpy(path,memo_path); char path2[6*1024]; file_select_ex("Save first COLOR file", path, NULL, 1024, 512, 256); if ((access(path,F_OK)!=-1) && (alert("Replace file?","",NULL,"Yes","No",0,0)==2) ) return 0; strcpy(path2,memo_path); file_select_ex("Save second POINT file", path2, NULL, 1024, 512, 256); if ((access(path2,F_OK)!=-1) && (alert("Replace file?","",NULL,"Yes","No",0,0)==2) ) return 0; if (output_to8(path,path2)!=0) alert("Save TO8 failed !","",NULL,"Ok",NULL,0,0); strcpy(memo_path,dirname(path)); /* after use of path ;) */ strcat(memo_path,"/"); } return 0; } main(int argc,char **argv) { init(); while (main_dialog_do()!=-1) { } } END_OF_MAIN()