Source file: /~heha/hs/ico2gif.zip/ico2gif.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "savegif.h"

typedef unsigned DWORD;
typedef unsigned short WORD;

typedef struct {
 WORD	reserved,
	type,
	count;
}ICOFHDR;

typedef struct {
 BYTE	width,
	height,
	colorcount,
	reserved;
 WORD	planes,
	bitcount;
 DWORD	sizeinbytes,
	fileoffset;
}ICOENTRY;

typedef struct {
 DWORD	size,
	width,
	height;
 WORD	planes,
	bitcount;
 DWORD	compression,
	imagesize,
	xpixelsperm,
	ypixelsperm,
	colorsused,
	colorsimportant;
}INFOHEADER;

typedef struct {
 BYTE rgbBlue,
      rgbGreen,
      rgbRed,
      rgbReserved;
}RGBQUAD;

int ansibcolor(RGBQUAD c) {
/* liefert Hintergrundfarbcode zum RGBQuad */
 int ret=8;
 if (c.rgbRed  >128) ret|=1;
 if (c.rgbGreen>128) ret|=2;
 if (c.rgbBlue >128) ret|=4;
 ret<<=3;
 if ((c.rgbRed  &127)>64) ret|=1;
 if ((c.rgbGreen&127)>64) ret|=2;
 if ((c.rgbBlue &127)>64) ret|=4;
 return ret;
}

int leftmostbit(unsigned n) {
/* liefert Bit-Nummer des am weitesten links stehenden Bits, -1 bei n=0 */
 int ret;
 for (ret=-1; n; n>>=1) ret++;	// Assembler-Befehl: bsf (386+)
 return ret;
}

int ansimode;

void printcolor(int c, char*s, ...) {
 static int lc=0;
 if (!ansimode) return;
 if (c!=lc) {
  if (c) {
   printf("\033[%d;%dm",((c>>3)&7)+40,(c&7)+30);
  }else{
   printf("\033[0m");
  }
  lc=c;
 }
 vprintf(s,(void*)(s+1));
}

int main(int argc, char **argv){
 int iconnumber=0;
 int width,height,bitcount;
 static BYTE loadspace[4096];
 ICOFHDR *icofhdr;
 ICOENTRY *icoentry;
 INFOHEADER *infoheader;
 RGBQUAD *colors=NULL;

 RGBCOLOR *rgbcolors;
 BYTE *xorbm, *andbm, *p, *pxor, *bmp,*h;
 int x,y,farbanz,xorbpl,xorsize,andbpl;
 FILE *fid;
 int histo[256], histo_trans, histo_xor;
 int bkcolor;
 BYTE tr[256];	//zur Farbreduktion
 int i,j,k;

 if (argc>=2 && argv[1][0]) {
  fid=fopen(argv[1],"rb");
 }else{
  fid=stdin;
 }
 if (argc>=3) {
  iconnumber=atoi(argv[2]);
 }

 if(!fid){
  fprintf(stderr,"Kann Datei nicht öffnen!\n");
  return -1;
 }

 ansimode=isatty(1);

 fread(loadspace,1,sizeof(loadspace),fid); // Alles in Speicher kopieren
 fclose(fid);

 icofhdr=(ICOFHDR*)loadspace;

 if (icofhdr->count<=iconnumber) {
  fprintf(stderr,"Enthält nur %d Bild(er)\n",icofhdr->count);
  return -8;
 }
 icoentry=(ICOENTRY*)(loadspace+sizeof(ICOFHDR)+sizeof(ICOENTRY)*iconnumber);
/*
 fprintf(stderr,"X: %u, Y: %u, Farbanz.: %u, Res: %u, Ebenen: %u,"
   " Bitanzahl %u, Größe: %lu, Offset: %lu\n\n",
   icoentry->width,icoentry->height,icoentry->colorcount,icoentry->reserved,
   icoentry->planes,icoentry->bitcount,icoentry->sizeinbytes,
   icoentry->fileoffset);
*/
 infoheader=(INFOHEADER*)(loadspace+icoentry->fileoffset);
 width =infoheader->width;
 height=(int)infoheader->height>>1;
 bitcount=infoheader->bitcount;
/*/
 printf("Größe: %lu, X: %d, Y: %d, Ebenen: %u, Bitanzahl %d\n\n",
   infoheader->size,width,height,infoheader->planes,bitcount);
/*/
 farbanz= 1<<bitcount;

 colors=(RGBQUAD*)(infoheader+1);

 xorbpl= ((bitcount*width+31)>>5)<<2;
 xorsize= xorbpl * height;
 //xorsize= ((infoheader.bitcount*infoheader.width-1)/32+1)*4

 andbpl= ((width+31)>>5)<<2;
/* andsize= andbpl * height;*/

 xorbm=(BYTE*)(colors+farbanz);

 andbm=(BYTE*)(xorbm+xorsize);
/*
 for(y=((int)infoheader.height>>1)-1;y>=0;y--){
  p=andbm+y*andbpl;
  pxor=xorbm+y*xorbpl;
  for(x=0;x<infoheader.width;x++){
   printf("%c", p[x>>3]&(1<<(7-x%8))?' ': 'A'+((pxor[x>>1]>>(x%2?0:4))&0x0f));
  }
  printf("\n");
 }
 printf("\n");
*/
 bmp=calloc(height,width);
 h=bmp;
 for (y=height-1; y>=0; y--) {
  pxor=xorbm+y*xorbpl;

  switch (bitcount) {
   case 1:
    for (x=0; x<width; x++)
      *h++=(pxor[x>>3]>>(7-x%8))&1;
    break;

   case 4:
    for(x=0;x<width;x++)
      *h++=(pxor[x>>1]>>(x%2?0:4))&0x0F;
    break;

   case 8:
    memmove(h,pxor,width);
    h+=width;
    break;

   default: return -9;
  }
 }

 memset(histo,0,sizeof(histo));
 histo_trans=histo_xor=0;
 h=bmp;
 for (y=height-1; y>=0; y--) {
  p=andbm+y*andbpl;
  for (x=0; x<width; x++) {
   if(p[x>>3]&(1<<(7-x%8))){
    histo_trans++;
    if (*h) histo_xor++;
    printcolor(0,y&1?"\\/":"/\\");
   }else{
    histo[*h]++;
    printcolor(ansibcolor(colors[*h]),"**");
   }
   h++;
  }
  printcolor(0,"\n");
 }
 if (histo_xor) fprintf(stderr,
   "Warnung: %d logisch mit Hintergrund verknüpfte Pixel\n",histo_xor);

 bkcolor=-1;
 for (x=y=0; x<farbanz; x++) {
  if (histo[x]) {
    //printf("%3d |%5d\n",x,histo[x]);
   y++;
  }else{
   if (histo_trans && bkcolor<0) bkcolor=x;
  }
 }

 for (k=i=0; i<farbanz; i++) {
  if (histo[i]) tr[i]=k++;
 }
 bkcolor=-1;
 if (histo_trans) {
  bkcolor=k;
  k++;	// noch eine transparente Farbe
 }
 //if (k>256) error("Kann nicht konvertieren!")
 j=leftmostbit(k-1)+1;

 h=bmp;
 for (y=height-1; y>=0; y--) {
  p=andbm+y*andbpl;
  for (x=0; x<width; x++) {
   if(p[x>>3]&(1<<(7-x%8))){
    *h=bkcolor;
   }else{
    *h=tr[*h];
   }
   h++;
  }
 }

 rgbcolors=calloc(farbanz,sizeof(RGBCOLOR));
 for (i=0; i<farbanz; i++) {
  if (histo[i]) {
   rgbcolors[tr[i]].r=colors[i].rgbRed;
   rgbcolors[tr[i]].g=colors[i].rgbGreen;
   rgbcolors[tr[i]].b=colors[i].rgbBlue;
  }
 }
 if (histo_trans) {
  rgbcolors[bkcolor].r=0xFF;
  rgbcolors[bkcolor].g=0xFF;
  rgbcolors[bkcolor].b=0xFF;
 }

 if (!ansimode) {
  savegif(stdout,bmp,width,height,rgbcolors,j,bkcolor);
 }

 if(bmp) free(bmp);
 free(rgbcolors);

 return 0;
}
Detected encoding: UTF-80