File: x_image.c

package info (click to toggle)
acfax 981011-17
  • links: PTS
  • area: main
  • in suites: bullseye, buster, jessie, jessie-kfreebsd, sid, stretch
  • size: 672 kB
  • sloc: ansic: 5,502; makefile: 36
file content (356 lines) | stat: -rw-r--r-- 10,320 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
/*
    ACfax - Fax reception with X11-interface for amateur radio
    Copyright (C) 1995-1998 Andreas Czechanowski, DL4SDC

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software Foundation,
    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

    andreas.czechanowski@ins.uni-stuttgart.de
*/
    
/*
 * x_image.c - XImage and colormap allocation functions
 */

#include <stdio.h>
#include <stdlib.h>
/*
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Intrinsic.h>
*/
#include "x_image.h"

unsigned long	coltab[256];	/* mapping table grayscale->pixel-value */
char	  cused[256];	/* table indicating used pixel-values */
Display	  *dpy = NULL;		/* X-display used */
Screen	  *scrn = NULL;		/* Screen of display */
Visual	  *visl = NULL;		/* Visual of screen to use */
int	  depth = -1;		/* depth of screen (# of planes) */
Colormap  icmap;		/* the colormap to use */
XImage	  *horimag = NULL;	/* intermediate-storage for horizontal scan */
XImage	  *verimag = NULL;	/* intermediate-storage for vertical scan */
XVisualInfo visinfo;		/* Visual-info-structure (from Xutil.h) */
unsigned long r_mask;		/* bit mask bits (truecolor) for red */
unsigned long g_mask;		/* bit mask bits (truecolor) for green */
unsigned long b_mask;		/* bit mask bits (truecolor) for blue */
int	  r_shift;		/* position of LSB in r_mask */
int	  g_shift;		/* position of LSB in g_mask */
int	  b_shift;		/* position of LSB in b_mask */
int	  r_bits;		/* count of significant bits in r_mask */
int	  g_bits;		/* count of significant bits in g_mask */
int	  b_bits;		/* count of significant bits in b_mask */

/*
 * get some global X11-variables and resources from the passed Widget
 */
void get_globals(Widget toplevel)
{
  if (!dpy)
    dpy = XtDisplay(toplevel);
  if (!scrn)
    scrn = XtScreen(toplevel);
  if (depth < 0)
    depth = DefaultDepthOfScreen(scrn);
  if (!visl) {
    visl = DefaultVisualOfScreen(scrn);
#if 0
    if (!(XMatchVisualInfo(dpy, XScreenNumberOfScreen(scrn), depth,
	 PseudoColor, &visinfo))) {
      fprintf(stderr, "cannot get PseudoColor-visual with depth %d !\n", depth);
      exit(1);
    }
    visl = visinfo.visual;
#endif
  }
}

/*
 * create two XImages as "transportation storage" between the raw-resulution
 * picture and the canvas-widget's pixmap (one horizontal stripe with
 * DEFHEIGHT lines, and one vertical stripe with DEFWIDTH columns).
 * If called more than once, the old
 * XImages are Destroyes and new ones are created with the given size.
 */
void create_images(Widget toplevel, Dimension wid, Dimension hei)
{
  get_globals(toplevel);
  fprintf(stderr, "creating XImage for %d x %d pixels\n", wid, hei);
  /* delete old images and their data (when image is resized) */
  if (horimag)
    XDestroyImage(horimag);
  if (verimag)
    XDestroyImage(verimag);
  horimag = XCreateImage(dpy, visl, depth, ZPixmap, 0, NULL,
        wid, DEFHEIGHT, 32, 0);
  verimag = XCreateImage(dpy, visl, depth, ZPixmap, 0, NULL,
        DEFWIDTH, hei, 32, 0);
  if (!(horimag) || !(verimag)) {
    fprintf(stderr,"cannot allocate Ximages !\n");
    exit(1);
  }
  /* allocate data for the XImages (not done by XCreateImage !) */
  horimag->data = (char *)XtMalloc(DEFHEIGHT * horimag->bytes_per_line);  
  verimag->data = (char *)XtMalloc(hei * verimag->bytes_per_line);
  if (!(horimag->data) || !(verimag->data)) {
    fprintf(stderr,"cannot allocate space for Ximage !\n");
    exit(1);
  }
}

/*
 * free the space allocated by the two XImages
 */
void destroy_images(void)
{
  if (horimag)
    XDestroyImage(horimag);
  if (verimag)
    XDestroyImage(verimag);
}

/*
 * allocate a new colormap. This is needed for PseudoColor visuals
 * of depth 8. For truecolor displays, nothing is to be done here.
 */
void alloc_cmap(Widget toplevel, Pixel *respix, unsigned nrespix)
{
  Colormap rootcmap;
  XColor col;
  static int cmap_created = 0;
  int i;
  XVisualInfo vTemplate;
  XVisualInfo *visuals;
  int nvisuals;
  unsigned long tmpmask;

  get_globals(toplevel);
  switch(visl->class)
  {
    case PseudoColor:
    case StaticColor:
      rootcmap = DefaultColormapOfScreen(scrn);
      if (!(cmap_created))
	icmap = XCreateColormap(dpy, XtWindow(toplevel), visl, AllocAll);
      cmap_created = 1;
      /* XAllocColorCells(dpy, icmap, True, planes, 0, pixels, 216); */
      /* copy the first 16 colors from the root-colormap, and also copy
	 the colors needed for our widgets */
      for (i=0; i<(1 << depth); i++)
	cused[i] = 0;
      for (i=0; i<nrespix; i++)
      {
/*
	fprintf(stderr, "respix[%d] = %u\n", i, (unsigned) respix[i]);
*/
	if (respix[i] > ((1 << depth) - 1)) respix[i] = 0;
	col.pixel = respix[i];
	cused[respix[i]] = 1;
	XQueryColor(dpy, rootcmap, &col);
	XStoreColor(dpy, icmap, &col);
      }
     /* now, we can use the rest of the colors for the
        grayscale or 6x6x6 colormap, but this is done
        in fill_cmap_col and fill_cmap_gray */
      break;
    case TrueColor:
    case DirectColor:
      /* we want a visual with the depth of our screen : */
      vTemplate.screen = XScreenNumberOfScreen(scrn);
      vTemplate.depth = DefaultDepth(dpy, vTemplate.screen);
      nvisuals = 0;
      visuals = XGetVisualInfo(dpy, VisualScreenMask | VisualDepthMask,
			&vTemplate, &nvisuals);
      if (nvisuals < 1)
      {
	fprintf(stderr, "cannot find visual matching default depth %d\n",
		vTemplate.depth);
	exit(1);
      }
      /* copy first visual info to own location */
      visinfo = visuals[0];
      /* discard the array from XGetVisualInfo() */
      XFree(visuals);

      /* determine the bit positions and count of significant bits
       * for red, green and blue, store it in *_shift and *_bits */
      r_mask = visinfo.red_mask;
      g_mask = visinfo.green_mask;
      b_mask = visinfo.blue_mask;
      if (r_mask == 0 || g_mask == 0 || b_mask == 0)
      {
	fprintf(stderr, "one of the color masks is zero : %08lx %08lx %08lx\n",
		r_mask, g_mask, b_mask);
	exit(1);
      }

      /* determine number of bits and position of mask for every color */
      r_shift = g_shift = b_shift = 0;
      r_bits = g_bits = b_bits = 0;

      tmpmask = r_mask;
      while ((tmpmask & 1) == 0)
      {
	tmpmask >>= 1;
	r_shift++;
      }
      while ((tmpmask & 1) == 1)
      {
	tmpmask >>= 1;
	r_bits++;
      }

      tmpmask = g_mask;
      while ((tmpmask & 1) == 0)
      {
	tmpmask >>= 1;
	g_shift++;
      }
      while ((tmpmask & 1) == 1)
      {
	tmpmask >>= 1;
	g_bits++;
      }

      tmpmask = b_mask;
      while ((tmpmask & 1) == 0)
      {
	tmpmask >>= 1;
	b_shift++;
      }
      while ((tmpmask & 1) == 1)
      {
	tmpmask >>= 1;
	b_bits++;
      }
      break;
    case StaticGray:
      fprintf (stderr, "Cannot handle StaticGray visual - abort\n");
      exit(1);
      /*NOTREACHED*/
    case GrayScale:
      fprintf (stderr, "Cannot handle GrayScale visual - abort\n");
      exit(1);
      /*NOTREACHED*/
    default:
      fprintf (stderr, "unknown visual type %x - abort\n", visl->class);
      exit(1);
      /*NOTREACHED*/
  }
}

/*
 * fill the colormap with a 6x6x6 color-cube.
 * when flip is set, the green and blue indexing is exchanged, and rotate
 * defines the order in which the colors are indexed.
 * The array coltab is filled with a lookup-table color_value -> pixel_index.
 */
void fill_cmap_col(int invert, int flip, int rotate)
{
  int cm[3];
  unsigned ixr, ixg, ixb;
  XColor col;
  int i = 0;

  fprintf(stderr, "filling colormap with 6x6x6 cube\n");
  col.flags = DoRed | DoGreen | DoBlue;
  switch(rotate) {
    case 1:
      ixr = 1;
      ixg = (flip) ? 0 : 2;
      ixb = (flip) ? 2 : 0;
      break;
    case 2:
      ixr = 2;
      ixg = (flip) ? 1 : 0;
      ixb = (flip) ? 0 : 1;
      break;
    case 0:
    default:
      ixr = 0;
      ixg = (flip) ? 2 : 1;
      ixb = (flip) ? 1 : 2;
      break;
  }
  for (cm[0]=0; cm[0]<6; cm[0]++)
    for (cm[1]=0; cm[1]<6; cm[1]++)
      for (cm[2]=0; cm[2]<6; cm[2]++) {
        while ((cused[i]) && i < 256) i++;
        if (i == 256) {
          fprintf(stderr,"cannot assign all required colors !\n");
          break;
        }
        col.pixel = i;
        if (invert) {
          col.red =   65535 - 9362 * (cm[ixr] + 1);
          col.green = 65535 - 9362 * (cm[ixg] + 1);
          col.blue =  65535 - 9362 * (cm[ixb] + 1);
        } else {
          col.red =   9362 * (cm[ixr] + 1);
          col.green = 9362 * (cm[ixg] + 1);
          col.blue =  9362 * (cm[ixb] + 1);
        }
        XStoreColor(dpy, icmap, &col);
        coltab[cm[0]+6*cm[1]+36*cm[2]] = i;
        i++;
  }
}

/*
 * fill the colormap with a grayscale of 64 steps (should be good enough).
 * The array coltab is filled with a lookup-table gray_value -> pixel_index.
 */
void fill_cmap_gray(int invert)
{
  int g, yv;
  XColor col;
  int i = 0;
  unsigned long cval;
 
  fprintf(stderr, "filling colormap with grayscale\n");
  switch (visl->class)
  {
    case StaticColor:
    case PseudoColor:
      col.flags = DoRed | DoGreen | DoBlue;
      for (g=0; g<64; g++)
      {
	while ((cused[i]) && i < 256) i++;
	if (i == 256)
	{
          fprintf(stderr,"cannot assign all required grayscales !\n");
          break;
	}
	col.pixel = i;
	yv = (invert) ? 63 - g : g;
	col.red = col.green = col.blue = 1040.2 * yv;
	XStoreColor(dpy, icmap, &col);
	coltab[g] = i;
	i++;
      }
      break;
    case TrueColor:
    case DirectColor:
      /* allocate a translation table grayscale -> truecolor_value */
      for (g=0; g<64; g++)
      {
	yv = (invert) ? 63 - g : g;
	cval = (((1 << r_bits) - 1) * yv / 63) << r_shift;
	cval += (((1 << g_bits) - 1) * yv / 63) << g_shift;
	cval += (((1 << b_bits) - 1) * yv / 63) << b_shift;
	coltab[g] = cval;
      }
      break;
  }
}