1 /* $Header: /home/yav/xpx/RCS/mag.c,v 1.10 1996/04/23 10:58:05 yav Exp $
2 * xpx save load MAG format
3 * written by yav (UHD98984@pcvan.or.jp)
4 */
5
6 #include <X11/Xlib.h>
7
8 #include "xpx.h"
9 #include "headers.h"
10 #include "work.h"
11 #define PUBLIC_MAG_C
12 #include "extern.h"
13
14
15 char rcsid_mag[] = "$Id: mag.c,v 1.10 1996/04/23 10:58:05 yav Exp $";
16 static char mag_magic_number[] = "MAKI02 ";
17 static char mag_default_user[] = ">\x93\xe4<";
18 static struct {int x,y;} magpostbl[16]={
19 {0,0},{1,0},{2,0},{4,0},{0,1},{1,1},{0,2},{1,2},
20 {2,2},{0,4},{1,4},{2,4},{0,8},{1,8},{2,8},{0,16}};
21 static long flagAsize;
22 static long flagBsize;
23 static long pixelsize;
24 static unsigned char *pixelbuf = NULL;
25 static unsigned char *flaga = NULL;
26 static unsigned char *flagb = NULL;
27
28
29 /* store short integer to char buffer as little-endian
30 */
setleshort(p,n)31 void setleshort(p, n)
32 char *p;
33 int n;
34 {
35 *p++ = n;
36 *p = n >> 8;
37 }
38
39 /* store long integer to char buffer as little-endian
40 */
setlelong(p,n)41 void setlelong(p, n)
42 char *p;
43 long n;
44 {
45 *p++ = n;
46 *p++ = n >> 8;
47 *p++ = n >> 16;
48 *p = n >> 24;
49 }
50
51 /* write MAG palette data
52 * Caution! Now supported only 16 colors format
53 */
write_mag_palette_section(fp)54 int write_mag_palette_section(fp)
55 FILE *fp;
56 {
57 int i;
58 COL *cp;
59 char buf[3*16], *p;
60
61 cp = color_buf;
62 p = buf;
63 for (i = 0; i < 16; i++) {
64 *p++ = cp->rgb.green;
65 *p++ = cp->rgb.red;
66 *p++ = cp->rgb.blue;
67 cp++;
68 }
69 if (!fwrite(buf, 3*16, 1, fp))
70 return 1;
71 return 0;
72 }
73
alloc_compress_work()74 int alloc_compress_work()
75 {
76 int w;
77
78 w = (imgfilew+7)/8;
79 pixelbuf = (unsigned char *)malloc((imgfilew+1)/2*imgfileh);
80 flaga = (unsigned char *)malloc(w*imgfileh + 1);
81 flagb = (unsigned char *)malloc(w*imgfileh + 1);
82 return pixelbuf == NULL || flaga == NULL || flagb == NULL;
83 }
84
free_compress_work()85 void free_compress_work()
86 {
87 if (pixelbuf != NULL) {
88 free(pixelbuf);
89 pixelbuf = NULL;
90 }
91 if (flaga != NULL) {
92 free(flaga);
93 flaga = NULL;
94 }
95 if (flagb != NULL) {
96 free(flagb);
97 flagb = NULL;
98 }
99 }
100
is_same_pixel(x,y,dd)101 int is_same_pixel(x, y, dd)
102 int x;
103 int y;
104 int dd;
105 {
106 int dx, dy;
107
108 dx = x - magpostbl[dd].x * 4;
109 dy = y - magpostbl[dd].y;
110 if (dx < 0 || dy < 0)
111 return 0;
112 return memcmp(imgdata+imgmaxw*y+x, imgdata+imgmaxw*dy+dx, 4) == 0;
113 }
114
search_same_pixel(x,y)115 int search_same_pixel(x, y)
116 int x;
117 int y;
118 {
119 int i, n;
120 static int stbl[15] = {1,4,5,6,7,9,10,2,8,11,12,13,14,3,15};
121
122 for (i = 0; i < 15; i++) {
123 n = stbl[i];
124 if (is_same_pixel(x, y, n))
125 return n;
126 }
127 return 0; /* not found */
128 }
129
130 /* compress MAG
131 * imgdata imgmaxw x imgmaxh
132 * effective area imgfilew x imgfileh
133 */
mag_compress()134 int mag_compress()
135 {
136 int x, y, n0, n1, w, bitpos;
137 unsigned char *flagbuf, *pf;
138 unsigned char *flagbuf2, *pf2; /* upper line flag cache */
139 unsigned char *pi, *pp;
140 unsigned char *pa, *pb;
141
142 w = (imgfilew+7)/8;
143 pf = flagbuf = (unsigned char *)malloc(w*imgfileh);
144 if (flagbuf == NULL)
145 return 1;
146 flagbuf2 = (unsigned char *)malloc(w);
147 if (flagbuf2 == NULL) {
148 free(flagbuf);
149 return 1;
150 }
151 if (alloc_compress_work()) {
152 free(flagbuf);
153 free_compress_work();
154 return 1;
155 }
156 pp = pixelbuf;
157 bzero(flagbuf2, w);
158 for (y = 0; y < imgfileh; y++) {
159 pi = imgdata+imgmaxw*y;
160 pf2 = flagbuf2;
161 for (x = 0; x < imgfilew; x += 8) {
162 n0 = *pf2 >> 4;
163 if (!n0 || !is_same_pixel(x, y, n0))
164 n0 = search_same_pixel(x, y);
165 if (!n0) {
166 *pp++ = (*pi << 4) | *(pi+1);
167 *pp++ = (*(pi+2) << 4) | *(pi+3);
168 }
169 pi += 4;
170 n1 = *pf2 & 0x0f;
171 if (!n1 || !is_same_pixel(x+4, y, n1))
172 n1 = search_same_pixel(x+4, y);
173 if (!n1) {
174 *pp++ = (*pi << 4) | *(pi+1);
175 *pp++ = (*(pi+2) << 4) | *(pi+3);
176 }
177 pi += 4;
178 *pf2++ = *pf++ = (n0 << 4) | n1;
179 }
180 }
181 for (y = imgfileh-1; y > 0; y--) {
182 pf = flagbuf+w*y;
183 for (x = 0; x < w; x++)
184 *pf++ ^= *(pf-w);
185 }
186 bitpos = 0x80;
187 pf = flagbuf;
188 pa = flaga;
189 pb = flagb;
190 for (y = 0; y < imgfileh; y++) {
191 for (x = 0; x < w; x++) {
192 if (*pf) {
193 *pb++ = *pf;
194 *pa |= bitpos;
195 }
196 if (!(bitpos >>= 1)) {
197 pa++;
198 *pa = 0;
199 bitpos = 0x80;
200 }
201 pf++;
202 }
203 }
204 if (bitpos != 0x80)
205 pa++;
206 flagAsize = pa - flaga;
207 if (flagAsize & 1)
208 flagAsize++;
209 flagBsize = pb - flagb;
210 if (flagBsize & 1)
211 flagBsize++;
212 pixelsize = pp - pixelbuf;
213 free(flagbuf);
214 free(flagbuf2);
215 return 0; /* success */
216 }
217
wr_mag(fp)218 int wr_mag(fp)
219 FILE *fp;
220 {
221 int i, x, y, comp;
222 unsigned char *p;
223 long l, flagAofs, flagBofs, pixelofs;
224 char *username, *comment;
225 char buf[512];
226
227 if (!imgfiledepth)
228 imgfiledepth = 4; /* If no depth info, treat 4 bit depth */
229 if (imgfiledepth > 4) {
230 message("!\n Supported only 16 color mag!\n");
231 return 1;
232 }
233 comp = 1;
234 username = (char *)getenv("USER");
235 if (username == NULL)
236 username = mag_default_user;
237 sprintf(buf, "%sxpx %-18.18s ", mag_magic_number, username);
238 if (!fwrite(buf, strlen(buf), 1, fp))
239 return 1;
240 sprintf(buf, "Saved by %s %s", myname, xpx_version);
241 comment = buf;
242 if (!fwrite(comment, strlen(comment), 1, fp))
243 return 1;
244 if (!fwrite("\032", 1, 1, fp))
245 return 1;
246 if (comp) {
247 if (mag_compress())
248 comp = 0; /* compression failed, select no compression */
249 }
250 if (!comp) {
251 flagAsize = ((imgfilew+3)/4+1)/2;
252 flagAsize *= imgfileh;
253 if (flagAsize & 1)
254 ++flagAsize;
255 flagBsize = 0;
256 pixelsize = ((imgfilew*imgfileh+3)/4) * 2;
257 }
258 flagAofs = 32 + 3*16;
259 flagBofs = flagAofs + flagAsize;
260 pixelofs = flagBofs + flagBsize;
261 /* write header */
262 bzero(buf, 32);
263 setleshort(buf+4, imgposx);
264 setleshort(buf+6, imgposy);
265 setleshort(buf+8, imgposx+imgfilew-1);
266 setleshort(buf+10, imgposy+imgfileh-1);
267 setlelong(buf+12, flagAofs);
268 setlelong(buf+16, flagBofs);
269 setlelong(buf+20, flagBsize);
270 setlelong(buf+24, pixelofs);
271 setlelong(buf+28, pixelsize);
272 fwrite(buf, 32, 1, fp);
273 write_mag_palette_section(fp);
274 if (comp) {
275 /* write flagA */
276 fwrite(flaga, 1, flagAsize, fp);
277 /* flagB */
278 fwrite(flagb, 1, flagBsize, fp);
279 /* write pixel */
280 fwrite(pixelbuf, 1, pixelsize, fp);
281 free_compress_work();
282 } else {
283 /* write flagA */
284 l = flagAsize;
285 bzero(buf, sizeof(buf));
286 while (l > 0) {
287 i = l < sizeof(buf) ? l : sizeof(buf);
288 fwrite(buf, i, 1, fp);
289 l -= i;
290 }
291 /* No need to save flagB */
292 /* write pixel */
293 for (y = 0; y < imgfileh; y++) {
294 p = imgdata+y*imgmaxw;
295 for (x = 0; x < imgfilew; x += 4) {
296 buf[0] = (*p << 4) | *(p+1);
297 buf[1] = (*(p+2) << 4) | *(p+3);
298 p += 4;
299 fwrite(buf, 2, 1, fp);
300 }
301 }
302 }
303 return ferror(fp);
304 }
305
rd_mag(fp)306 int rd_mag(fp)
307 FILE *fp;
308 {
309 int w, h;
310
311 free_color_all();
312 decode_mag(fp, "*noname*");
313 get_color(color_buf, mag_palcnt);
314 get_requested_colors();
315 w = mag_dataw;
316 h = mag_datah;
317 if (w > imgmaxw) {
318 w = imgmaxw;
319 message("!\nwidth %d trancate to %d.\n", mag_dataw, w);
320 }
321 if (h > imgmaxh) {
322 h = imgmaxh;
323 message("!\nheight %d trancate to %d.\n", mag_datah, h);
324 }
325 imgupdate(w, h);
326 return 0;
327 }
328
329 /* End of file */
330