~ubuntu-branches/debian/sid/acfax/sid

« back to all changes in this revision

Viewing changes to x_image.c

  • Committer: Bazaar Package Importer
  • Author(s): Hamish Moffatt
  • Date: 2001-12-27 12:07:46 UTC
  • Revision ID: james.westby@ubuntu.com-20011227120746-iz2p5k757bcla8ov
Tags: upstream-981011
ImportĀ upstreamĀ versionĀ 981011

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    ACfax - Fax reception with X11-interface for amateur radio
 
3
    Copyright (C) 1995-1998 Andreas Czechanowski, DL4SDC
 
4
 
 
5
    This program is free software; you can redistribute it and/or modify
 
6
    it under the terms of the GNU General Public License as published by
 
7
    the Free Software Foundation; either version 2 of the License, or
 
8
    (at your option) any later version.
 
9
 
 
10
    This program is distributed in the hope that it will be useful,
 
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
    GNU General Public License for more details.
 
14
 
 
15
    You should have received a copy of the GNU General Public License
 
16
    along with this program; if not, write to the Free Software Foundation,
 
17
    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
18
 
 
19
    andreas.czechanowski@ins.uni-stuttgart.de
 
20
*/
 
21
    
 
22
/*
 
23
 * x_image.c - XImage and colormap allocation functions
 
24
 */
 
25
 
 
26
#include <stdio.h>
 
27
#include <stdlib.h>
 
28
/*
 
29
#include <X11/X.h>
 
30
#include <X11/Xlib.h>
 
31
#include <X11/Intrinsic.h>
 
32
*/
 
33
#include "x_image.h"
 
34
 
 
35
unsigned long   coltab[256];    /* mapping table grayscale->pixel-value */
 
36
char      cused[256];   /* table indicating used pixel-values */
 
37
Display   *dpy = NULL;          /* X-display used */
 
38
Screen    *scrn = NULL;         /* Screen of display */
 
39
Visual    *visl = NULL;         /* Visual of screen to use */
 
40
int       depth = -1;           /* depth of screen (# of planes) */
 
41
Colormap  icmap;                /* the colormap to use */
 
42
XImage    *horimag = NULL;      /* intermediate-storage for horizontal scan */
 
43
XImage    *verimag = NULL;      /* intermediate-storage for vertical scan */
 
44
XVisualInfo visinfo;            /* Visual-info-structure (from Xutil.h) */
 
45
unsigned long r_mask;           /* bit mask bits (truecolor) for red */
 
46
unsigned long g_mask;           /* bit mask bits (truecolor) for green */
 
47
unsigned long b_mask;           /* bit mask bits (truecolor) for blue */
 
48
int       r_shift;              /* position of LSB in r_mask */
 
49
int       g_shift;              /* position of LSB in g_mask */
 
50
int       b_shift;              /* position of LSB in b_mask */
 
51
int       r_bits;               /* count of significant bits in r_mask */
 
52
int       g_bits;               /* count of significant bits in g_mask */
 
53
int       b_bits;               /* count of significant bits in b_mask */
 
54
 
 
55
/*
 
56
 * get some global X11-variables and resources from the passed Widget
 
57
 */
 
58
void get_globals(Widget toplevel)
 
59
{
 
60
  if (!dpy)
 
61
    dpy = XtDisplay(toplevel);
 
62
  if (!scrn)
 
63
    scrn = XtScreen(toplevel);
 
64
  if (depth < 0)
 
65
    depth = DefaultDepthOfScreen(scrn);
 
66
  if (!visl) {
 
67
    visl = DefaultVisualOfScreen(scrn);
 
68
#if 0
 
69
    if (!(XMatchVisualInfo(dpy, XScreenNumberOfScreen(scrn), depth,
 
70
         PseudoColor, &visinfo))) {
 
71
      fprintf(stderr, "cannot get PseudoColor-visual with depth %d !\n", depth);
 
72
      exit(1);
 
73
    }
 
74
    visl = visinfo.visual;
 
75
#endif
 
76
  }
 
77
}
 
78
 
 
79
/*
 
80
 * create two XImages as "transportation storage" between the raw-resulution
 
81
 * picture and the canvas-widget's pixmap (one horizontal stripe with
 
82
 * DEFHEIGHT lines, and one vertical stripe with DEFWIDTH columns).
 
83
 * If called more than once, the old
 
84
 * XImages are Destroyes and new ones are created with the given size.
 
85
 */
 
86
void create_images(Widget toplevel, Dimension wid, Dimension hei)
 
87
{
 
88
  get_globals(toplevel);
 
89
  fprintf(stderr, "creating XImage for %d x %d pixels\n", wid, hei);
 
90
  /* delete old images and their data (when image is resized) */
 
91
  if (horimag)
 
92
    XDestroyImage(horimag);
 
93
  if (verimag)
 
94
    XDestroyImage(verimag);
 
95
  horimag = XCreateImage(dpy, visl, depth, ZPixmap, 0, NULL,
 
96
        wid, DEFHEIGHT, 32, 0);
 
97
  verimag = XCreateImage(dpy, visl, depth, ZPixmap, 0, NULL,
 
98
        DEFWIDTH, hei, 32, 0);
 
99
  if (!(horimag) || !(verimag)) {
 
100
    fprintf(stderr,"cannot allocate Ximages !\n");
 
101
    exit(1);
 
102
  }
 
103
  /* allocate data for the XImages (not done by XCreateImage !) */
 
104
  horimag->data = (char *)XtMalloc(DEFHEIGHT * horimag->bytes_per_line);  
 
105
  verimag->data = (char *)XtMalloc(hei * verimag->bytes_per_line);
 
106
  if (!(horimag->data) || !(verimag->data)) {
 
107
    fprintf(stderr,"cannot allocate space for Ximage !\n");
 
108
    exit(1);
 
109
  }
 
110
}
 
111
 
 
112
/*
 
113
 * free the space allocated by the two XImages
 
114
 */
 
115
void destroy_images(void)
 
116
{
 
117
  if (horimag)
 
118
    XDestroyImage(horimag);
 
119
  if (verimag)
 
120
    XDestroyImage(verimag);
 
121
}
 
122
 
 
123
/*
 
124
 * allocate a new colormap. This is needed for PseudoColor visuals
 
125
 * of depth 8. For truecolor displays, nothing is to be done here.
 
126
 */
 
127
void alloc_cmap(Widget toplevel, Pixel *respix, unsigned nrespix)
 
128
{
 
129
  Colormap rootcmap;
 
130
  XColor col;
 
131
  static int cmap_created = 0;
 
132
  int i;
 
133
  XVisualInfo vTemplate;
 
134
  XVisualInfo *visuals;
 
135
  int nvisuals;
 
136
  unsigned long tmpmask;
 
137
 
 
138
  get_globals(toplevel);
 
139
  switch(visl->class)
 
140
  {
 
141
    case PseudoColor:
 
142
    case StaticColor:
 
143
      rootcmap = DefaultColormapOfScreen(scrn);
 
144
      if (!(cmap_created))
 
145
        icmap = XCreateColormap(dpy, XtWindow(toplevel), visl, AllocAll);
 
146
      cmap_created = 1;
 
147
      /* XAllocColorCells(dpy, icmap, True, planes, 0, pixels, 216); */
 
148
      /* copy the first 16 colors from the root-colormap, and also copy
 
149
         the colors needed for our widgets */
 
150
      for (i=0; i<(1 << depth); i++)
 
151
        cused[i] = 0;
 
152
      for (i=0; i<nrespix; i++)
 
153
      {
 
154
/*
 
155
        fprintf(stderr, "respix[%d] = %u\n", i, (unsigned) respix[i]);
 
156
*/
 
157
        if (respix[i] > ((1 << depth) - 1)) respix[i] = 0;
 
158
        col.pixel = respix[i];
 
159
        cused[respix[i]] = 1;
 
160
        XQueryColor(dpy, rootcmap, &col);
 
161
        XStoreColor(dpy, icmap, &col);
 
162
      }
 
163
     /* now, we can use the rest of the colors for the
 
164
        grayscale or 6x6x6 colormap, but this is done
 
165
        in fill_cmap_col and fill_cmap_gray */
 
166
      break;
 
167
    case TrueColor:
 
168
    case DirectColor:
 
169
      /* we want a visual with the depth of our screen : */
 
170
      vTemplate.screen = XScreenNumberOfScreen(scrn);
 
171
      vTemplate.depth = DefaultDepth(dpy, vTemplate.screen);
 
172
      nvisuals = 0;
 
173
      visuals = XGetVisualInfo(dpy, VisualScreenMask | VisualDepthMask,
 
174
                        &vTemplate, &nvisuals);
 
175
      if (nvisuals < 1)
 
176
      {
 
177
        fprintf(stderr, "cannot find visual matching default depth %d\n",
 
178
                vTemplate.depth);
 
179
        exit(1);
 
180
      }
 
181
      /* copy first visual info to own location */
 
182
      visinfo = visuals[0];
 
183
      /* discard the array from XGetVisualInfo() */
 
184
      XFree(visuals);
 
185
 
 
186
      /* determine the bit positions and count of significant bits
 
187
       * for red, green and blue, store it in *_shift and *_bits */
 
188
      r_mask = visinfo.red_mask;
 
189
      g_mask = visinfo.green_mask;
 
190
      b_mask = visinfo.blue_mask;
 
191
      if (r_mask == 0 || g_mask == 0 || b_mask == 0)
 
192
      {
 
193
        fprintf(stderr, "one of the color masks is zero : %08lx %08lx %08lx\n",
 
194
                r_mask, g_mask, b_mask);
 
195
        exit(1);
 
196
      }
 
197
 
 
198
      /* determine number of bits and position of mask for every color */
 
199
      r_shift = g_shift = b_shift = 0;
 
200
      r_bits = g_bits = b_bits = 0;
 
201
 
 
202
      tmpmask = r_mask;
 
203
      while ((tmpmask & 1) == 0)
 
204
      {
 
205
        tmpmask >>= 1;
 
206
        r_shift++;
 
207
      }
 
208
      while ((tmpmask & 1) == 1)
 
209
      {
 
210
        tmpmask >>= 1;
 
211
        r_bits++;
 
212
      }
 
213
 
 
214
      tmpmask = g_mask;
 
215
      while ((tmpmask & 1) == 0)
 
216
      {
 
217
        tmpmask >>= 1;
 
218
        g_shift++;
 
219
      }
 
220
      while ((tmpmask & 1) == 1)
 
221
      {
 
222
        tmpmask >>= 1;
 
223
        g_bits++;
 
224
      }
 
225
 
 
226
      tmpmask = b_mask;
 
227
      while ((tmpmask & 1) == 0)
 
228
      {
 
229
        tmpmask >>= 1;
 
230
        b_shift++;
 
231
      }
 
232
      while ((tmpmask & 1) == 1)
 
233
      {
 
234
        tmpmask >>= 1;
 
235
        b_bits++;
 
236
      }
 
237
      break;
 
238
    case StaticGray:
 
239
      fprintf (stderr, "Cannot handle StaticGray visual - abort\n");
 
240
      exit(1);
 
241
      /*NOTREACHED*/
 
242
    case GrayScale:
 
243
      fprintf (stderr, "Cannot handle GrayScale visual - abort\n");
 
244
      exit(1);
 
245
      /*NOTREACHED*/
 
246
    default:
 
247
      fprintf (stderr, "unknown visual type %x - abort\n", visl->class);
 
248
      exit(1);
 
249
      /*NOTREACHED*/
 
250
  }
 
251
}
 
252
 
 
253
/*
 
254
 * fill the colormap with a 6x6x6 color-cube.
 
255
 * when flip is set, the green and blue indexing is exchanged, and rotate
 
256
 * defines the order in which the colors are indexed.
 
257
 * The array coltab is filled with a lookup-table color_value -> pixel_index.
 
258
 */
 
259
void fill_cmap_col(int invert, int flip, int rotate)
 
260
{
 
261
  int cm[3];
 
262
  unsigned ixr, ixg, ixb;
 
263
  XColor col;
 
264
  int i = 0;
 
265
 
 
266
  fprintf(stderr, "filling colormap with 6x6x6 cube\n");
 
267
  col.flags = DoRed | DoGreen | DoBlue;
 
268
  switch(rotate) {
 
269
    case 1:
 
270
      ixr = 1;
 
271
      ixg = (flip) ? 0 : 2;
 
272
      ixb = (flip) ? 2 : 0;
 
273
      break;
 
274
    case 2:
 
275
      ixr = 2;
 
276
      ixg = (flip) ? 1 : 0;
 
277
      ixb = (flip) ? 0 : 1;
 
278
      break;
 
279
    case 0:
 
280
    default:
 
281
      ixr = 0;
 
282
      ixg = (flip) ? 2 : 1;
 
283
      ixb = (flip) ? 1 : 2;
 
284
      break;
 
285
  }
 
286
  for (cm[0]=0; cm[0]<6; cm[0]++)
 
287
    for (cm[1]=0; cm[1]<6; cm[1]++)
 
288
      for (cm[2]=0; cm[2]<6; cm[2]++) {
 
289
        while ((cused[i]) && i < 256) i++;
 
290
        if (i == 256) {
 
291
          fprintf(stderr,"cannot assign all required colors !\n");
 
292
          break;
 
293
        }
 
294
        col.pixel = i;
 
295
        if (invert) {
 
296
          col.red =   65535 - 9362 * (cm[ixr] + 1);
 
297
          col.green = 65535 - 9362 * (cm[ixg] + 1);
 
298
          col.blue =  65535 - 9362 * (cm[ixb] + 1);
 
299
        } else {
 
300
          col.red =   9362 * (cm[ixr] + 1);
 
301
          col.green = 9362 * (cm[ixg] + 1);
 
302
          col.blue =  9362 * (cm[ixb] + 1);
 
303
        }
 
304
        XStoreColor(dpy, icmap, &col);
 
305
        coltab[cm[0]+6*cm[1]+36*cm[2]] = i;
 
306
        i++;
 
307
  }
 
308
}
 
309
 
 
310
/*
 
311
 * fill the colormap with a grayscale of 64 steps (should be good enough).
 
312
 * The array coltab is filled with a lookup-table gray_value -> pixel_index.
 
313
 */
 
314
void fill_cmap_gray(int invert)
 
315
{
 
316
  int g, yv;
 
317
  XColor col;
 
318
  int i = 0;
 
319
  unsigned long cval;
 
320
 
 
321
  fprintf(stderr, "filling colormap with grayscale\n");
 
322
  switch (visl->class)
 
323
  {
 
324
    case StaticColor:
 
325
    case PseudoColor:
 
326
      col.flags = DoRed | DoGreen | DoBlue;
 
327
      for (g=0; g<64; g++)
 
328
      {
 
329
        while ((cused[i]) && i < 256) i++;
 
330
        if (i == 256)
 
331
        {
 
332
          fprintf(stderr,"cannot assign all required grayscales !\n");
 
333
          break;
 
334
        }
 
335
        col.pixel = i;
 
336
        yv = (invert) ? 63 - g : g;
 
337
        col.red = col.green = col.blue = 1040.2 * yv;
 
338
        XStoreColor(dpy, icmap, &col);
 
339
        coltab[g] = i;
 
340
        i++;
 
341
      }
 
342
      break;
 
343
    case TrueColor:
 
344
    case DirectColor:
 
345
      /* allocate a translation table grayscale -> truecolor_value */
 
346
      for (g=0; g<64; g++)
 
347
      {
 
348
        yv = (invert) ? 63 - g : g;
 
349
        cval = (((1 << r_bits) - 1) * yv / 63) << r_shift;
 
350
        cval += (((1 << g_bits) - 1) * yv / 63) << g_shift;
 
351
        cval += (((1 << b_bits) - 1) * yv / 63) << b_shift;
 
352
        coltab[g] = cval;
 
353
      }
 
354
      break;
 
355
  }
 
356
}