xref: /reactos/dll/opengl/mesa/image.c (revision 40462c92)
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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 
661 void gl_free_image( struct gl_image *image )
662 {
663    if (image->Data) {
664       free(image->Data);
665    }
666    free(image);
667 }
668