1
/*===========================================================================
2
Copyright (C) 2000 Craig B. Markwardt
4
This program is free software; you can redistribute it and/or
5
modify it under the terms of the GNU General Public License as
6
published by the Free Software Foundation; either version 2 of
7
the License, or (at your option) any later version.
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU General Public License for more details.
14
You should have received a copy of the GNU General Public
15
License along with this program; if not, write to the Free
16
Software Foundation, Inc., 675 Massachusetts Ave, Cambridge,
19
Correspondence concerning ESO-MIDAS should be addressed as follows:
20
Internet e-mail: midas@eso.org
21
Postal address: European Southern Observatory
22
Data Management Division
23
Karl-Schwarzschild-Strasse 2
24
D 85748 Garching bei Muenchen
26
===========================================================================*/
28
/***********************************************************************
32
* IDI Device Dependent Routines
33
* (version for XWindows release 11)
36
* V 1.00 001129: C. Markwardt - conversions for 24- and 16-bit visuals
38
* get_plane_offset : convert bitmask to a shift offset
39
* idi_conv32_24 : convert 32-bit RGB to 24-bit RGB
40
* idi_conv24_32 : convert 24-bit RGB to 32-bit RGB
41
* idi_conv32_16 : convert 32-bit RGB to 16-bit RGB
42
* idi_conv16_32 : convert 16-bit RGB to 32-bit RGB
43
* idi_order32 : reorder 32-bit RGB
44
* idi_putimage : wrapper for XPutImage
45
* idi_getsubimage : wrapper for XGetSubImage
46
* test_swap : check, if byte swap is needed
50
************************************************************************/
59
#include <idistruct.h>
61
#include <proto_idi.h>
64
/* Determine the shift to apply to 8-bit data to align with "mask" */
66
get_plane_offset(mask, wordsize)
67
unsigned int mask, wordsize;
71
if ( (mask>>i) & 1 ) return (i+1-wordsize);
78
/* Convert 32-bit input to 24-bit output. The image data sizes are
79
the same, hence each line output line will be padded by 25%. Note
80
that this function allocates memory which must be freed by the
83
unsigned char *idi_conv32_24(image, src)
88
unsigned char *dst, *p, *q;
90
unsigned int test = 0x000000ff;
91
unsigned char *ptest = (unsigned char *)&test;
95
if ( *ptest == 0xff ) lend = 1; else lend = 0;
97
/* Allocate a destination image */
98
nbytes = image->bytes_per_line*image->height;
99
dst = malloc((size_t)nbytes);
103
/* Zero the new image data */
105
for (i=0; i<nbytes; i++)
108
for (j=0; j<image->height; j++) {
109
p = src + image->bytes_per_line*j;
110
q = dst + image->bytes_per_line*j;
111
/* Note that for 24-bit data, all we have to do is copy the 3
112
lsb's and discard the msb, while otherwise preserving the byte
115
/* Little-endian - discard msb at end of each source word */
116
for (i=0; i<image->width; i++) {
117
*q++ = *p++; *q++ = *p++; *q++ = *p++;
121
/* Big-endian - discard msb at beginning of each source word */
122
for (i=0; i<image->width; i++) {
124
*q++ = *p++; *q++ = *p++; *q++ = *p++;
135
/* Convert 24-bit input to 32-bit output. The image data sizes are
136
the same, hence each input line must be padded by 25%. Note that
137
this function allocates memory which must be freed by the
140
unsigned char *idi_conv24_32(image, src)
145
unsigned char *dst, *p, *q;
147
unsigned int test = 0x000000ff;
148
unsigned char *ptest = (unsigned char *)&test;
152
/* Test for endian-ness */
153
if ( *ptest == 0xff ) lend = 1; else lend = 0;
155
fprintf(stderr, "%s-endian\n", lend?"little":"big");
156
fprintf(stderr, "red_mask = 0x%08x\n", image->red_mask);
157
fprintf(stderr, "green_mask = 0x%08x\n", image->green_mask);
158
fprintf(stderr, "blue_mask = 0x%08x\n", image->blue_mask);
161
/* Allocate a destination image */
162
nbytes = image->bytes_per_line*image->height;
163
dst = malloc((size_t)nbytes);
167
/* Zero the new image data */
169
for (i=0; i<nbytes; i++)
172
for (j=0; j<image->height; j++) {
173
p = src + image->bytes_per_line*j;
174
q = dst + image->bytes_per_line*j;
175
/* Note that for 24-bit data, all we have to do is copy the 3
176
lsb's and discard the msb, while otherwise preserving the byte
179
/* Little-endian - insert msb at end of each dest word */
180
for (i=0; i<image->width; i++) {
181
*q++ = *p++; *q++ = *p++; *q++ = *p++;
185
/* Big-endian - insert msb at beginning of each dest word */
186
for (i=0; i<image->width; i++) {
188
*q++ = *p++; *q++ = *p++; *q++ = *p++;
199
/* Convert 32-bit input to 16-bit output.
200
The main work is now done in function `wr_lut', here we just
201
convert from unsignded int (4 bytes) to unsigned short int (2 bytes). */
203
unsigned char *idi_conv32_16(image, src, wordsize)
206
unsigned int wordsize;
209
unsigned char *dst, *p, *q;
210
unsigned short int *qi;
212
unsigned int word, nbytes;
216
/* allocate a destination image */
218
nbytes = image->bytes_per_line*image->height;
219
dst = malloc((size_t)nbytes);
220
if (dst == (unsigned char *) 0) return 0;
223
/* copy/convert from source to dest. image */
228
for (j=0; j<image->height; j++)
230
pi = (unsigned int *) p;
231
qi = (unsigned short int *) q;
233
for (i=0; i<image->width; i++)
236
*qi++ = (unsigned short int) word;
238
p += image->bytes_per_line;
239
q += image->bytes_per_line;
248
/* Convert 16-bit input to 32-bit output. The image data sizes are
249
the same, hence each input line must be padded by 50%. Note that
250
this function allocates memory which must be freed by the
251
caller. Also, the conversion from 16-bit to 24-bit assumes that the
252
low-order bits are zero. */
254
unsigned char *idi_conv16_32(image, src, wordsize)
257
unsigned int wordsize;
260
unsigned char *dst, *p, *q;
261
unsigned short int *pi;
264
unsigned char r, g, b;
265
unsigned int rm, gm, bm; /* Red green and blue masks */
266
unsigned int ro, go, bo; /* Red green and blue mask offsets */
267
unsigned short int word;
270
rm = image->red_mask;
271
gm = image->green_mask;
272
bm = image->blue_mask;
273
ro = get_plane_offset(rm, wordsize);
274
go = get_plane_offset(gm, wordsize);
275
bo = get_plane_offset(bm, wordsize);
276
if (ro < 0 || go < 0 || bo < 0)
279
/* Allocate a destination image */
280
nbytes = image->bytes_per_line*image->height;
281
dst = malloc((size_t)nbytes);
285
for (i=0, q=dst; i<nbytes; i++)
288
for (j=0; j<image->height; j++) {
289
p = src + image->bytes_per_line*j;
290
q = dst + image->bytes_per_line*j;
291
pi = (unsigned short int *) p;
292
qi = (unsigned int *) q;
293
/* Note that for 16-bit input data the red element in the 24-bit
294
output data will always be in the LSB, given the way that
295
RGBord is constructed */
297
/* bo must be negative */
298
for (i=0; i<image->width; i++) {
300
r = (word & rm) >> ro;
301
g = (word & gm) >> go;
302
b = (word & bm) << -bo;
303
*qi++ = r | (g << 8) | (b << 16);
306
/* ro must be negative */
307
for (i=0; i<image->width; i++) {
309
r = (word & rm) << -ro;
310
g = (word & gm) >> go;
311
b = (word & bm) >> bo;
312
*qi++ = r | (g << 8) | (b << 16);
323
/* Wrapper for XPutImage. The arguments are identical. This function
324
takes an XImage either in 32-bit truecolor or 8-bit pseudocolor and
325
converts to the appropriate bitsize and depth of the output
326
drawable. No error checking is done on the arguments. */
328
void idi_putimage(display, draw, gc, image, sx, sy, dx, dy, width, height)
334
unsigned int width, height;
337
unsigned char *dst = 0;
338
unsigned char *src = (unsigned char *)image->data;
341
/* Convert from a standard size, either 8-bit or 32-bit, to the
343
switch (image->bits_per_pixel) {
344
/* 32-bit true-color, and 8-bit pseudo color are output immediately */
349
dst = idi_conv32_16(image, src, wordsize); /* 32 bits to 16 bits */
352
dst = idi_conv32_24(image, src); /* 32 bits to 24 bits */
356
/* Temporarily insert the transformed data into the XImage, Put the
357
image, and then restore the original data */
358
if (dst) image->data = (char *) dst;
359
XPutImage(display, draw, gc, image, sx, sy, dx, dy, width, height);
360
image->data = (char *) src;
370
void idi_order32(no,image, src)
378
register unsigned char *p, *q, rr, gg, bb;
382
ii = image->bytes_per_line;
386
/* work on RGBord = 1 */
388
if (Xworkst[no].flag24[2] == 1) /* special swap flag */
390
for (j=0; j<image->height; j++)
394
for (i=0; i<image->width; i++)
413
for (j=0; j<image->height; j++)
417
for (i=0; i<image->width; i++)
438
/* Wrapper for XGetSubImage. The arguments are identical. This
439
function reads an XImage from the drawable, in the native bitsize
440
and depth of the drawable, and then converts to either an 8-bit
441
pseudocolor or 32-bit RGB image. No error checking is done on the
445
*idi_getsubimage(display,draw,x,y,width,height,plane_mask,format,dimage,no)
449
unsigned int width, height;
450
unsigned long plane_mask;
462
/* Do the actual XGetSubImage, which will return in the native
463
depth and bit_per_pixel of the drawable */
466
XGetSubImage(display,draw,x,y,width,height,plane_mask,format,dimage,0,0);
469
/* Convert to a standard size, either 8-bit or 32-bit */
470
switch (image->bits_per_pixel)
472
case 16: /* 16 bits to 32 bits */
473
dst = idi_conv16_32(image,(unsigned char *) image->data, 8);
474
break; /* wordsize = 8 */
476
case 24: /* 24 bits to 32 bits */
477
dst = idi_conv24_32(image,(unsigned char *) image->data);
480
case 8: /* 8-bit pseudo color, nothing to do */
483
case 32: /* 32-bit true-color, reorder */
484
if (Xworkst[no].RGBord == 1)
485
idi_order32(no,image,(unsigned char *) image->data);
492
/* Now copy the "destination" image back into the original "source" */
494
if (dst != (unsigned char *)0)
496
unsigned int nbytes, i;
497
register unsigned char *p, *q;
499
nbytes = image->bytes_per_line * image->height;
501
q = (unsigned char *) image->data;
502
for (i=0; i<nbytes; i++) *q++ = *p++;
513
/* test_swap returns 1, if byte swapping needed, else 0 */
517
/* `test_swap()' is copied from Xtest.c */
521
unsigned char hilo[4];
525
/* find byte order at Xhost */
527
nn = XImageByteOrder(mydisp[ididev[dspno].screen]);
529
nn = 0; /* least signif. byte first */
531
nn = 1; /* most signif. byte first */
534
/* get byte order locally */
536
endian = (int *) &hilo[0];
537
*endian = 0x1256abef;
540
/* the most significant byte (0x12) is stored first,
541
we have a big-endian architecture */
546
/* the most significant byte (0x12) is stored last,
547
we have a little-endian architecture */