1 /****************************************************************************
2 * Copyright (C) 1996-98 by Leo Khramov
3 * email: leo@xnc.dubna.su
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 ****************************************************************************/
19 #define ABS(x) ((x) > 0 ? (x) : (-(x)))
20 extern "C" void (*im_coding
)(unsigned int,unsigned int,unsigned int,char**);
21 extern "C" void im_truetruecoding(unsigned int ir
,unsigned int ig
,unsigned int ib
,char **imdata
);
22 extern "C" void im_truenocoding(unsigned int ir
,unsigned int ig
,unsigned int ib
,char **imdata
);
27 int depth
,bdep
,translation
,b_pad
=1;
32 uint rmask
,gmask
,bmask
,rsh
,bsh
,gsh
;
33 uint red_rsh
,green_rsh
,blue_rsh
,red_lsh
,green_lsh
,blue_lsh
;
40 void (*im_coding256
)(char **,int);
41 void im_256truecoding(char**,int);
42 void im_256nocoding(char**,int);
43 void im_256256coding(char**,int);
45 unsigned long *global_pal
=NULL
;
48 unsigned long XPixelTable
[256];
49 unsigned long Xfreepix
[256];
54 int im_getpixels(unsigned long* pt
)
57 if(vclass
==PseudoColor
)
58 for(int i
=0;i
<ptnum
;i
++)
73 Colormap
im_choose_cmp()
76 if(cmptype
==CMP_OWN
&& vclass
==PseudoColor
)
78 cmp
=XCreateColormap(disp
,DefaultRootWindow(disp
),vis
,AllocNone
);
85 void im_freecmp(Colormap XColorMap
,unsigned long *pt
,int iptnum
)
88 if(XColorMap
==0) XColorMap
=defc
;
89 if(vclass
==PseudoColor
&& XColorMap
==defc
)
90 XFreeColors(disp
, XColorMap
, pt
, iptnum
, 0L);
91 if(XColorMap
!=defc
) XFreeColormap(disp
,XColorMap
);
95 Colormap
im_get_colormap()
97 if(cmptype
==CMP_OWN
&& vclass
==PseudoColor
) return lcmp
;
115 void im_separate_colors()
118 for(int i
=0;i
<256;i
++)
122 gpart
[i
]=im
.pal
[i3
+1];
123 bpart
[i
]=im
.pal
[i3
+2];
127 void im_union_colors()
130 for(int i
=0;i
<256;i
++)
134 im
.pal
[i3
+1]=gpart
[i
];
135 im
.pal
[i3
+2]=bpart
[i
];
139 void im_add_cmp_entry(unsigned long ent
)
141 Xfreepix
[ptnum
++]=ent
;
143 global_pal
[ptnum
-1]=ent
;
146 void im_alloc_closest_cmp(Colormap XColorMap
,int ColorMapSize
=256)
148 int i
, j
, Index
= 0, Count
= 0, XNumOfColors
;
149 unsigned long D
, Distance
, Red
, Green
, Blue
;
151 XColor
*XOldColorTable
;
153 for (i
= 0; i
< 256; i
++) {
154 if (i
< ColorMapSize
) { /* Prepere color entry in X format. */
155 XColorTable
[i
].red
= im
.pal
[i
*3] << 8;
156 XColorTable
[i
].green
= im
.pal
[i
*3+1] << 8;
157 XColorTable
[i
].blue
= im
.pal
[i
*3+2] << 8;
158 XColorTable
[i
].flags
= DoRed
| DoGreen
| DoBlue
;
159 XPixelTable
[i
] =(unsigned long)-1; /* Not allocated yet. */
162 XPixelTable
[i
] = 0; /* Put reasonable color for out of range. */
165 for (i
= 0; i
< ColorMapSize
; i
++) /* Allocate the colors from X: */
166 if (XAllocColor(disp
, XColorMap
, &XColorTable
[i
]))
168 XPixelTable
[i
] = XColorTable
[i
].pixel
;
169 im_add_cmp_entry(XPixelTable
[i
]);
173 if(ptnum
<ColorMapSize
/2 && cmptype
==CMP_AUTO
&& Failed
==True
)
176 XColorMap
=im_choose_cmp();
177 im_alloc_closest_cmp(XColorMap
,ColorMapSize
);
181 XNumOfColors
= DisplayCells(disp
,DefaultScreen(disp
));
182 XOldColorTable
= (XColor
*) malloc(sizeof(XColor
) * XNumOfColors
);
183 for (i
= 0; i
< XNumOfColors
; i
++) XOldColorTable
[i
].pixel
= i
;
184 XQueryColors(disp
, XColorMap
, XOldColorTable
, XNumOfColors
);
186 for (i
= 0; i
< ColorMapSize
; i
++) {
187 /* Allocate closest colors from X: */
188 if (XPixelTable
[i
] == -1) { /* Failed to allocate this one. */
189 Distance
= 0xffffffff;
191 Red
= XColorTable
[i
].red
;
192 Green
= XColorTable
[i
].green
;
193 Blue
= XColorTable
[i
].blue
;
195 for (j
= 0; j
< XNumOfColors
; j
++) {
196 /* Find the closest color in 3D RGB space using L1 norm. */
197 if ((D
= ABS(Red
- XOldColorTable
[j
].red
) +
198 ABS(Green
- XOldColorTable
[j
].green
) +
199 ABS(Blue
- XOldColorTable
[j
].blue
)) < Distance
) {
204 XPixelTable
[i
] = Index
;
209 free(XOldColorTable
);
211 for(i
=0;i
<ColorMapSize
;i
++)
212 trans
[i
]=(XPixelTable
[i
]& 0xff);
216 void im_alloccmp(Colormap XColorMap
,int ColorMapSize
=256)
220 im_alloc_closest_cmp(XColorMap
,ColorMapSize
);
222 for (i
= 0; i
< 256; i
++)
223 XPixelTable
[i
] = 0; /* Put reasonable color for out of range. */
225 for (Strip
= 0, Msk
= 0xff; Strip
< 8; Strip
++, Msk
<<= 1) {
226 for (i
= 0; i
< ColorMapSize
; i
++) {
227 /* Prepere color entry in X format. */
228 XColorTable
[i
].red
= (im
.pal
[i
*3] & Msk
) << 8;
229 XColorTable
[i
].green
= (im
.pal
[i
*3+1] & Msk
) << 8;
230 XColorTable
[i
].blue
= (im
.pal
[i
*3+2] & Msk
) << 8;
231 XColorTable
[i
].flags
= DoRed
| DoGreen
| DoBlue
;
232 if (XAllocColor(disp
,XColorMap
, &XColorTable
[i
]))
234 XPixelTable
[i
] = XColorTable
[i
].pixel
;
235 im_add_cmp_entry(XPixelTable
[i
]);
240 if (i
< ColorMapSize
)
243 XFreeColors(disp
, XColorMap
, XPixelTable
, i
, 0L);
250 fprintf(stderr
,"Can not display the image - not enough colors available.\n");
252 for(i
=0;i
<ColorMapSize
;i
++)
253 trans
[i
]=(XPixelTable
[i
]& 0xff);
258 XImage
*im_process_pseudo_256(int cmpsize
=256)
262 int imlen
=im
.w
*im
.h
,i
;
267 trans
=new char[256*bdep
];
268 im_alloccmp(cmp
,cmpsize
);
270 im
.pic
[i
]=trans
[im
.pic
[i
]];
272 imdata
=(char*)im
.pic
;
274 if((xim
=XCreateImage(disp
,vis
,depth
,ZPixmap
,0,imdata
,im
.w
,im
.h
,8,0))==NULL
)
277 fprintf(stderr
,"Image Engine Error: XCreateImage\n");
280 xim
->byte_order
=MSBFirst
;
287 char *tmp
=new char[strlen(im
.fullInfo
)+1];
288 strcpy(tmp
,im
.fullInfo
);
292 void do_masks(uint mask
,uint
&lsh
,uint
&rsh
)
295 while((mask
& 1)==0) {lsh
++;mask
>>=1;};
296 while(mask
& 1) {rsh
++;mask
>>=1;};
300 void im_reset_coding()
302 im_coding256
=im_256nocoding
;
308 im_coding256
=im_256truecoding
;
312 long cmap_distance
[256];
314 XColor
*XCmapColorTable
=NULL
;
317 long im_calc_weight(unsigned short red
,
318 unsigned short green
,
321 double r
=(double)red
;
322 double g
=(double)green
;
323 double b
=(double)blue
;
324 return (long)sqrt(r
*r
+g
*g
+b
*b
);
327 void im_init_cmap(Colormap XColorMap
)
331 int screen
=DefaultScreen(disp
);
333 depth
=DefaultDepth(disp
,screen
);
334 vis
=DefaultVisual(disp
,screen
);
335 defc
=DefaultColormap(disp
,screen
);
337 XNumOfColors
= DisplayCells(disp
,DefaultScreen(disp
));
338 if(XCmapColorTable
== NULL
)
339 XCmapColorTable
= (XColor
*) malloc(sizeof(XColor
) * XNumOfColors
);
340 for (i
= 0; i
< XNumOfColors
; i
++)
341 XCmapColorTable
[i
].pixel
= i
;
342 XQueryColors(disp
, XColorMap
, XCmapColorTable
, XNumOfColors
);
344 for(i
=0;i
< XNumOfColors
;i
++)
346 cmap_distance
[i
]=im_calc_weight(XCmapColorTable
[i
].red
,
347 XCmapColorTable
[i
].green
,
348 XCmapColorTable
[i
].blue
);
350 XCmapNumColors
=XNumOfColors
;
354 int im_find_closest_color(XColor
* orig
, XColor
* tocol
)
356 unsigned long weight
,distance
, Red
, Green
, Blue
, D
;
358 if(vclass
==TrueColor
)
367 for(i
=0;i
<XCmapNumColors
;i
++)
369 if ((D
= ABS(Red
- XCmapColorTable
[i
].red
) +
370 ABS(Green
- XCmapColorTable
[i
].green
) +
371 ABS(Blue
- XCmapColorTable
[i
].blue
)) < distance
)
377 *tocol
=XCmapColorTable
[idx
];
378 tocol
->flags
= DoGreen
| DoRed
| DoBlue
;
382 int im_find_closest_color2(XColor
* orig
, XColor
* tocol
)
384 long weight
,distance
;
386 if(vclass
==TrueColor
)
391 weight
=im_calc_weight(orig
->red
, orig
->green
, orig
->blue
);
392 distance
=ABS(cmap_distance
[idx
]-weight
);
393 for(i
=1;i
<XCmapNumColors
;i
++)
394 if(distance
>ABS(cmap_distance
[i
]-weight
))
397 distance
=ABS(cmap_distance
[i
]-weight
);
399 *tocol
=XCmapColorTable
[idx
];
400 tocol
->flags
= DoGreen
| DoRed
| DoBlue
;
404 Status
im_AllocColor(Display
* d
, Colormap cmap
, XColor
*cl
)
408 if((st
=XAllocColor(disp
, cmap
, cl
))!=0)
410 if(cmap
!=XCmapCmap
|| XCmapColorTable
==NULL
)
412 im_find_closest_color2(cl
, &cl2
);
414 return XAllocColor(disp
, cmap
, cl
);
417 Status (*pim_AllocColor
)(Display
*, Colormap
, XColor
*)=im_AllocColor
;
419 void init_imagengine()
422 XPixmapFormatValues
*pixformat
;
424 int screen
=DefaultScreen(disp
);
426 depth
=DefaultDepth(disp
,screen
);
427 vis
=DefaultVisual(disp
,screen
);
428 defc
=DefaultColormap(disp
,screen
);
430 fprintf(stderr
, "**********Image Engine**********\n");
431 fprintf(stderr
,"* *\n");
436 pixformat
= XListPixmapFormats(disp
, &count
);
437 for (i
=0; i
<count
; i
++) {
438 if (pixformat
[i
].depth
== depth
) {
439 bdep
= (pixformat
[i
].bits_per_pixel
+7) / 8;
440 b_pad
= pixformat
[i
].scanline_pad
/ 8;
446 if((xim
=XCreateImage(disp
,vis
,depth
,ZPixmap
,0,NULL
,10,10,b_pad
*8,0))==NULL
)
448 fprintf(stderr
,"Image Engine Error: XCreateImage\n");
452 gmask
=xim
->green_mask
;
453 bmask
=xim
->blue_mask
;
455 x11_create_lut(rmask
,gmask
,bmask
);
457 do_masks(rmask
,red_lsh
,red_rsh
);
458 do_masks(gmask
,green_lsh
,green_rsh
);
459 do_masks(bmask
,blue_lsh
,blue_rsh
);
460 im_coding
=im_truetruecoding
;
461 im_coding256
=im_256truecoding
;
462 fprintf(stderr
,"*Visual: TrueColor *\n");
463 fprintf(stderr
,"*Depth: %-3d (%d bytes/pixel) *\n",depth
,bdep
);
464 fprintf(stderr
,"*RGB: %d:%d:%d *\n",8-red_rsh
,8-green_rsh
,8-blue_rsh
);
465 fprintf(stderr
,"*Colors: %-9d *\n",1<<depth
);
466 fprintf(stderr
,"*Images: GIF,JPEG,PCX *\n");
474 XColorTable
=new XColor
[256];
476 im_coding256
=im_256256coding
;
477 im_coding
=im_truenocoding
;
478 fprintf(stderr
,"*Visual: PseudoColor *\n");
479 fprintf(stderr
,"*Depth: %-3d (%d bytes) *\n",depth
,bdep
);
480 fprintf(stderr
,"*Colors: %-9d *\n",1<<depth
);
481 fprintf(stderr
,"*Images: GIF,JPEG,PCX *\n");
484 fprintf(stderr
,"*Visual: PseudoColor *\n");
485 fprintf(stderr
,"*Not supported *\n");
490 fprintf(stderr
,"*Visual: DirectColor *\n");
491 fprintf(stderr
,"*Not supported *\n");
494 fprintf(stderr
,"* *\n");
495 fprintf(stderr
,"******** (c) Leo 96-98 *********\n");
498 //return -1 if not detected
499 int autodetect(char *f
)
501 int fp
=open(f
,O_RDONLY
);
502 if(fp
==-1) return -1;
504 if(read(fp
,buf
,30)<30)
510 if(buf
[0]=='G' && buf
[1]=='I' && buf
[2]=='F') return F_GIF
;
512 else if(buf
[0]==buf
[1] && (buf
[0]=='I' || buf
[0]=='M')) return F_TIFF
;
515 else if(buf
[0]==0xa && buf
[1]<=5 && buf
[2]==1) return F_PCX
;
518 else if(buf
[0]=='B' && buf
[1]=='M') return F_BMP
;
521 else if (strncmp((char*)buf
, "/* XPM */", (size_t) 9)==0) return F_XPM
;
524 else if (strncmp((char*)buf
,"#define", (size_t) 7)==0) return F_XBM
;
527 else if (buf
[0]==0 && buf
[1]==0 &&
528 buf
[2]==2 && buf
[3]==0 &&
529 buf
[4]==0 && buf
[5]==0 &&
530 buf
[6]==0 && buf
[7]==0) return F_TARGA
;
533 else if (strncmp((char*)buf
+1,"PNG", (size_t) 3)==0) return F_PNG
;
536 else if(buf
[0]==0xff && buf
[1]==0xd8 && buf
[2]==0xff) return F_JPEG
;
543 if(strncmp(f
,".pcd",4)==0 || strncmp(f
,".PCD",4)==0)
552 void im_init_translation()
558 trans
=new char[256*bdep
];
560 if(vclass
==PseudoColor
)
567 col
.flags
=DoRed
| DoGreen
| DoBlue
;
570 i3
=i
*3;i2
=bdep
*(i
+1);
571 col
.red
=(unsigned short)(im
.pal
[i3
])<<8;
572 col
.green
=(unsigned short)(im
.pal
[i3
+1])<<8;
573 col
.blue
=(unsigned short)(im
.pal
[i3
+2])<<8;
574 XAllocColor(disp
,defc
,&col
);
576 global_pal
[i
]=col
.pixel
;
577 for(j
=bdep
-1;j
>=0;j
--)
579 trans
[i2
-j
-1]=(char)((col
.pixel
>>(j
<<3))& 0xff);
586 XImage
*LoadXImage(char *file
,int cmptype
,int type
)
594 if(vclass
==DirectColor
) return NULL
;
596 if(vclass
==PseudoColor
) return NULL
;
598 if(type
==F_AUTO
) type
=autodetect(file
);
604 im_load_gif(file
,&im
,fromMem
);
610 if(vclass
==PseudoColor
)
614 if(LoadJFIF(file
,&im
))
618 fprintf(stderr
,"Image Engine: LoadJpeg\n");
628 if(LoadTIFF(file
,&im
)) break;else {fprintf(stderr
,"Image Engine: LoadTiff\n");return NULL
;};
636 if(LoadPNG(file
,&im
)) break;else {fprintf(stderr
,"Image Engine: LoadPNG\n");return NULL
;};
644 if(LoadPCX(file
,&im
)) break;else {fprintf(stderr
,"Image Engine: LoadPcx\n");return NULL
;};
651 if(vclass
==PseudoColor
) translation
=0;
653 if(LoadPCD(file
,&im
)) break;else {fprintf(stderr
,"Image Engine: LoadPcd\n");return NULL
;};
661 if(LoadXBM(file
,&im
)) break;else {fprintf(stderr
,"Image Engine: LoadXBM\n");return NULL
;};
669 if(LoadXPM(file
,&im
)) break;else {fprintf(stderr
,"Image Engine: LoadXPM\n");return NULL
;};
677 if(LoadBMP(file
,&im
)) break;else {fprintf(stderr
,"Image Engine: LoadBmp\n");return NULL
;};
685 if(LoadTarga(file
,&im
)) break;else {fprintf(stderr
,"Image Engine: LoadTGA\n");return NULL
;};
689 default: return NULL
;
692 if(vclass
==PseudoColor
)
695 return im_process_pseudo_256(im_get_checked());
697 im_convert_true_to_pseudo(im
,256);
699 return im_process_pseudo_256(conv24
!=CONV24_FAST
? 230:256);
703 if(im
.type
==PIC8
&& vclass
==TrueColor
)
708 im_init_translation();
712 lw
+= b_pad
- lw
% b_pad
;
714 imdata
=new char[lw
*im
.h
];
716 for (y
=0; y
<im
.h
; y
++) {
718 for (x
=0; x
<im
.w
; x
++) {
719 ind
= im
.pic
[i
++] * bdep
;
720 for (j
=0; j
<bdep
; j
++)
721 imdata
[l
++] = trans
[ind
++];
727 imdata
=(char*)im
.pic
;
729 if((xim
=XCreateImage(disp
,vis
,depth
,ZPixmap
,0,imdata
,im
.w
,im
.h
,b_pad
*8,0))==NULL
)
732 fprintf(stderr
,"Image Engine Error: XCreateImage\n");
735 xim
->byte_order
=MSBFirst
;
737 } else if(im
.type
==PIC24
&& vclass
==TrueColor
)
743 lw
+= b_pad
- lw
% b_pad
;
744 imdata
= new char[lw
*im
.h
];
747 for (y
=0; y
< im
.h
; y
++) {
748 imdat
= imdata
+ y
* lw
;
749 for (x
=0; x
< im
.w
; x
++, i
+=3)
750 im_truetruecoding(im
.pic
[i
],im
.pic
[i
+1],im
.pic
[i
+2],&imdat
);
755 imdata
=(char*)im
.pic
;
756 if((xim
=XCreateImage(disp
,vis
,depth
,ZPixmap
,0,imdata
,im
.w
,im
.h
,b_pad
*8,0))==NULL
)
758 fprintf(stderr
,"Image Engine Error: XCreateImage\n");
762 xim
->byte_order
=MSBFirst
;
768 XImage
* encoding256(PICINFO
& im
,int ncol
)
776 trans
=new char[256*bdep
];
777 col
.flags
=DoRed
| DoGreen
| DoBlue
;
781 col
.red
=(unsigned short)(im
.pal
[i
*3])<<8;
782 col
.green
=(unsigned short)(im
.pal
[i
*3+1])<<8;
783 col
.blue
=(unsigned short)(im
.pal
[i
*3+2])<<8;
784 XAllocColor(disp
,defc
,&col
);
786 if(vclass
==PseudoColor
)
787 im_add_cmp_entry(col
.pixel
);
790 for(j
=bdep
-1;j
>=0;j
--)
792 trans
[mask
-j
-1]=(char)((col
.pixel
>>(j
<<3))& 0xff);
798 lw
+= b_pad
- lw
% b_pad
;
800 imdata
=new char[im
.h
*lw
];
801 for (i
=0; i
<im
.h
; i
++) {
802 for (k
=0; k
<im
.w
; k
++) {
803 ind
= im
.pic
[i
*im
.w
+k
];
805 delta
= i
* lw
+ k
* bdep
;
807 imdata
[delta
+j
]=trans
[ind
+j
];
811 if((xim
=XCreateImage(disp
,vis
,depth
,ZPixmap
,0,imdata
,im
.w
,im
.h
,b_pad
*8,0))==NULL
)
814 fprintf(stderr
,"Image Engine Error: XCreateImage\n");
817 xim
->byte_order
=MSBFirst
;
821 void im_256truecoding(char **data
,int ind
)
823 char *ltrans
=trans
+ind
*bdep
;
824 for(int i
=0;i
<bdep
;i
++)
825 *((*data
)++)=*(ltrans
++);
828 void im_256nocoding(char **data
,int ind
)
833 void im_256256coding(char **data
,int ind
)
835 *((*data
)++)=trans
[ind
];
838 Pixmap
LoadPixmap(char *fname
,int type
,int& l
,int& h
,int cmptype
)
843 iim
=LoadXImage(fname
,cmptype
,type
);
846 im
=XCreatePixmap(disp
,DefaultRootWindow(disp
),
847 iim
->width
,iim
->height
,depth
);
848 gcw
=XCreateGC(disp
,im
,0,NULL
);
849 l
=iim
->width
;h
=iim
->height
;
850 XPutImage(disp
,im
,gcw
,iim
,0,0,0,0,l
,h
);
852 delete iim
->data
;iim
->data
=NULL
;XDestroyImage(iim
);
858 Pixmap
LoadPixmapFromMem(char *fname
,int type
,int& l
,int& h
,
865 iim
=LoadXImage(fname
,cmptype
,type
);
869 im
=XCreatePixmap(disp
,DefaultRootWindow(disp
),
870 iim
->width
,iim
->height
,depth
);
871 gcw
=XCreateGC(disp
,im
,0,NULL
);
872 l
=iim
->width
;h
=iim
->height
;
873 XPutImage(disp
,im
,gcw
,iim
,0,0,0,0,l
,h
);
875 delete iim
->data
;iim
->data
=NULL
;XDestroyImage(iim
);
881 void im_populate_pallete(unsigned long* pal
)
886 void im_clear_global_pal()