Rice GLES2 (from mupen64plus-ae) plugin. Compile but doesn't works well on the OpenPa...
[mupen64plus-pandora.git] / source / gles2rice / src / liblinux / BMGUtils.c
1 /*
2 //  source code for the BMGLib Utility functions
3 //
4 //  Copyright (C) 2001 M. Scott Heiman
5 //  All Rights Reserved
6 //
7 // You may use the software for any purpose you see fit. You may modify
8 // it, incorporate it in a commercial application, use it for school,
9 // even turn it in as homework. You must keep the Copyright in the
10 // header and source files. This software is not in the "Public Domain".
11 // You may use this software at your own risk. I have made a reasonable
12 // effort to verify that this software works in the manner I expect it to;
13 // however,...
14 //
15 // THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" AND
16 // WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, INCLUDING
17 // WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR FITNESS FOR A
18 // PARTICULAR PURPOSE. IN NO EVENT SHALL MICHAEL S. HEIMAN BE LIABLE TO
19 // YOU OR ANYONE ELSE FOR ANY DIRECT, SPECIAL, INCIDENTAL, INDIRECT OR
20 // CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING
21 // WITHOUT LIMITATION, LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE,
22 // OR THE CLAIMS OF THIRD PARTIES, WHETHER OR NOT MICHAEL S. HEIMAN HAS
23 // BEEN ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
24 // ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
25 // POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
26 */
27
28 #include <stdlib.h>
29 #include "BMGUtils.h"
30
31 #ifndef _WIN32
32 #include <string.h>
33 #endif // _WIN32
34
35 /* error strings for all BMG errors */
36 static char BMGErrorStrings[17][128] = {
37 "No Error",
38 "Corrupted file or invalid file format",
39 "Invalid bits per pixel for this file format",
40 "Memory allocation error",
41 "Invalid requested image size",
42 "Invalid bitmap handle",
43 "Windows API Error",  /* this will be overwritten */
44 "Unable to open file",
45 "Unsupported file format option",
46 "Invalid pointer to a BMG image",
47 "Unsupported file extension",
48 "Error reading file",
49 "Error writing to the output file",
50 "Invalid pointer to a GeoTIFF structure",
51 "The background image is undefined",
52 "The background image is too small",
53 "Corrupt File"
54 };
55
56 /* stores last BMG error */
57 static BMGError LastBMGError;
58
59 /* sets the last BMG error */
60 void SetLastBMGError( BMGError err )
61 {
62     LastBMGError = err;
63 }
64
65 /* returns the last error state */
66 BMGError GetLastBMGError(void)
67 {
68     return LastBMGError;
69 }
70 /* gets the error message */
71 void GetLastBMGErrorMessage( const char **msg )
72 {
73     if ( LastBMGError == errWindowsAPI )
74     {
75        char* lpMsgBuf = "Erreur BMG\n";
76
77         /* copy the string. */
78           strcpy( BMGErrorStrings[(int)LastBMGError], (char *)lpMsgBuf );
79     }
80
81     *msg = BMGErrorStrings[(int)LastBMGError];
82 }
83
84 /* Global background color variables */
85 static unsigned char BackgroundColor[4];
86 static struct BMGImageStruct BackgroundImage;
87
88 /* this function simply initializes the background info.  It is called from
89    the DllEntryPoint function */
90 void InitBackground(void)
91 {
92     memset( (void *)BackgroundColor, 0xFF, 3 ); /* white */
93     BackgroundColor[3] = 0; /* ignored */
94     InitBMGImage( &BackgroundImage );
95 }
96
97 unsigned char *GetBackgroundColor(void)
98 {
99     return &BackgroundColor[0];
100 }
101
102 struct BMGImageStruct *GetBackgroundImage(void)
103 {
104     return &BackgroundImage;
105 }
106
107 /* converts an array of 1-bit scanlines to 8-bit scanlines */
108 void Convert1to8( struct BMGImageStruct img,
109                   unsigned char *out )
110 {
111     unsigned char *p, *q, *r, *s, *end;
112     int i;
113
114     q = out;
115
116     for ( s = img.bits; s < img.bits + img.scan_width * img.height;
117           s += img.scan_width, q += img.width )
118     {
119         i = img.width % 8;
120         end = q + img.width - i;
121         p = s;
122         for ( r = q; r < end; p++ )
123         {
124             *r++ = (unsigned char)((*p & 0x80) ? 1 : 0);
125             *r++ = (unsigned char)((*p & 0x40) ? 1 : 0);
126             *r++ = (unsigned char)((*p & 0x20) ? 1 : 0);
127             *r++ = (unsigned char)((*p & 0x10) ? 1 : 0);
128             *r++ = (unsigned char)((*p & 0x08) ? 1 : 0);
129             *r++ = (unsigned char)((*p & 0x04) ? 1 : 0);
130             *r++ = (unsigned char)((*p & 0x02) ? 1 : 0);
131             *r++ = (unsigned char)(*p & 0x01);
132         }
133
134         if ( i-- )
135         {
136             *r++ =  (unsigned char)((*p & 0x80) ? 1 : 0);
137             if ( i-- )
138             {
139                 *r++ =  (unsigned char)((*p & 0x40) ? 1 : 0);
140                 if ( i-- )
141                 {
142                     *r++ =  (unsigned char)((*p & 0x20) ? 1 : 0);
143                     if ( i-- )
144                     {
145                         *r++ =  (unsigned char)((*p & 0x10) ? 1 : 0);
146                         if ( i-- )
147                         {
148                             *r++ =  (unsigned char)((*p & 0x08) ? 1 : 0);
149                             if ( i-- )
150                             {
151                                 *r++ =  (unsigned char)((*p & 0x04) ? 1 : 0);
152                                 if ( i )
153                                     *r   =  (unsigned char)((*p & 0x02) ? 1:0);
154                             }
155                         }
156                     }
157                 }
158             }
159         }
160     }
161 }
162
163 /* converts an array of 4-bit scanlines to 8-bit scanlines */
164 void Convert4to8( struct BMGImageStruct img,
165                   unsigned char *out )
166 {
167     unsigned char *p, *q, *r, *s, *end;
168     int i;
169
170     q = out;
171
172     for ( s = img.bits; s < img.bits + img.scan_width * img.height;
173           s += img.scan_width, q += img.width )
174     {
175         i = img.width % 2;
176         end = q + img.width - i;
177         p = s;
178         for ( r = q; r < end; p++ )
179         {
180             *r++ = (unsigned char)((*p >> 4) & 0x0F);
181             *r++ = (unsigned char)(*p & 0x0F);
182         }
183
184         if ( i )
185             *r =  (unsigned char)((*p >> 4) & 0x0F);
186     }
187 }
188
189 /****************************************************************************/
190 /* this function performs alpha blending.  It is a variation of a function
191   that I found in the PNG example code */
192 unsigned char AlphaComp( unsigned char fg,
193                          unsigned char alpha,
194                          unsigned char bg )
195 {
196   unsigned char out;
197   unsigned short temp;
198
199   switch ( alpha )
200   {
201     case 0:
202       out = bg;
203       break;
204     case 255:
205       out = fg;
206       break;
207     default:
208       temp = ((unsigned short)(fg)*(unsigned short)(alpha) +
209                     (unsigned short)(bg)*(unsigned short)(255 -
210                     (unsigned short)(alpha)) + (unsigned short)128);
211       out = (unsigned char)((temp + (temp >> 8)) >> 8);
212       break;
213   }
214   return out;
215 }
216
217 /****************************************************************************
218 // Converts a 16 BPP image to a 24 BPP image 
219 // returns 1 if successfull, 0 otherwise */
220 BMGError Convert16to24( struct BMGImageStruct *img )
221 {
222     unsigned int i;
223     unsigned int new_scan_width;
224     unsigned char *new_bits;
225
226     /* this function will only work with 16 BBP images */
227     if ( img->bits_per_pixel != 16 )
228         return errInvalidPixelFormat;
229
230     /* calculate the new scan width */
231     new_scan_width = 3 * img->width;
232     if ( new_scan_width % 4 && img->opt_for_bmp )
233         new_scan_width += 4 - new_scan_width % 4;
234
235     /* allocate memory for the new pixel values */
236     new_bits = (unsigned char *)calloc( new_scan_width * img->height, sizeof(unsigned char) );
237     if ( new_bits == NULL )
238         return errMemoryAllocation;
239
240     /* convert the 16 BPP pixel values to the equivalent 24 BPP values  */
241     for ( i = 0; i < img->height; i++ )
242     {
243         unsigned char *p24;
244         unsigned short *p16 = (unsigned short *)(img->bits + i * img->scan_width);
245         unsigned char *start = new_bits + i * new_scan_width;
246         unsigned char *end = start + new_scan_width;
247         for ( p24 = start; p24 < end; p24 += 3, p16++ ) 
248         {
249             p24[0] = (unsigned char)( (*p16 & 0x001F) << 3 );
250             p24[1] = (unsigned char)( (*p16 & 0x03E0) >> 2 );
251             p24[2] = (unsigned char)( (*p16 & 0x7C00) >> 7 );
252         }
253     }
254
255     free( img->bits );
256     img->bits = new_bits;
257     img->scan_width = new_scan_width;
258     img->bits_per_pixel = 24;
259
260     return BMG_OK;
261 }
262
263 /****************************************************************************/
264 /* this function undoes alpha blending - kind-a-sort-of ;-) */
265 unsigned char InverseAlphaComp( unsigned char fg, unsigned char alpha,
266                                unsigned char bg )
267 {
268   unsigned char out;
269   short temp;
270
271   switch ( alpha )
272   {
273     case 0:
274       out = bg;
275       break;
276     case 255:
277       out = fg;
278       break;
279     default:
280       temp = (255*fg - bg*(255-alpha))/alpha;
281       if ( temp < 0 )
282         temp = 0;
283       out = (unsigned char)temp;
284       break;
285   }
286   return out;
287 }
288
289 /****************************************************************************/
290 /*
291 // Creates a BITMAPINFOHEADER for the given width, height, bit count, and
292 // compression.  Compression must = BI_RGB, BI_BITFIELDS, BI_RLE4, or BI_RLE8.
293 */
294 BITMAPINFO InternalCreateBMI( unsigned int dwWidth,  /* width */
295                               unsigned int dwHeight, /* height */
296                               unsigned short wBitCount, /* bit count */
297                               int compression )  /* compression type */
298 {
299    BITMAPINFO bi;         /* bitmap header */
300    unsigned int dwBytesPerLine;        /* Number of bytes per scanline */
301
302    /* clear the bitmapinfo structure */
303    memset(&bi, 0, sizeof(BITMAPINFO));
304
305    /* Make sure bits per pixel is valid */
306    if (wBitCount <= 1)
307       wBitCount = 1;
308    else if (wBitCount <= 4)
309       wBitCount = 4;
310    else if (wBitCount <= 8)
311       wBitCount = 8;
312    else if (wBitCount <= 16)
313       wBitCount = 16;
314    else if (wBitCount <= 24)
315       wBitCount = 24;
316    else if (wBitCount <= 32)
317       wBitCount = 32;
318    else
319       wBitCount = 8;  /* set default value to 8 if parameter is bogus */
320
321    dwBytesPerLine =   (((wBitCount * dwWidth) + 31) / 32 * 4);
322
323    /* initialize BITMAPINFO */
324    bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
325    bi.bmiHeader.biWidth = dwWidth;
326    bi.bmiHeader.biHeight = dwHeight;
327    bi.bmiHeader.biPlanes = 1;              /* must be 1 */
328    bi.bmiHeader.biBitCount = wBitCount;
329    bi.bmiHeader.biCompression =  compression;
330    bi.bmiHeader.biSizeImage = dwBytesPerLine*dwHeight;
331    bi.bmiHeader.biXPelsPerMeter = 0;
332    bi.bmiHeader.biYPelsPerMeter = 0;
333    bi.bmiHeader.biClrUsed = wBitCount <= 8 ? 1U << wBitCount : 0;
334    bi.bmiHeader.biClrImportant = bi.bmiHeader.biClrUsed;
335
336    return bi;
337 }
338
339 short SwapShort( short in )
340 {
341     char sin[2];
342     char sout[2];
343
344     memcpy( (char *)sin, (char *)&in, 2 );
345
346     sout[0] = sin[1];
347     sout[1] = sin[0];
348
349     return *((short *)sout);
350 }
351
352 unsigned short SwapUShort( unsigned short in )
353 {
354     char sin[2];
355     char sout[2];
356
357     memcpy( (char *)sin, (char *)&in, 2 );
358
359     sout[0] = sin[1];
360     sout[1] = sin[0];
361
362     return *((unsigned short *)sout);
363 }
364
365 int SwapLong( int in )
366 {
367     char sin[4];
368     char sout[4];
369
370     memcpy( (char *)sin, (char *)&in, 4 );
371
372     sout[0] = sin[3];
373     sout[1] = sin[2];
374     sout[2] = sin[1];
375     sout[3] = sin[0];
376
377     return *((int *)sout);
378 }
379
380 unsigned int SwapULong( unsigned int in )
381 {
382     char sin[4];
383     char sout[4];
384
385     memcpy( (char *)sin, (char *)&in, 4 );
386
387     sout[0] = sin[3];
388     sout[1] = sin[2];
389     sout[2] = sin[1];
390     sout[3] = sin[0];
391
392     return *((unsigned int *)sout);
393 }
394