checked in minirgb stuff + webcam grabber
[my-code/ivac.git] / minirgb.c
1 /* minirgb -- simple rgb buffer drawing library for 16, 24 and 32 bit displays
2  * Copyright (C) 2000 timecop@japan.co.jp
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
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.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  */
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <X11/Xlib.h>
21 #include <X11/Xutil.h>
22 #include "minirgb.h"
23
24 #undef  MAX
25 #define MAX(a, b)  (((a) > (b)) ? (a) : (b))
26
27 /* local variables */
28 Display *minirgb_display;                       /* display */
29 Visual  *minirgb_visual;                        /* visual */
30 int     minirgb_depth;                          /* display depth */
31 int     minirgb_ok = 0;                         /* init ok? */
32
33 /* local prototypes */
34 static __inline void rgb_conv_16(unsigned char *ptr, unsigned char r, unsigned char g, unsigned char b, XImage *image);
35 static __inline void rgb_conv_24(unsigned char *ptr, unsigned char r, unsigned char g, unsigned char b, XImage *image);
36 static __inline void rgb_conv_32(unsigned char *ptr, unsigned char r, unsigned char g, unsigned char b, XImage *image);
37
38 static __inline void rgb_conv_16(unsigned char *ptr, unsigned char r, unsigned char g, unsigned char b, XImage *image)
39 {
40     if (image->green_mask & 0x7e0) /* 565 */
41         *(unsigned short int *)ptr = ((r >> 3) << 11) |
42                                      ((g >> 2) << 5) |
43                                      (b >> 3);
44     else /* 555 untested */
45         *(unsigned short int *)ptr = ((r >> 3) << 11) |
46                                      ((g >> 3) << 6) |
47                                      (b >> 3);
48 }
49
50 static __inline void rgb_conv_24(unsigned char *ptr, unsigned char r, unsigned char g, unsigned char b, XImage *image)
51 {
52     /* untested */
53     *ptr++ = r;
54     *ptr++ = g;
55     *ptr = b;
56 }
57
58 static __inline void rgb_conv_32(unsigned char *ptr, unsigned char r, unsigned char g, unsigned char b, XImage *image)
59 {
60     if (image->red_mask & 0xff0000)  /* 0888 */
61         *(unsigned int *)ptr = (r << 16) |
62                                (g << 8) |
63                                (b);
64     else /* 8880 untested */
65         *(unsigned int *)ptr = (r << 24) |
66                                (g << 16) |
67                                (b << 8);
68 }
69
70 int minirgb_init(Display *d)
71 {
72     int screen;
73
74     minirgb_display = d;
75     screen = DefaultScreen(minirgb_display);
76     minirgb_visual = XDefaultVisual(minirgb_display, screen);
77     minirgb_depth = XDefaultDepth(minirgb_display, screen);
78     if (minirgb_depth <= 8) {
79         fprintf(stderr, "minirgb: No support for 8 bit displays\n");
80         minirgb_ok = 0;
81         return 1;
82     } else {
83         minirgb_ok = 1;
84         return 0;
85     }
86 }
87
88 void minirgb_setpixel(MiniRGB *rgb_image, unsigned char *color, unsigned int x, unsigned int y)
89 {
90     unsigned char *ptr;
91
92     ptr = rgb_image->mem + (y * rgb_image->rowstride * 3) + (x * 3);
93     *ptr++ = *color++;
94     *ptr++ = *color++;
95     *ptr = *color;
96 }
97
98 void minirgb_copy(MiniRGB *from, MiniRGB *to,
99         unsigned int sx, unsigned int sy, unsigned int w, unsigned int h,
100         unsigned int dx, unsigned int dy)
101 {
102     unsigned int i;
103     unsigned char *src, *dest;
104
105 #ifdef VERBOSE
106     fprintf(stderr, "minirgb: copy %d, %d (%dx%d) -> %d, %d)\n", sx, sy, w, h, dx, dy);
107 #endif
108
109 #if 0
110     if (w == 1) { /* special case - dot operations */
111         src = from->mem + (sy * from->rowstride * 3) + sx * 3;
112         dest = to->mem + (dy * to->rowstride * 3) + dx * 3;
113         dest[0] = dest[0] & src[0];
114         dest[1] = dest[1] & src[1];
115         dest[2] = dest[2] & src[2];
116         return;
117     }
118 #endif
119
120     for (i = 0; i < h; i++) {
121         src = from->mem + ((sy + i) * from->rowstride * 3) + sx * 3;
122         dest = to->mem + ((dy + i) * to->rowstride * 3) + dx * 3;
123         memcpy(dest, src, w * 3);
124     }
125 }
126
127 void minirgb_new(MiniRGB *image, unsigned int width, unsigned int height)
128 {
129     image->width = width;
130     image->height = height;
131     image->rowstride = width;
132     image->mem = calloc(1, width * height * 3);
133 }
134
135 void minirgb_draw(Window drawable, GC gc, int x, int y, int width,
136                        int height, MiniRGB *rgb_image)
137 {
138     XImage *image = NULL;
139     unsigned int bpp;
140     unsigned int x0, y0;
141     unsigned char *ptr, *col;
142     void (*conv) (unsigned char *, unsigned char, unsigned char, unsigned char, XImage *) = NULL;
143
144     if (!minirgb_ok)
145         return;
146
147     image = XCreateImage(minirgb_display, minirgb_visual, minirgb_depth, ZPixmap, 0, 0, width, height, 32, 0);
148     bpp = (image->bits_per_pixel + 7) / 8;
149     switch (bpp) {
150         case 2:
151             conv = rgb_conv_16;
152             break;
153         case 3:
154             conv = rgb_conv_24;
155             break;
156         case 4:
157             conv = rgb_conv_32;
158             break;
159     }
160 #ifdef VERBOSE
161     printf("minirgb: image %p %dx%d (bpp: %d, bpl: %d)\n", image, width, height, bpp, image->bytes_per_line);
162 #endif 
163     image->data = malloc(image->bytes_per_line * height);
164     if (!image->data) {
165         fprintf(stderr, "minirgb: allocation error\n");
166         XDestroyImage(image);
167         return;
168     }
169
170     for (y0 = 0; y0 < height; y0++) {
171         for (x0 = 0; x0 < width; x0++) {
172             col = rgb_image->mem + (y0 * rgb_image->rowstride * 3 + x0 * 3);
173             ptr = image->data + (y0 * image->bytes_per_line + x0 * bpp);
174             conv(ptr, col[0], col[1], col[2], image);
175         }
176     }
177     /* draw image onto drawable */
178     XPutImage(minirgb_display, drawable, gc, image, 0, 0, x, y, width, height);
179     XDestroyImage(image);
180 }