1 /* $Header: /home/yav/xpx/RCS/tim.c,v 1.7 1996/04/24 23:08:27 yav Exp $
2  *
3  * TIM file access routine for xpx
4  * written by yav (UHD98984@pcvan.or.jp)
5  *
6  *
7  * WARNING:
8  *
9  * Permission to use and distribute this source is granted without fee.
10  * But, It is not permitted to analyze this source without license.
11  *
12  *
13  */
14 
15 #include <X11/Xlib.h>
16 
17 #include "xpx.h"
18 #include "headers.h"
19 #include "work.h"
20 #define PUBLIC_TIM_C
21 #include "extern.h"
22 
23 
24 char rcsid_tim[] = "$Id: tim.c,v 1.7 1996/04/24 23:08:27 yav Exp $";
25 
26 /*
27  * TIM - Tohshinden image file format
28  *
29  * +0: Header block
30  *  +0 - 3	magic number?
31  *  +4 - 7	bit1-0:	bytes per pixel
32  *			(0: 4bits per pixel)
33  *		bit3-2:	bytes per color
34  *			(0: no CLUT?)
35  *
36  * +8: CLUT block
37  *  +0 - 3	CLUT block length
38  *  +4,5	(unknown)
39  *  +6,7	(unknown)
40  *  +8,9	number of colors?
41  *  +10,11	number of color groups?
42  *  +12...	color data
43  *		2bytes per color:
44  *			(bit14-10:blue, 9-5:green, 4-0:red)
45  *
46  * +8+12+n*(2or3): Pixel block
47  *  +0 - 3	Pixel block length
48  *  +4,5	x-offset?
49  *  +6,7	y-offset?
50  *  +8,9	image width (unit short)
51  *  +10,11	image height
52  *  +12...	pixel data
53  *
54  */
55 
56 typedef struct _TIM_BLOCK_INFO {
57   long len;			/* Block length (byte) */
58   short x, y;
59   short w, h;
60 } TIM_BLOCK_INFO;
61 
read_tim_block_info(fp,p)62 int read_tim_block_info(fp, p)
63      FILE *fp;
64      TIM_BLOCK_INFO *p;
65 {
66   p->len = readlelong(fp);
67   p->x = readleshort(fp);
68   p->y = readleshort(fp);
69   p->w = readleshort(fp);
70   p->h = readleshort(fp);
71   message(" len = %ld, x = %d, y = %d, w = %d, h = %d\n",
72 	  p->len, p->x, p->y, p->w, p->h);
73   if (debug_mode)
74     fprintf(stderr, " len = %ld, x = %d, y = %d, w = %d, h = %d\n",
75 	    p->len, p->x, p->y, p->w, p->h);
76   return 0;
77 }
78 
79 
80 /* read CLUT block */
read_clut(fp)81 int read_clut(fp)
82      FILE *fp;
83 {
84   int i, n, c;
85   TIM_BLOCK_INFO info;
86   COL *cp;
87 
88   read_tim_block_info(fp, &info);
89   free_color_all();
90   colposx = info.x;
91   colposy = info.y;
92   colfilew = info.w;
93   colfileh = info.h;
94   n = (info.len - 12) / 2;	/* number of colors */
95   cp = color_buf;
96   for (i = 0; i < n; i++) {
97     c = readleshort(fp);
98     if (i < 256) {
99       cp->rgb.red = (c & 0x1f) << 3;
100       cp->rgb.green = ((c >> 5) & 0x1f) << 3;
101       cp->rgb.blue = ((c >> 10) & 0x1f) << 3;
102       cp++;
103     }
104   }
105   if (i > 256)
106     i = 256;
107   get_color(color_buf, i);
108   get_requested_colors();
109   return 0;
110 }
111 
112 /* read TIM file */
rd_tim(fp)113 int rd_tim(fp)
114      FILE *fp;
115 {
116   int c;
117   int clut;			/* bytes per color */
118   int bpp;			/* bytes per pixel (0:4bit) */
119   int x, y, w, h;
120   long l;
121   TIM_BLOCK_INFO info;
122   unsigned char lnbuf[1024];
123 
124   /* skip magic number */
125   l = readlelong(fp);
126   message("\nLoad TIM file.\n");
127   message(" magic number = 0x%08lx\n", l);
128   if (debug_mode)
129     fprintf(stderr, " magic number = 0x%08lx\n", l);
130   /* read header */
131   l = readlelong(fp);
132   c = l;
133   bpp = c & 3;
134   clut = (c >> 2) & 3;
135   message(" mode = %08lx (bpp = %d, clut = %d)\n", l, bpp, clut);
136   if (debug_mode)
137     fprintf(stderr, " mode = %08lx (bpp = %d, clut = %d)\n", l, bpp, clut);
138 
139   if (clut)
140     read_clut(fp);
141 
142   /* read pixel block */
143   read_tim_block_info(fp, &info);
144   imgposx = info.x;
145   imgposy = info.y;
146   w = info.w;
147   h = info.h;
148   for (y = 0; y < h; y++) {
149     if (y >= imgmaxh)
150       break;
151     fread(lnbuf, 1, w*2, fp);
152     switch (bpp) {
153     case 0:			/* 1/2 byte per pixel */
154       for (x = 0; x < w*2; x++) {
155 	imgdata[y*imgmaxw+x*2] = lnbuf[x] & 0x0f;
156 	imgdata[y*imgmaxw+x*2+1] = lnbuf[x] >> 4;
157       }
158       break;
159     case 1:			/* 1 byte per pixel */
160       memcpy(imgdata+y*imgmaxw, lnbuf, w*2);
161       break;
162     default:			/* other depth */
163       message("!\nNot supported pixel depth!\n");
164       return 1;
165     }
166   }
167   /* calc true image width */
168   switch (bpp) {
169   case 0:			/* 1/2 byte per pixel */
170     w *= 4;
171     imgfiledepth = 4;
172     break;
173   case 1:			/* 1 byte per pixel */
174     w *= 2;
175     imgfiledepth = 8;
176     break;
177   default:			/* other depth */
178     message("!\nNot supported pixel depth!\n");
179     return 1;
180   }
181   imgupdate(w, h);
182   return 0;
183 }
184 
185 /* write TIM file */
wr_tim(fp)186 int wr_tim(fp)
187      FILE *fp;
188 {
189   long l;
190   int i, x, y;
191   COL *cp;
192   char *p;
193   char buf[1024];
194 
195   setlelong(buf, 0x10L);
196   if (imgfiledepth < 0)
197     return 1;
198   if (!imgfiledepth)
199     imgfiledepth = 4;
200 
201   if (imgfiledepth <= 4)
202     l = 0;
203   else if (imgfiledepth <= 8)
204     l = 1;
205   else
206     return 1;
207 
208   l |= 8;			/* 2 bytes per color */
209   setlelong(buf+4, l);
210   if (!fwrite(buf, 8, 1, fp))
211     return 1;			/* header write error! */
212 
213   /* colors */
214   l = 4 + 2 + 2 + 2 + 2 + colfilew * colfileh * 2;
215   setlelong(buf, l);
216   setleshort(buf+4, colposx);
217   setleshort(buf+6, colposy);
218   setleshort(buf+8, colfilew);
219   setleshort(buf+10, colfileh);
220   if (!fwrite(buf, 12, 1, fp))
221     return 1;			/* clut block header write error! */
222 
223   cp = color_buf;
224   for (y = 0; y < colfileh; y++) {
225     for (x = 0; x < colfilew; x++) {
226       l = (cp->rgb.red >> 3)
227 	| ((cp->rgb.green >> 3) << 5)
228 	  | ((cp->rgb.blue >> 3) << 10);
229       cp++;
230       setleshort(buf+x*2, (int)l);
231     }
232     if (!fwrite(buf, colfilew*2, 1, fp))
233       return 1;			/* color data write error! */
234   }
235 
236   /* pixel block */
237   /* get width short count */
238   i = (imgfiledepth == 4) ? imgfilew/4 : imgfilew/2;
239   l = 4 + 2 + 2 + 2 + 2 + i * 2 * imgfileh;
240   setlelong(buf, l);
241   setleshort(buf+4, imgposx);
242   setleshort(buf+6, imgposy);
243   setleshort(buf+8, i);
244   setleshort(buf+10, imgfileh);
245   if (!fwrite(buf, 12, 1, fp))
246     return 1;			/* pixel block header write error! */
247 
248   if (imgfiledepth == 4) {
249     for (y = 0; y < imgfileh; y++) {
250       p = buf;
251       for (x = 0; x < i; x++) {
252 	*p++ = imgdata[y*imgmaxw+x*4+0] + (imgdata[y*imgmaxw+x*4+1]<<4);
253 	*p++ = imgdata[y*imgmaxw+x*4+2] + (imgdata[y*imgmaxw+x*4+3]<<4);
254       }
255       if (!fwrite(buf, i*2, 1, fp))
256 	return 1;		/* pixel write error! */
257     }
258   } else {
259     for (y = 0; y < imgfileh; y++) {
260       if (!fwrite(imgdata+y*imgmaxw, i*2, 1, fp))
261 	return 1;		/* pixel write error! */
262     }
263   }
264   return 0;
265 }
266 
267 /* read CLS file */
rd_cls(fp)268 int rd_cls(fp)
269      FILE *fp;
270 {
271   long l;
272   int c, bpp, clut;
273 
274   l = readlelong(fp);
275   message("\nLoad CLS file.\n");
276   message(" magic number = 0x%08lx\n", l);
277   if (debug_mode)
278     fprintf(stderr, " magic number = 0x%08lx\n", l);
279 
280   /* read header */
281   l = readlelong(fp);
282   c = l;
283   bpp = c & 3;
284   clut = (c >> 2) & 3;
285   message(" mode = %08lx (bpp = %d, clut = %d)\n", l, bpp, clut);
286   if (debug_mode)
287     fprintf(stderr, " mode = %08lx (bpp = %d, clut = %d)\n", l, bpp, clut);
288 
289   read_clut(fp);
290   return 0;
291 }
292 
293 /* End of file */
294