home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.sunet.sepub/pictures
/
2014.11.ftp.sunet.se-pictures.tar
/
ftp.sunet.se
/
pub
/
pictures
/
ACiD-artpacks
/
programs
/
unix
/
editors
/
gimp-plugins-unstable-0_99_23_tar.gz
/
gimp-plugins-unstable-0_99_23_tar
/
gimp-plugins-unstable-0.99.23
/
icon
/
iconread.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-02-24
|
17KB
|
668 lines
/* Time-stamp: <97/12/29 00:42:54 riffraff> */
/*
* $Id: iconread.c,v 1.1 1998/02/24 07:28:51 yosh Exp $
*
* $Author: yosh $
* $Date: 1998/02/24 07:28:51 $
* $Header: /debian/home/gnomecvs/gimp-plugins-unstable/icon/iconread.c,v 1.1 1998/02/24 07:28:51 yosh Exp $
*
* $Log: iconread.c,v $
* Revision 1.1 1998/02/24 07:28:51 yosh
* More plugins from the registry... time to autoconf stuff now...
*
* -Yosh
*
* Revision 1.4 1997/12/29 05:43:56 riffraff
* kludge for images that improperly set bColorCount to 0...
* now figures it out later using biBitCount (may not be correct
* in all instances, but a good guess)
*
* Revision 1.3 1997/12/29 05:13:08 riffraff
* was to strict reading in image....now liberal input,
* strict output...
*
* apparently, images with 256 colors only put 255 in
* bColorCount (a char can only hold 0-255, i dont know
* why they (whoever 'they' are) didnt say that a color
* count of 0 equalled 256, but whatever...a small workaround
* to make a colorcount of 255 actually read in 256, but
* toss the last entry read...
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#include <malloc.h>
#include <sys/types.h>
#include <libgimp/gimp.h>
#include <gtk/gtk.h>
#include "icon.h"
static char rcsid[] = "$Id: iconread.c,v 1.1 1998/02/24 07:28:51 yosh Exp $";
static FILE *fp;
static ICO_Header ICO_header;
static ICO_TIconDirEntry *ICO_direntry;
static ICO_IconImage *ICO_iconimage;
static int debug_level;
static char *filename;
static int bad_colors=0;
/* debug levels (and together):
0x01 = fatal errors
0x02 = warnings
0x04 = info
*/
static int ICO_read_iconheader(void);
static int ICO_read_direntries(void);
static int ICO_read_bitmapinfo(int);
static int ICO_read_rgbquad(int);
static int ICO_read_pixeldata(int);
static gint32 make_image(void);
#define PERR(str) if (debug_level & 0x04) printf(str);
gint32 ReadICON(char *fn) {
gint32 image_id;
debug_level=0x03; /* fatal errors and warnings */
filename=strdup(fn);
fp=fopen(filename,"rb"); /* why rb? */
if (fp==NULL) {
if (debug_level & 0x01)
printf("failed to open %s\n",filename);
free(filename);
return(-1);
}
if (debug_level & 0x04)
printf("ICO: Reading header\n");
if (ICO_read_iconheader()) {
free(filename);
fclose(fp);
return(-1);
}
if (debug_level & 0x04) {
printf("ICO: ICON Information:\n");
printf("ICO: Number of Images: %d\n",(int)(ICO_header.idCount));
}
if (ICO_read_direntries()) {
if (debug_level & 0x01)
printf("ICO: unable to read icon header\n");
free(filename);
fclose(fp);
return(-1);
}
if ((image_id=make_image())) {
g_free(ICO_direntry);
g_free(ICO_iconimage[0].icColors);
g_free(ICO_iconimage[0].icXOR);
g_free(ICO_iconimage[0].icAND);
g_free(ICO_iconimage);
free(filename);
return(image_id);
}
g_free(ICO_direntry);
g_free(ICO_iconimage[0].icColors);
g_free(ICO_iconimage[0].icXOR);
g_free(ICO_iconimage[0].icAND);
g_free(ICO_iconimage);
free(filename);
return(-1);
}
static int ICO_read_iconheader(void) {
int b;
unsigned short i;
/* read Reserved bit, abort if not 0 */
b=fread((void *)&i,1,sizeof(i),fp);
if (b!=sizeof(i))
return(-1);
ICO_header.idReserved=i;
if (ICO_header.idReserved!=0)
return(-1);
/* read Resource Type, 1 is for icons, abort if different */
b=fread((void *)&i,1,sizeof(i),fp);
if (b!=sizeof(i))
return(-1);
ICO_header.idType=i;
if (ICO_header.idType!=1)
return(-1);
/* read Number of images, abort if invalid value (0) */
b=fread((void *)&i,1,sizeof(i),fp);
if (b!=sizeof(i))
return(-1);
ICO_header.idCount=i; /* Number of images (>0) */
if (ICO_header.idCount==0) {
if (debug_level & 0x01)
printf("ICO: no images in file!\n");
return(-1);
}
if (ICO_header.idCount>1) {
if (debug_level & 0x02) {
printf("ICO: warning: this plugin only handles one icon image at this time\n");
printf("ICO: only reading one image\n");
}
}
return(0);
}
static int ICO_read_direntries(void) {
int b,j;
unsigned short i;
unsigned char c;
unsigned long l;
ICO_direntry=g_new(ICO_TIconDirEntry,ICO_header.idCount);
if (ICO_direntry==NULL) { /* shouldn't happen */
if (debug_level & 0x01)
printf("ICO: fatal error: out of memory!\n");
return(-1);
}
/* read in direntries one by one,
perform some primitive sanity checks */
for (j=0; j<ICO_header.idCount; j++) {
/* read Width, in pixels */
b=fread((void *)&c,1,sizeof(c),fp);
if (b!=sizeof(c)) {
PERR("ICO: unable to read bWidth\n");
return(-1);
}
ICO_direntry[j].bWidth=c;
/* read Height, in pixels */
b=fread((void *)&c,1,sizeof(c),fp);
if (b!=sizeof(c)) {
PERR("ICO: unable to read bHeight\n");
return(-1);
}
ICO_direntry[j].bHeight=c;
/* and validate data */
if (debug_level & 0x04)
printf("ICO: bWidth==%d bHeight==%d\n",
(int)ICO_direntry[j].bWidth,
(int)ICO_direntry[j].bHeight);
if (ICO_direntry[j].bWidth==0 || ICO_direntry[j].bHeight==0)
return(-1);
/* Number of colors in image */
b=fread((void *)&c,1,sizeof(c),fp);
if (b!=sizeof(c)) {
PERR("ICO: unable to read bColorCount\n");
return(-1);
}
ICO_direntry[j].bColorCount=c;
if (debug_level & 0x04)
printf("ICO: bColorCount==%d\n",(int)ICO_direntry[j].bColorCount);
if (ICO_direntry[j].bColorCount==0) {
if (debug_level & 0x02) {
printf("ICO: warning: number of colors not defined in image...\n");
printf("ICO: will try to figure it out myself\n");
}
bad_colors=1;
/* ICO_direntry[j].bColorCount=255; */
/* return(-1); */
}
if (ICO_direntry[j].bColorCount>256) {
if (debug_level & 0x01)
printf("ICO: this plugin does not support images with more than 256 colors\n");
return(-1);
}
/* Reserved (must be 0) */
b=fread((void *)&c,1,sizeof(c),fp);
if (b!=sizeof(c))
return(-1);
ICO_direntry[j].bReserved=c;
if (ICO_direntry[j].bReserved!=0)
return(-1);
/* Color Planes, not used, 0 */
b=fread((void *)&i,1,sizeof(i),fp);
if (b!=sizeof(i))
return(-1);
ICO_direntry[j].wPlanes=i;
/* Bits per pixel, not used, 0 */
b=fread((void *)&i,1,sizeof(i),fp);
if (b!=sizeof(i))
return(-1);
ICO_direntry[j].wBitCount=i;
/* size of image data, in bytes */
b=fread((void *)&l,1,sizeof(l),fp);
if (b!=sizeof(l))
return(-1);
ICO_direntry[j].dwBytesInRes=l;
if (ICO_direntry[j].dwBytesInRes==0)
return(-1);
/* offset from beginning image info */
b=fread((void *)&l,1,sizeof(l),fp);
if (b!=sizeof(l))
return(-1);
ICO_direntry[j].dwImageOffset=l;
if (ICO_direntry[j].dwImageOffset==0)
return(-1);
if (debug_level & 0x04) {
printf("\nImage #%d\n",j);
printf("Width: %d\n",(int)(ICO_direntry[j].bWidth));
printf("Height: %d\n",(int)(ICO_direntry[j].bHeight));
printf("Colors: %d\n",(int)(ICO_direntry[j].bColorCount));
printf("Bit Count (unused): %d\n",(int)(ICO_direntry[j].wBitCount));
printf("Total bytes: %ld\n",(long)(ICO_direntry[j].dwBytesInRes));
printf("Offset: %ld\n",(long)(ICO_direntry[j].dwImageOffset));
}
}
return(0);
}
static int ICO_read_bitmapinfo(int imagenum) {
int b;
unsigned long l;
unsigned short i;
#define ih ICO_iconimage[imagenum].icHeader
/* read bitmap info an perform some primitive sanity checks */
/* sizeof(TBitmapInfoHeader) */
b=fread((void *)&l,1,sizeof(l),fp);
if (b!=sizeof(l)) {
PERR("ICO: unable to read biSize\n");
return(-1);
}
ih.biSize=l;
/* width of bitmap */
b=fread((void *)&l,1,sizeof(l),fp);
if (b!=sizeof(l)) {
PERR("ICO: unable to read biWidth\n");
return(-1);
}
ih.biWidth=l;
/* height of bitmap, see notes (icon.h) */
b=fread((void *)&l,1,sizeof(l),fp);
if (b!=sizeof(l)) {
PERR("ICO: unable to read biHeight\n");
return(-1);
}
ih.biHeight=l;
if (debug_level & 0x04)
printf("ICO: biWidth==%d biHeight==%d\n",(int)ih.biWidth,(int)ih.biHeight);
if (ih.biWidth==0 || ih.biHeight==0)
return(-1);
/* planes, always 1 */
b=fread((void *)&i,1,sizeof(i),fp);
if (b!=sizeof(i)) {
PERR("ICO: unable to read biPlanes\n");
return(-1);
}
ih.biPlanes=i;
/* number of color bits (2,4,8) */
b=fread((void *)&i,1,sizeof(i),fp);
if (b!=sizeof(i)) {
PERR("ICO: unable to read biBitCount\n");
return(-1);
}
ih.biBitCount=i;
if (bad_colors)
if (ih.biBitCount==8)
ICO_direntry[imagenum].bColorCount=255;
else
ICO_direntry[imagenum].bColorCount=1<<ih.biBitCount;
/* compression used, 0 */
b=fread((void *)&l,1,sizeof(l),fp);
if (b!=sizeof(l)) {
PERR("ICO: unable to read biCompression\n");
return(-1);
}
ih.biCompression=l;
if (ih.biCompression!=0) {
if (debug_level & 0x01)
printf("ICO: invalid compression value of %d\n",(int)ih.biCompression);
return(-1);
}
/* size of the pixel data, see icon.h */
b=fread((void *)&l,1,sizeof(l),fp);
if (b!=sizeof(l)) {
return(-1);
PERR("ICO: unable to read biSizeImage\n");
}
ih.biSizeImage=l;
if (debug_level & 0x04)
printf("ICO: biSizeImage==%d\n",(int)ih.biSizeImage);
/* used to abort on this, but it's not really that important...
should be the len of the XORMASK + ANDMASK...
as the saying goes, be liberal in what you accept,
and strict in what you output (or something to that effect
*/
/* if (ih.biSizeImage==0)
return(-1); */
/* not used, 0 */
b=fread((void *)&l,1,sizeof(l),fp);
if (b!=sizeof(l)) {
PERR("ICO: unable to read biXPelsPerMeter\n");
return(-1);
}
ih.biXPelsPerMeter=l;
/* not used, 0 */
b=fread((void *)&l,1,sizeof(l),fp);
if (b!=sizeof(l)) {
PERR("ICO: unable to read biYPelsPerMeter\n");
return(-1);
}
ih.biYPelsPerMeter=l;
/* # of colors used, set to 0 */
b=fread((void *)&l,1,sizeof(l),fp);
if (b!=sizeof(l)) {
PERR("ICO: unable to read biClrUsed\n");
return(-1);
}
ih.biClrUsed=l;
/* important colors, set to 0 */
b=fread((void *)&l,1,sizeof(l),fp);
if (b!=sizeof(l)) {
PERR("ICO: unable to read biClrImportant\n");
return(-1);
}
ih.biClrImportant=l;
#undef ih
return(0);
}
static int ICO_read_rgbquad(int imagenum) {
int i,j;
unsigned char c;
int colors;
colors=ICO_direntry[imagenum].bColorCount;
ICO_iconimage[imagenum].icColors=g_new(ICO_TRGBQuad,colors);
if (ICO_iconimage[imagenum].icColors==NULL) { /* shouldn't happen */
if (debug_level & 0x01)
printf("ICO: fatal error: out of memory!\n");
return(-1);
}
#define cc ICO_iconimage[imagenum].icColors
if (debug_level & 0x04)
printf("\nRGB Data\n");
for (j=0; j<colors; j++) {
i=fread((void *)&c,sizeof(c),1,fp);
if (i<1)
return(-1);
cc[j].rgbBlue=c;
i=fread((void *)&c,sizeof(c),1,fp);
if (i<1)
return(-1);
cc[j].rgbGreen=c;
i=fread((void *)&c,sizeof(c),1,fp);
if (i<1)
return(-1);
cc[j].rgbRed=c;
i=fread((void *)&c,sizeof(c),1,fp);
if (i<1)
return(-1);
cc[j].rgbReserved=c;
if (debug_level & 0x04)
printf("#%d: Red: %d Green: %d Blue: %d\n",j,cc[j].rgbRed,
cc[j].rgbGreen,cc[j].rgbBlue);
}
#undef cc
if (colors==255) {
char buf[10];
fread((void *)&buf,4,1,fp);
}
return(0);
}
static int ICO_read_pixeldata(int imagenum) {
int xormasklen,andmasklen,xornum;
int b;
int i,j,k;
unsigned char *buf,*p;
xornum=(ICO_direntry[imagenum].bWidth*
ICO_direntry[imagenum].bHeight);
xormasklen=(xornum*ICO_iconimage[imagenum].icHeader.biBitCount)/8;
if (debug_level & 0x04)
printf("ICO: xormasklen==%d, xornum==%d\n",xormasklen,xornum);
andmasklen=xornum/8;
ICO_iconimage[imagenum].xormasklen=xormasklen;
ICO_iconimage[imagenum].andmasklen=andmasklen;
ICO_iconimage[imagenum].icXOR=g_new(unsigned char,xornum);
if (ICO_iconimage[imagenum].icXOR==NULL) { /* shouldnt happen */
if (debug_level & 0x01)
printf("ICO: fatal error: out of memory!\n");
return(-1);
}
ICO_iconimage[imagenum].icAND=g_new(unsigned char,xornum);
if (ICO_iconimage[imagenum].icAND==NULL) { /* shouldnt happen */
if (debug_level & 0x01)
printf("ICO: fatal error: out of memory!\n");
g_free(ICO_iconimage[imagenum].icXOR);
return(-1);
}
buf=g_new(unsigned char,xormasklen);
if (buf==NULL) { /* shouldnt happen */
if (debug_level & 0x01)
printf("ICO: fatal error: out of memory!\n");
g_free(ICO_iconimage[imagenum].icXOR);
g_free(ICO_iconimage[imagenum].icAND);
return(-1);
}
fread((void *)buf,1,xormasklen,fp);
b=fread((void *)ICO_iconimage[imagenum].icAND,1,andmasklen,fp);
if (b<andmasklen) {
g_free(ICO_iconimage[imagenum].icXOR);
g_free(ICO_iconimage[imagenum].icAND);
g_free(buf);
return(-1);
}
p=&ICO_iconimage[imagenum].icXOR[xornum-1];
/* probably not the most efficient code, but it's fast, and
since the icon's are small anyway, doesn't take too much
memory
*/
#define height ICO_direntry[imagenum].bHeight
#define width ICO_direntry[imagenum].bWidth
for (j=0; j<height; j++) {
p=&ICO_iconimage[imagenum].icXOR[(height-j-1)*width];
for (i=0; i<width*ICO_iconimage[imagenum].icHeader.biBitCount/8; i++) {
k=buf[j*height*ICO_iconimage[imagenum].icHeader.biBitCount/8+i];
switch(ICO_iconimage[imagenum].icHeader.biBitCount) {
case 1:
*p++=BitSet(k,0x80);
*p++=BitSet(k,0x40);
*p++=BitSet(k,0x20);
*p++=BitSet(k,0x10);
*p++=BitSet(k,0x08);
*p++=BitSet(k,0x04);
*p++=BitSet(k,0x02);
*p++=BitSet(k,0x01);
break;
case 4:
*p++=(k>>4) & 0x0f;
*p++=k & 0x0f;
break;
case 8:
*p++=k;
break;
default:
if (debug_level & 0x01)
printf("ICO: invalid bit count\n");
g_free(ICO_iconimage[imagenum].icXOR);
g_free(ICO_iconimage[imagenum].icAND);
g_free(buf);
return(-1);
}
}
}
g_free(buf);
return(0);
#undef height
#undef width
}
static gint32 make_image(void) {
ICO_iconimage=g_new(ICO_IconImage,ICO_header.idCount);
if (ICO_iconimage==NULL) { /* shouldnt happen */
if (debug_level & 0x01)
printf("ICO1: fatal error: out of memory!\n");
return(-1);
}
/* for future expansion although we only read 1 image */
/* for (i=0; i<ICO_header.idCount; i++) { */
fseek(fp,ICO_direntry[0].dwImageOffset,SEEK_SET);
if (ICO_read_bitmapinfo(0)) {
if (debug_level & 0x01)
printf("ICO: unable to read bitmap info\n");
return(-1);
}
if (ICO_read_rgbquad(0)) {
if (debug_level & 0x01)
printf("ICO: unable to read palette table\n");
return(-1);
}
if (ICO_read_pixeldata(0)) {
if (debug_level & 0x01)
printf("ICO: unable to read pixel data\n");
return(-1);
}
fclose(fp);
{
int width,height;
int i,j;
GPixelRgn pixel_rgn;
gint32 image;
gint32 layer;
GDrawable *drawable;
guchar gimp_cmap[768];
char *name;
int xornum;
name=g_malloc(strlen(filename)+15);
sprintf(name,"Loading %s:",filename);
gimp_progress_init(name);
g_free(name);
width=ICO_direntry[0].bWidth;
height=ICO_direntry[0].bHeight;
image=gimp_image_new(width,height,INDEXED);
layer=gimp_layer_new(image,"Background",width,height,INDEXED_IMAGE,100,NORMAL_MODE);
gimp_image_set_filename(image,filename);
if (debug_level & 0x04) {
printf("ICO: width==%d\n",width);
printf("ICO: height==%d\n",height);
printf("ICO: image==%ld\n",(long)image);
printf("ICO: layer==%ld\n",(long)layer);
}
gimp_image_add_layer(image,layer,0);
drawable=gimp_drawable_get(layer);
gimp_pixel_rgn_init(&pixel_rgn,drawable,0,0,drawable->width,drawable->height,TRUE,FALSE);
if (debug_level & 0x04)
printf("ICO: after gimp_pixel_rgn_init\n");
xornum=(ICO_direntry[0].bWidth*ICO_direntry[0].bHeight);
gimp_pixel_rgn_set_rect(&pixel_rgn,ICO_iconimage[0].icXOR,0,0,drawable->width,drawable->height);
for (i=j=0; i<ICO_direntry[0].bColorCount; i++) {
gimp_cmap[j++]=ICO_iconimage[0].icColors[i].rgbRed;
gimp_cmap[j++]=ICO_iconimage[0].icColors[i].rgbGreen;
gimp_cmap[j++]=ICO_iconimage[0].icColors[i].rgbBlue;
}
gimp_progress_update((double)100.0);
gimp_image_set_cmap(image,gimp_cmap,ICO_direntry[0].bColorCount);
gimp_drawable_flush(drawable);
gimp_drawable_detach(drawable);
return(image);
/* gimp_pixel_rgn_set_rect(&pixel_rgn,ICO_iconimage[0].icXOR,0,0,drawable->width,height); */
}
/* } */
}
#ifdef DEBUG
int main(int argc, char **argv) {
int i,j;
gint32 ico_err;
if (argc!=2) {
printf("no file!\n");
return(1);
}
ico_err=ReadICON(argv[1]);
return(ico_err);
}
#endif