1 /* $Id: image.c,v 1.19 1997/11/07 03:49:04 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 2.5
6 * Copyright (C) 1995-1997 Brian Paul
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the Free
20 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23
24 /*
25 * $Log: image.c,v $
26 * Revision 1.19 1997/11/07 03:49:04 brianp
27 * more error checking work (but more to be done)
28 *
29 * Revision 1.18 1997/11/02 20:19:47 brianp
30 * added more error checking to gl_unpack_image3D()
31 *
32 * Revision 1.17 1997/10/16 01:04:51 brianp
33 * added code to normalize color, depth values in gl_unpack_image3d()
34 *
35 * Revision 1.16 1997/09/27 00:15:39 brianp
36 * changed parameters to gl_unpack_image()
37 *
38 * Revision 1.15 1997/08/11 01:23:10 brianp
39 * added a pointer cast
40 *
41 * Revision 1.14 1997/07/24 01:25:18 brianp
42 * changed precompiled header symbol from PCH to PC_HEADER
43 *
44 * Revision 1.13 1997/05/28 03:25:26 brianp
45 * added precompiled header (PCH) support
46 *
47 * Revision 1.12 1997/04/29 01:26:25 brianp
48 * added #include "context.h"
49 *
50 * Revision 1.11 1997/04/20 20:28:49 brianp
51 * replaced abort() with gl_problem()
52 *
53 * Revision 1.10 1997/04/06 17:49:32 brianp
54 * image reference count wasn't always initialized to zero (Christopher Lloyd)
55 *
56 * Revision 1.9 1997/02/09 20:05:03 brianp
57 * new arguments for gl_pixel_addr_in_image()
58 *
59 * Revision 1.8 1997/02/09 18:52:53 brianp
60 * added GL_EXT_texture3D support
61 *
62 * Revision 1.7 1997/01/09 21:25:54 brianp
63 * initialize image reference count to zero
64 *
65 * Revision 1.6 1996/11/13 03:58:31 brianp
66 * fixed undefined "format" variable in gl_unpack_image()
67 *
68 * Revision 1.5 1996/11/10 17:48:03 brianp
69 * check if format is GL_DEPTH_COMPONENT or GL_STENCIL_COMPONENT
70 *
71 * Revision 1.4 1996/11/06 04:23:01 brianp
72 * changed gl_unpack_image() components argument to srcFormat
73 *
74 * Revision 1.3 1996/09/27 01:27:10 brianp
75 * removed unused variables
76 *
77 * Revision 1.2 1996/09/26 22:35:10 brianp
78 * fixed a few compiler warnings from IRIX 6 -n32 and -64 compiler
79 *
80 * Revision 1.1 1996/09/13 01:38:16 brianp
81 * Initial revision
82 *
83 */
84
85
86 #ifdef PC_HEADER
87 #include "all.h"
88 #else
89 #include <assert.h>
90 #include <stdio.h>
91 #include <stdlib.h>
92 #include <string.h>
93 #include "context.h"
94 #include "image.h"
95 #include "macros.h"
96 #include "pixel.h"
97 #include "types.h"
98 #endif
99
100
101
102 /*
103 * Flip the 8 bits in each byte of the given array.
104 */
gl_flip_bytes(GLubyte * p,GLuint n)105 void gl_flip_bytes( GLubyte *p, GLuint n )
106 {
107 register GLuint i, a, b;
108
109 for (i=0;i<n;i++) {
110 b = (GLuint) p[i];
111 a = ((b & 0x01) << 7) |
112 ((b & 0x02) << 5) |
113 ((b & 0x04) << 3) |
114 ((b & 0x08) << 1) |
115 ((b & 0x10) >> 1) |
116 ((b & 0x20) >> 3) |
117 ((b & 0x40) >> 5) |
118 ((b & 0x80) >> 7);
119 p[i] = (GLubyte) a;
120 }
121 }
122
123
124 /*
125 * Flip the order of the 2 bytes in each word in the given array.
126 */
gl_swap2(GLushort * p,GLuint n)127 void gl_swap2( GLushort *p, GLuint n )
128 {
129 register GLuint i;
130
131 for (i=0;i<n;i++) {
132 p[i] = (p[i] >> 8) | ((p[i] << 8) & 0xff00);
133 }
134 }
135
136
137
138 /*
139 * Flip the order of the 4 bytes in each word in the given array.
140 */
gl_swap4(GLuint * p,GLuint n)141 void gl_swap4( GLuint *p, GLuint n )
142 {
143 register GLuint i, a, b;
144
145 for (i=0;i<n;i++) {
146 b = p[i];
147 a = (b >> 24)
148 | ((b >> 8) & 0xff00)
149 | ((b << 8) & 0xff0000)
150 | ((b << 24) & 0xff000000);
151 p[i] = a;
152 }
153 }
154
155
156
157
158 /*
159 * Return the size, in bytes, of the given GL datatype.
160 * Return 0 if GL_BITMAP.
161 * Return -1 if invalid type enum.
162 */
gl_sizeof_type(GLenum type)163 GLint gl_sizeof_type( GLenum type )
164 {
165 switch (type) {
166 case GL_BITMAP:
167 return 0;
168 case GL_UNSIGNED_BYTE:
169 return sizeof(GLubyte);
170 case GL_BYTE:
171 return sizeof(GLbyte);
172 case GL_UNSIGNED_SHORT:
173 return sizeof(GLushort);
174 case GL_SHORT:
175 return sizeof(GLshort);
176 case GL_UNSIGNED_INT:
177 return sizeof(GLuint);
178 case GL_INT:
179 return sizeof(GLint);
180 case GL_FLOAT:
181 return sizeof(GLfloat);
182 default:
183 return -1;
184 }
185 }
186
187
188
189 /*
190 * Return the number of components in a GL enum pixel type.
191 * Return -1 if bad format.
192 */
gl_components_in_format(GLenum format)193 GLint gl_components_in_format( GLenum format )
194 {
195 switch (format) {
196 case GL_COLOR_INDEX:
197 case GL_STENCIL_INDEX:
198 case GL_DEPTH_COMPONENT:
199 case GL_RED:
200 case GL_GREEN:
201 case GL_BLUE:
202 case GL_ALPHA:
203 case GL_LUMINANCE:
204 return 1;
205 case GL_LUMINANCE_ALPHA:
206 return 2;
207 case GL_RGB:
208 case GL_BGR_EXT:
209 return 3;
210 case GL_RGBA:
211 case GL_BGRA_EXT:
212 return 4;
213 default:
214 return -1;
215 }
216 }
217
218
219 /*
220 * Return the address of a pixel in an image (actually a volume).
221 * Pixel unpacking/packing parameters are observed according to 'packing'.
222 * Input: image - start of image data
223 * width, height - size of image
224 * format - image format
225 * type - pixel component type
226 * packing - GL_TRUE = use packing params
227 * GL_FALSE = use unpacking params.
228 * img - which image in the volume (0 for 2-D images)
229 * row, column - location of pixel in the image
230 * Return: address of pixel at (image,row,column) in image or NULL if error.
231 */
gl_pixel_addr_in_image(struct gl_pixelstore_attrib * packing,const GLvoid * image,GLsizei width,GLsizei height,GLenum format,GLenum type,GLint row)232 GLvoid *gl_pixel_addr_in_image( struct gl_pixelstore_attrib *packing,
233 const GLvoid *image, GLsizei width,
234 GLsizei height, GLenum format, GLenum type,
235 GLint row)
236 {
237 GLint bytes_per_comp; /* bytes per component */
238 GLint comp_per_pixel; /* components per pixel */
239 GLint comps_per_row; /* components per row */
240 GLint pixels_per_row; /* pixels per row */
241 GLint alignment; /* 1, 2 or 4 */
242 GLint skiprows;
243 GLint skippixels;
244 GLubyte *pixel_addr;
245
246 /* Compute bytes per component */
247 bytes_per_comp = gl_sizeof_type( type );
248 if (bytes_per_comp<0) {
249 return NULL;
250 }
251
252 /* Compute number of components per pixel */
253 comp_per_pixel = gl_components_in_format( format );
254 if (comp_per_pixel<0) {
255 return NULL;
256 }
257
258 alignment = packing->Alignment;
259 if (packing->RowLength>0) {
260 pixels_per_row = packing->RowLength;
261 }
262 else {
263 pixels_per_row = width;
264 }
265 skiprows = packing->SkipRows;
266 skippixels = packing->SkipPixels;
267
268 if (type==GL_BITMAP) {
269 /* BITMAP data */
270 GLint bytes_per_row;
271
272 bytes_per_row = alignment
273 * CEILING( comp_per_pixel*pixels_per_row, 8*alignment );
274
275 pixel_addr = (GLubyte *) image
276 + (skiprows + row) * bytes_per_row
277 + (skippixels) / 8;
278 }
279 else {
280 /* Non-BITMAP data */
281
282 if (bytes_per_comp>=alignment) {
283 comps_per_row = comp_per_pixel * pixels_per_row;
284 }
285 else {
286 GLint bytes_per_row = bytes_per_comp * comp_per_pixel
287 * pixels_per_row;
288
289 comps_per_row = alignment / bytes_per_comp
290 * CEILING( bytes_per_row, alignment );
291 }
292
293 /* Copy/unpack pixel data to buffer */
294 pixel_addr = (GLubyte *) image
295 + (skiprows + row) * bytes_per_comp * comps_per_row
296 + (skippixels) * bytes_per_comp * comp_per_pixel;
297 }
298
299 return (GLvoid *) pixel_addr;
300 }
301
302
303
304 /*
305 * Unpack a 2-D image from user-supplied address, returning a pointer to
306 * a new gl_image struct.
307 *
308 * Input: width, height - size in pixels
309 * srcFormat - format of incoming pixel data, ignored if
310 * srcType BITMAP.
311 * srcType - GL_UNSIGNED_BYTE .. GL_FLOAT
312 * pixels - pointer to unpacked image in client memory space.
313 */
gl_unpack_image(GLcontext * ctx,GLint width,GLint height,GLenum srcFormat,GLenum srcType,const GLvoid * pixels)314 struct gl_image *gl_unpack_image( GLcontext *ctx,
315 GLint width, GLint height,
316 GLenum srcFormat, GLenum srcType,
317 const GLvoid *pixels )
318 {
319 GLint components;
320 GLenum destType;
321
322 if (srcType==GL_UNSIGNED_BYTE) {
323 destType = GL_UNSIGNED_BYTE;
324 }
325 else if (srcType==GL_BITMAP) {
326 destType = GL_BITMAP;
327 }
328 else {
329 destType = GL_FLOAT;
330 }
331
332 components = gl_components_in_format( srcFormat );
333
334 if (components < 0)
335 return NULL;
336
337 if (srcType==GL_BITMAP || destType==GL_BITMAP) {
338 struct gl_image *image;
339 GLint bytes, i, width_in_bytes;
340 GLubyte *buffer, *dst;
341 assert( srcType==GL_BITMAP );
342 assert( destType==GL_BITMAP );
343
344 /* Alloc dest storage */
345 if (width > 0 && height > 0)
346 bytes = ((width+7)/8 * height);
347 else
348 bytes = 0;
349 if (bytes>0 && pixels!=NULL) {
350 buffer = (GLubyte *) malloc( bytes );
351 if (!buffer) {
352 return NULL;
353 }
354 /* Copy/unpack pixel data to buffer */
355 width_in_bytes = CEILING( width, 8 );
356 dst = buffer;
357 for (i=0; i<height; i++) {
358 GLvoid *src = gl_pixel_addr_in_image( &ctx->Unpack, pixels,
359 width, height,
360 GL_COLOR_INDEX, srcType,
361 i);
362 if (!src) {
363 free(buffer);
364 return NULL;
365 }
366 MEMCPY( dst, src, width_in_bytes );
367 dst += width_in_bytes;
368 }
369 /* Bit flipping */
370 if (ctx->Unpack.LsbFirst) {
371 gl_flip_bytes( buffer, bytes );
372 }
373 }
374 else {
375 /* a 'null' bitmap */
376 buffer = NULL;
377 }
378
379 image = (struct gl_image *) malloc( sizeof(struct gl_image) );
380 if (image) {
381 image->Width = width;
382 image->Height = height;
383 image->Components = 0;
384 image->Format = GL_COLOR_INDEX;
385 image->Type = GL_BITMAP;
386 image->Data = buffer;
387 image->RefCount = 0;
388 }
389 else {
390 if (buffer)
391 free( buffer );
392 return NULL;
393 }
394 return image;
395 }
396 else if (srcFormat==GL_DEPTH_COMPONENT) {
397 /* TODO: pack as GLdepth values (GLushort or GLuint) */
398
399 }
400 else if (srcFormat==GL_STENCIL_INDEX) {
401 /* TODO: pack as GLstencil (GLubyte or GLushort) */
402
403 }
404 else if (destType==GL_UNSIGNED_BYTE) {
405 struct gl_image *image;
406 GLint width_in_bytes;
407 GLubyte *buffer, *dst;
408 GLint i;
409 assert( srcType==GL_UNSIGNED_BYTE );
410
411 width_in_bytes = width * components * sizeof(GLubyte);
412 buffer = (GLubyte *) malloc( height * width_in_bytes );
413 if (!buffer) {
414 return NULL;
415 }
416 /* Copy/unpack pixel data to buffer */
417 dst = buffer;
418 for (i=0;i<height;i++) {
419 GLubyte *src = (GLubyte *) gl_pixel_addr_in_image( &ctx->Unpack,
420 pixels, width, height, srcFormat, srcType, i);
421 if (!src) {
422 free(buffer);
423 return NULL;
424 }
425 MEMCPY( dst, src, width_in_bytes );
426 dst += width_in_bytes;
427 }
428
429 if (ctx->Unpack.LsbFirst) {
430 gl_flip_bytes( buffer, height * width_in_bytes );
431 }
432
433 image = (struct gl_image *) malloc( sizeof(struct gl_image) );
434 if (image) {
435 image->Width = width;
436 image->Height = height;
437 image->Components = components;
438 image->Format = srcFormat;
439 image->Type = GL_UNSIGNED_BYTE;
440 image->Data = buffer;
441 image->RefCount = 0;
442 }
443 else {
444 free( buffer );
445 return NULL;
446 }
447 return image;
448 }
449 else if (destType==GL_FLOAT) {
450 struct gl_image *image;
451 GLfloat *buffer, *dst;
452 GLint elems_per_row;
453 GLint i, j;
454 GLboolean normalize;
455 elems_per_row = width * components;
456 buffer = (GLfloat *) malloc( height * elems_per_row * sizeof(GLfloat));
457 if (!buffer) {
458 return NULL;
459 }
460
461 normalize = (srcFormat != GL_COLOR_INDEX)
462 && (srcFormat != GL_STENCIL_INDEX);
463
464 dst = buffer;
465 /** img_pixels= pixels;*/
466 for (i=0;i<height;i++) {
467 GLvoid *src = gl_pixel_addr_in_image( &ctx->Unpack, pixels,
468 width, height,
469 srcFormat, srcType,
470 i);
471 if (!src) {
472 free(buffer);
473 return NULL;
474 }
475
476 switch (srcType) {
477 case GL_UNSIGNED_BYTE:
478 if (normalize) {
479 for (j=0;j<elems_per_row;j++) {
480 *dst++ = UBYTE_TO_FLOAT(((GLubyte*)src)[j]);
481 }
482 }
483 else {
484 for (j=0;j<elems_per_row;j++) {
485 *dst++ = (GLfloat) ((GLubyte*)src)[j];
486 }
487 }
488 break;
489 case GL_BYTE:
490 if (normalize) {
491 for (j=0;j<elems_per_row;j++) {
492 *dst++ = BYTE_TO_FLOAT(((GLbyte*)src)[j]);
493 }
494 }
495 else {
496 for (j=0;j<elems_per_row;j++) {
497 *dst++ = (GLfloat) ((GLbyte*)src)[j];
498 }
499 }
500 break;
501 case GL_UNSIGNED_SHORT:
502 if (ctx->Unpack.SwapBytes) {
503 for (j=0;j<elems_per_row;j++) {
504 GLushort value = ((GLushort*)src)[j];
505 value = ((value >> 8) & 0xff) | ((value&0xff) << 8);
506 if (normalize) {
507 *dst++ = USHORT_TO_FLOAT(value);
508 }
509 else {
510 *dst++ = (GLfloat) value;
511 }
512 }
513 }
514 else {
515 if (normalize) {
516 for (j=0;j<elems_per_row;j++) {
517 *dst++ = USHORT_TO_FLOAT(((GLushort*)src)[j]);
518 }
519 }
520 else {
521 for (j=0;j<elems_per_row;j++) {
522 *dst++ = (GLfloat) ((GLushort*)src)[j];
523 }
524 }
525 }
526 break;
527 case GL_SHORT:
528 if (ctx->Unpack.SwapBytes) {
529 for (j=0;j<elems_per_row;j++) {
530 GLshort value = ((GLshort*)src)[j];
531 value = ((value >> 8) & 0xff) | ((value&0xff) << 8);
532 if (normalize) {
533 *dst++ = SHORT_TO_FLOAT(value);
534 }
535 else {
536 *dst++ = (GLfloat) value;
537 }
538 }
539 }
540 else {
541 if (normalize) {
542 for (j=0;j<elems_per_row;j++) {
543 *dst++ = SHORT_TO_FLOAT(((GLshort*)src)[j]);
544 }
545 }
546 else {
547 for (j=0;j<elems_per_row;j++) {
548 *dst++ = (GLfloat) ((GLshort*)src)[j];
549 }
550 }
551 }
552 break;
553 case GL_UNSIGNED_INT:
554 if (ctx->Unpack.SwapBytes) {
555 GLuint value;
556 for (j=0;j<elems_per_row;j++) {
557 value = ((GLuint*)src)[j];
558 value = ((value & 0xff000000) >> 24)
559 | ((value & 0x00ff0000) >> 8)
560 | ((value & 0x0000ff00) << 8)
561 | ((value & 0x000000ff) << 24);
562 if (normalize) {
563 *dst++ = UINT_TO_FLOAT(value);
564 }
565 else {
566 *dst++ = (GLfloat) value;
567 }
568 }
569 }
570 else {
571 if (normalize) {
572 for (j=0;j<elems_per_row;j++) {
573 *dst++ = UINT_TO_FLOAT(((GLuint*)src)[j]);
574 }
575 }
576 else {
577 for (j=0;j<elems_per_row;j++) {
578 *dst++ = (GLfloat) ((GLuint*)src)[j];
579 }
580 }
581 }
582 break;
583 case GL_INT:
584 if (ctx->Unpack.SwapBytes) {
585 GLint value;
586 for (j=0;j<elems_per_row;j++) {
587 value = ((GLint*)src)[j];
588 value = ((value & 0xff000000) >> 24)
589 | ((value & 0x00ff0000) >> 8)
590 | ((value & 0x0000ff00) << 8)
591 | ((value & 0x000000ff) << 24);
592 if (normalize) {
593 *dst++ = INT_TO_FLOAT(value);
594 }
595 else {
596 *dst++ = (GLfloat) value;
597 }
598 }
599 }
600 else {
601 if (normalize) {
602 for (j=0;j<elems_per_row;j++) {
603 *dst++ = INT_TO_FLOAT(((GLint*)src)[j]);
604 }
605 }
606 else {
607 for (j=0;j<elems_per_row;j++) {
608 *dst++ = (GLfloat) ((GLint*)src)[j];
609 }
610 }
611 }
612 break;
613 case GL_FLOAT:
614 if (ctx->Unpack.SwapBytes) {
615 GLint value;
616 for (j=0;j<elems_per_row;j++) {
617 value = ((GLuint*)src)[j];
618 value = ((value & 0xff000000) >> 24)
619 | ((value & 0x00ff0000) >> 8)
620 | ((value & 0x0000ff00) << 8)
621 | ((value & 0x000000ff) << 24);
622 *dst++ = *((GLfloat*) &value);
623 }
624 }
625 else {
626 MEMCPY( dst, src, elems_per_row*sizeof(GLfloat) );
627 dst += elems_per_row;
628 }
629 break;
630 default:
631 gl_problem(ctx, "Bad type in gl_unpack_image3D");
632 return NULL;
633 } /*switch*/
634 } /* for height */
635
636 image = (struct gl_image *) malloc( sizeof(struct gl_image) );
637 if (image) {
638 image->Width = width;
639 image->Height = height;
640 image->Components = components;
641 image->Format = srcFormat;
642 image->Type = GL_FLOAT;
643 image->Data = buffer;
644 image->RefCount = 0;
645 }
646 else {
647 free( buffer );
648 return NULL;
649 }
650 return image;
651 }
652 else {
653 gl_problem(ctx, "Bad dest type in gl_unpack_image3D");
654 return NULL;
655 }
656 return NULL; /* never get here */
657 }
658
659
660
gl_free_image(struct gl_image * image)661 void gl_free_image( struct gl_image *image )
662 {
663 if (image->Data) {
664 free(image->Data);
665 }
666 free(image);
667 }
668