#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;
}
Vorgefundene Kodierung: UTF-8 | 0
|