7fd59977 |
1 | /* |
2 | Created: zov : 1-Apr-1998 : Saves an image as .XWD file |
3 | Note: Adapted from Xw_save_image.c |
4 | */ |
5 | |
6 | #define PRO5356 /* GG_130996: Compatibillite vis a vis de XReadDisplay (IRIX) |
7 | GG_240898 Compatibillite vis a vis de XReadScreen (SOLARIS) |
8 | */ |
9 | |
10 | #define PRO16753 /* GG 261198 |
11 | // Don't free pname because this pointer is a |
12 | // static address in Xw_get_filename() space. |
13 | */ |
14 | |
15 | #include <Xw_Extension.h> |
16 | |
17 | /* ifdef then trace on */ |
18 | #ifdef TRACE |
19 | #define TRACE_SAVE_IMAGE |
20 | #endif |
21 | |
22 | #define DECOSF1_COMPATIBILITY |
23 | |
24 | /* |
25 | |
26 | XW_STATUS Xw_save_xwd_image (awindow,aimage,filename): |
27 | XW_EXT_WINDOW *awindow |
28 | XW_EXT_IMAGEDATA *aimage |
29 | char *filename XWD Image name |
30 | |
31 | Save an image to an XWD file. |
32 | |
33 | returns SUCCESS if successfull |
34 | returns ERROR if something is wrong |
35 | |
36 | */ |
37 | |
38 | #define SWAPTEST (*(char*)&swaptest) |
39 | #define LOWBIT(x) ((x) & (~(x) + 1)) |
40 | |
41 | static unsigned long swaptest = 1; |
42 | #ifdef XW_PROTOTYPE |
43 | static void SwapLong ( char*, unsigned); |
44 | static void SwapShort ( char* bp, unsigned); |
45 | #else |
46 | static void SwapLong(); |
47 | static void SwapShort(); |
48 | #endif |
49 | static XWDFileHeader header; |
50 | |
51 | #ifdef XW_PROTOTYPE |
52 | XW_STATUS Xw_save_xwd_image_adv (Display *aDisplay,Window aWindow,XWindowAttributes aWinAttr,XImage *aPximage,Colormap aColormap,int aNcolors,char *filename) |
53 | #else |
54 | XW_STATUS Xw_save_xwd_image_adv (aDisplay,aWindow,aWinAttr,aPximage,aColormap,aNcolors,filename) |
55 | Display *aDisplay; |
56 | Window aWindow; |
57 | XWindowAttributes aWinAttr; |
58 | XImage *aPximage; |
59 | Colormap aColormap; |
60 | int ncolors; |
61 | char *filename; |
62 | #endif /*XW_PROTOTYPE*/ |
63 | { |
64 | char *wname = NULL,*pname = NULL ; |
65 | int i,isize,lname,iclass,ncolors; |
66 | Visual *pvisual = aWinAttr.visual; |
67 | XColor *pcolors = NULL; |
68 | XWDColor *qcolors = NULL; |
69 | FILE *fimage = NULL ; |
70 | XW_STATUS status = XW_SUCCESS; |
71 | |
72 | pname = Xw_get_filename(filename,"xwd") ; |
73 | /* Open XWD File */ |
74 | if( pname ) fimage = fopen(pname,"w") ; |
75 | |
76 | if( !fimage ) { |
77 | /*ERROR*Bad Filename*/ |
78 | Xw_set_error(55,"Xw_save_xwd_image",filename) ; |
79 | return (XW_ERROR) ; |
80 | } |
81 | /* Get Window name */ |
82 | XFetchName(aDisplay,aWindow,&wname); |
83 | |
84 | if( !wname || !strlen(wname) ) { |
85 | wname = (char*) strdup(pname); |
86 | } |
87 | lname = strlen(wname) + 1; |
88 | |
89 | iclass = pvisual->c_class; |
90 | #ifdef PRO5356 |
91 | if( (iclass == PseudoColor) && (aPximage->red_mask > 0) ) iclass = TrueColor; |
92 | |
93 | /* iclass = (pximage->depth > 8) ? TrueColor : pvisual->c_class; GG_240898 */ |
94 | #endif |
95 | /* Get color table */ |
96 | switch ( iclass ) { |
97 | case PseudoColor : |
98 | ncolors = aNcolors; |
99 | if(( pcolors = (XColor*) Xw_calloc(ncolors,sizeof(XColor)) )) { |
100 | for( i=0 ; i<ncolors ; i++) { |
101 | pcolors[i].pixel = i; |
102 | pcolors[i].pad = 0; |
103 | } |
104 | XQueryColors(aDisplay,aColormap,pcolors,ncolors); |
105 | #ifdef DECOSF1_COMPATIBILITY |
106 | if( sizeof(XColor) != sizeof(XWDColor) ) { |
107 | if(( qcolors = (XWDColor*) Xw_calloc(ncolors,sizeof(XWDColor)) )) { |
108 | for( i=0 ; i<ncolors ; i++) { |
109 | qcolors[i].pixel = pcolors[i].pixel; |
110 | qcolors[i].red = pcolors[i].red; |
111 | qcolors[i].green = pcolors[i].green; |
112 | qcolors[i].blue = pcolors[i].blue; |
113 | qcolors[i].flags = pcolors[i].flags; |
114 | qcolors[i].pad = 0; |
115 | } |
116 | Xw_free(pcolors); |
117 | } else { |
118 | /*ERROR*Bad Image allocation*/ |
119 | Xw_set_error(60,"Xw_save_xwd_image",0) ; |
120 | Xw_free(wname) ; |
121 | #ifndef PRO16753 |
122 | Xw_free(pname) ; |
123 | #endif |
124 | Xw_free(pcolors) ; |
125 | fclose(fimage) ; |
126 | return (XW_ERROR) ; |
127 | } |
128 | } else { |
129 | qcolors = (XWDColor*) pcolors; |
130 | } |
131 | #endif |
132 | } else { |
133 | /*ERROR*Bad Image allocation*/ |
134 | Xw_set_error(60,"Xw_save_xwd_image",0) ; |
135 | Xw_free(wname) ; |
136 | #ifndef PRO16753 |
137 | Xw_free(pname) ; |
138 | #endif |
139 | fclose(fimage) ; |
140 | return (XW_ERROR) ; |
141 | } |
142 | break ; |
143 | case TrueColor : |
144 | ncolors = 0; |
145 | break ; |
146 | case DirectColor : |
147 | ncolors = aNcolors; |
148 | if(( pcolors = (XColor*) Xw_calloc(ncolors,sizeof(XColor)) )) { |
149 | unsigned long red = 0,lred = LOWBIT(pvisual->red_mask); |
150 | unsigned long green = 0,lgreen = LOWBIT(pvisual->green_mask); |
151 | unsigned long blue = 0,lblue = LOWBIT(pvisual->blue_mask); |
152 | for( i=0 ; i<ncolors ; i++) { |
153 | pcolors[i].pixel = red|green|blue; |
154 | pcolors[i].pad = 0; |
155 | red += lred; |
156 | if( red > pvisual->red_mask ) red = 0; |
157 | green += lgreen; |
158 | if( green > pvisual->green_mask ) green = 0; |
159 | blue += lblue; |
160 | if( blue > pvisual->blue_mask ) blue = 0; |
161 | } |
162 | XQueryColors(aDisplay,aColormap,pcolors,ncolors); |
163 | #ifdef DECOSF1_COMPATIBILITY |
164 | if( sizeof(XColor) != sizeof(XWDColor) ) { |
165 | if(( qcolors = (XWDColor*) Xw_calloc(ncolors,sizeof(XWDColor)) )) { |
166 | for( i=0 ; i<ncolors ; i++) { |
167 | qcolors[i].pixel = pcolors[i].pixel; |
168 | qcolors[i].red = pcolors[i].red; |
169 | qcolors[i].green = pcolors[i].green; |
170 | qcolors[i].blue = pcolors[i].blue; |
171 | qcolors[i].flags = pcolors[i].flags; |
172 | qcolors[i].pad = 0; |
173 | } |
174 | Xw_free(pcolors); |
175 | } else { |
176 | /*ERROR*Bad Image allocation*/ |
177 | Xw_set_error(60,"Xw_save_xwd_image",0) ; |
178 | Xw_free(wname) ; |
179 | #ifndef PRO16753 |
180 | Xw_free(pname) ; |
181 | #endif |
182 | Xw_free(pcolors) ; |
183 | fclose(fimage) ; |
184 | return (XW_ERROR) ; |
185 | } |
186 | } else { |
187 | qcolors = (XWDColor*) pcolors; |
188 | } |
189 | #endif |
190 | } else { |
191 | /*ERROR*Bad Image allocation*/ |
192 | Xw_set_error(60,"Xw_save_xwd_image",0) ; |
193 | Xw_free(wname) ; |
194 | #ifndef PRO16753 |
195 | Xw_free(pname) ; |
196 | #endif |
197 | fclose(fimage) ; |
198 | return (XW_ERROR) ; |
199 | } |
200 | break ; |
201 | default : |
202 | /*ERROR*Unimplemented Image Visual class*/ |
203 | Xw_set_error(59,"Xw_save_xwd_image",&header.visual_class) ; |
204 | fclose(fimage) ; |
205 | return (XW_ERROR) ; |
206 | } |
207 | |
208 | /* Build Header */ |
209 | header.ncolors = ncolors; |
210 | header.header_size = (CARD32) (sizeof(header) + lname); |
211 | header.file_version = (CARD32) XWD_FILE_VERSION; |
212 | header.pixmap_format = (CARD32) ZPixmap; |
213 | header.pixmap_depth = (CARD32) aPximage->depth; |
214 | header.pixmap_width = (CARD32) aPximage->width; |
215 | header.pixmap_height = (CARD32) aPximage->height; |
216 | header.xoffset = (CARD32) aPximage->xoffset; |
217 | header.byte_order = (CARD32) aPximage->byte_order; |
218 | header.bitmap_unit = (CARD32) aPximage->bitmap_unit; |
219 | header.bitmap_bit_order = (CARD32) aPximage->bitmap_bit_order; |
220 | header.bitmap_pad = (CARD32) aPximage->bitmap_pad; |
221 | header.bits_per_pixel = (CARD32) aPximage->bits_per_pixel; |
222 | header.bytes_per_line = (CARD32) aPximage->bytes_per_line; |
223 | header.visual_class = (CARD32) iclass; |
224 | #ifdef PRO5356 |
225 | header.red_mask = (CARD32) aPximage->red_mask; |
226 | header.green_mask = (CARD32) aPximage->green_mask; |
227 | header.blue_mask = (CARD32) aPximage->blue_mask; |
228 | #else |
229 | header.red_mask = (CARD32) pvisual->red_mask; |
230 | header.green_mask = (CARD32) pvisual->green_mask; |
231 | header.blue_mask = (CARD32) pvisual->blue_mask; |
232 | #endif |
233 | header.bits_per_rgb = (CARD32) pvisual->bits_per_rgb; |
234 | header.colormap_entries = (CARD32) pvisual->map_entries; |
235 | header.window_width = (CARD32) aWinAttr.width; |
236 | header.window_height = (CARD32) aWinAttr.height; |
237 | header.window_x = aWinAttr.x; |
238 | header.window_y = aWinAttr.y; |
239 | header.window_bdrwidth = (CARD32) aWinAttr.border_width; |
240 | isize = header.bytes_per_line*header.pixmap_height ; |
241 | |
242 | if( SWAPTEST ) { |
243 | SwapLong((char*) &header,sizeof(header)) ; |
244 | #ifdef DECOSF1_COMPATIBILITY |
245 | for( i=0 ; i<ncolors ; i++) { |
246 | SwapLong((char *) &qcolors[i].pixel,4); |
247 | SwapShort((char *) &qcolors[i].red, 3*sizeof(short)); |
248 | } |
249 | #else |
250 | for( i=0 ; i<ncolors ; i++) { |
251 | SwapLong((char *) &pcolors[i].pixel,sizeof(long)); |
252 | SwapShort((char *) &pcolors[i].red, 3*sizeof(short)); |
253 | } |
254 | #endif |
255 | } |
256 | |
257 | if( status && (int)fwrite((char *)&header, sizeof(header), 1, fimage) < 1 ) |
258 | status = XW_ERROR; |
259 | if( status && (int)fwrite(wname, lname, 1, fimage) < 1 ) status = XW_ERROR; |
260 | |
261 | /* |
262 | * Write out the color maps, if any |
263 | */ |
264 | |
265 | #ifdef DECOSF1_COMPATIBILITY |
266 | if( ncolors > 0 ) { |
267 | if( status && |
268 | (int)fwrite((char *) qcolors, sizeof(XWDColor), ncolors, fimage) < ncolors ) |
269 | status = XW_ERROR; |
270 | } |
271 | #else |
272 | if( ncolors > 0 ) { |
273 | if( status && |
274 | fwrite((char *) pcolors, sizeof(XColor), ncolors, fimage) < ncolors ) |
275 | status = XW_ERROR; |
276 | } |
277 | #endif |
278 | |
279 | /* |
280 | * Write out the buffer. |
281 | */ |
282 | |
283 | /* |
284 | * This copying of the bit stream (data) to a file is to be replaced |
285 | * by an Xlib call which hasn't been written yet. It is not clear |
286 | * what other functions of xwd will be taken over by this (as yet) |
287 | * non-existant X function. |
288 | */ |
289 | if( status && (int)fwrite(aPximage->data, 1, isize, fimage) < isize ) |
290 | status = XW_ERROR; |
291 | |
292 | /* Close the image file */ |
293 | fclose(fimage) ; |
294 | |
295 | #ifndef PRO16753 |
296 | Xw_free(pname) ; |
297 | #endif |
298 | |
299 | Xw_free(wname) ; |
300 | |
301 | #ifdef DECOSF1_COMPATIBILITY |
302 | if( qcolors ) Xw_free(qcolors) ; |
303 | #else |
304 | if( pcolors ) Xw_free(pcolors) ; |
305 | #endif |
306 | |
307 | return (status); |
308 | } |
309 | |
310 | #ifdef XW_PROTOTYPE |
311 | XW_STATUS Xw_save_xwd_image (void *awindow,void *aimage,char *filename) |
312 | #else |
313 | XW_STATUS Xw_save_xwd_image (awindow,aimage,filename) |
314 | void *awindow; |
315 | void *aimage; |
316 | char *filename ; |
317 | #endif /*XW_PROTOTYPE*/ |
318 | { |
319 | XW_EXT_WINDOW *pwindow = (XW_EXT_WINDOW*) awindow; |
320 | XW_EXT_IMAGEDATA *pimage = (XW_EXT_IMAGEDATA*) aimage; |
321 | XImage *pximage = NULL; |
322 | XW_STATUS status = XW_SUCCESS; |
323 | |
324 | if( !Xw_isdefine_window(pwindow) ) { |
325 | /*ERROR*Bad EXT_WINDOW Address*/ |
326 | Xw_set_error(24,"Xw_save_xwd_image",pwindow) ; |
327 | return (XW_ERROR) ; |
328 | } |
329 | |
330 | if( !Xw_isdefine_image(pimage) ) { |
331 | /*ERROR*Bad EXT_IMAGEDATA Address*/ |
332 | Xw_set_error(25,"Xw_save_xwd_image",pimage) ; |
333 | return (XW_ERROR) ; |
334 | } |
335 | |
336 | pximage = (_ZIMAGE) ? _ZIMAGE : _IIMAGE; |
337 | |
338 | status = Xw_save_xwd_image_adv(_DISPLAY,_WINDOW,_ATTRIBUTES,pximage,_COLORMAP->info.colormap,_COLORMAP->maxhcolor,filename); |
339 | #ifdef TRACE_SAVE_IMAGE |
340 | if( Xw_get_trace() ) { |
341 | printf (" %d = Xw_save_xwd_image(%lx,%lx,'%s')\n",status,(long ) pwindow,(long ) pimage,filename); |
342 | } |
343 | #endif |
344 | return status; |
345 | } |
346 | |
347 | #ifdef XW_PROTOTYPE |
348 | static void SwapLong (register char* bp, register unsigned n) |
349 | #else |
350 | static void SwapLong (bp, n) |
351 | register char *bp; |
352 | register unsigned n; |
353 | #endif |
354 | /* |
355 | Swap long ints depending of CPU |
356 | */ |
357 | { |
358 | register char c; |
359 | register char *ep = bp + n; |
360 | register char *sp; |
361 | |
362 | while (bp < ep) { |
363 | sp = bp + 3; |
364 | c = *sp; |
365 | *sp = *bp; |
366 | *bp++ = c; |
367 | sp = bp + 1; |
368 | c = *sp; |
369 | *sp = *bp; |
370 | *bp++ = c; |
371 | bp += 2; |
372 | } |
373 | } |
374 | |
375 | #ifdef XW_PROTOTYPE |
376 | static void SwapShort (register char* bp, register unsigned n) |
377 | #else |
378 | static void SwapShort (bp, n) |
379 | register char *bp; |
380 | register unsigned n; |
381 | #endif |
382 | /* |
383 | Swap short ints depending of CPU |
384 | */ |
385 | { |
386 | register char c; |
387 | register char *ep = bp + n; |
388 | |
389 | while (bp < ep) { |
390 | c = *bp; |
391 | *bp = *(bp + 1); |
392 | bp++; |
393 | *bp++ = c; |
394 | } |
395 | } |