Fixing Linux SCons build.
[xonotic/netradiant.git] / contrib / gtkgensurf / bitmap.cpp
1 /*
2 GenSurf plugin for GtkRadiant
3 Copyright (C) 2001 David Hyde, Loki software and qeradiant.com
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library 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 GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22
23 #ifdef _WIN32
24 // cough, cough
25 typedef __int32 int32_t;
26 typedef unsigned __int16 uint16_t;
27 typedef unsigned __int8 uint8_t;
28 typedef unsigned __int32 uint32_t;
29 typedef __int16 int16_t;
30 #endif
31
32 #include <math.h>
33 #include "gensurf.h"
34
35 void GenerateBitmapMapping ()
36 {
37   double              value;
38   double              C0, C1;
39   double              x, y;
40   int                 i, j;
41   int                 O00,O01,O10,O11;
42   int                 r0, r1, c0, c1;
43   int                 color;
44   unsigned char       *colors;
45
46   if (!gbmp.colors)
47     return;
48
49   colors = gbmp.colors;
50
51   for (j=0; j<=NV; j++)
52   {
53     y  = (double)(j*(gbmp.height-1))/(double)NV;
54     r0 = (int)floor(y);
55     r1 = (int)ceil(y);
56     for (i=0; i<=NH; i++)
57     {
58       x = (double)(i*(gbmp.width-1))/(double)NH;
59       c0 = (int)floor(x);
60       c1 = (int)ceil(x);
61       O00 = r0*gbmp.width + c0;
62       O01 = r0*gbmp.width + c1;
63       O10 = r1*gbmp.width + c0;
64       O11 = r1*gbmp.width + c1;
65       C0 = (double)colors[O00] + (double)(colors[O01]-colors[O00])*(x-(double)c0);
66       C1 = (double)colors[O10] + (double)(colors[O11]-colors[O10])*(x-(double)c0);
67       color = (int)(C0 + (C1-C0)*(y-r0));
68
69       value = CalculateSnapValue(gbmp.black_value + color*((gbmp.white_value-gbmp.black_value)/255.));
70
71       switch(Plane)
72       {
73       case PLANE_XZ0:
74       case PLANE_XZ1:
75         xyz[i][j].p[1] = value;
76         break;
77       case PLANE_YZ0:
78       case PLANE_YZ1:
79         xyz[i][j].p[0] = value;
80         break;
81       default:
82         xyz[i][j].p[2] = value;
83       }
84     }
85   }
86 }
87
88 static unsigned char* OpenBitmapFile ()
89 {
90 #define INVALID_FORMAT do{\
91   fprintf(stderr,"%s:%d: Error file '%s' is malformed.\n",__FILE__,__LINE__,gbmp.name);\
92   fclose(fp);\
93   return NULL;\
94 }while(0);
95
96   int32_t bmWidth;
97   int32_t bmHeight;
98   uint16_t bmPlanes;
99   uint16_t bmBitsPixel;
100   uint8_t m1,m2;
101   uint32_t sizeimage;
102   int16_t res1,res2;
103   int32_t filesize, pixoff;
104   int32_t bmisize, compression;
105   int32_t xscale, yscale;
106   int32_t colors, impcol;
107   uint32_t m_bytesRead = 0;
108   unsigned char *image;
109   FILE *fp;
110
111   fp = fopen (gbmp.name, "rb");
112   if (fp == NULL)
113   {
114           fprintf(stderr,"Error: Invalid filename '%s'\n",gbmp.name);
115           return NULL;
116   }
117
118   long rc;
119   rc = fread(&m1, 1, 1, fp);
120   m_bytesRead++;
121   if (rc == -1)
122   {
123     fclose(fp);
124     return NULL;
125   }
126
127   rc = fread(&m2, 1, 1, fp);
128   m_bytesRead++;
129   if ((m1 != 'B') || (m2 != 'M'))
130   INVALID_FORMAT;
131
132   rc = fread((uint32_t*)&(filesize),4,1,fp); m_bytesRead+=4;
133   if (rc != 1)  INVALID_FORMAT;
134
135   rc = fread((uint16_t*)&(res1),2,1,fp); m_bytesRead+=2;
136   if (rc != 1) INVALID_FORMAT;
137
138   rc = fread((uint16_t*)&(res2),2,1,fp); m_bytesRead+=2;
139   if (rc != 1) INVALID_FORMAT;
140
141   rc = fread((uint32_t*)&(pixoff),4,1,fp); m_bytesRead+=4;
142   if (rc != 1) INVALID_FORMAT;
143
144   rc = fread((uint32_t*)&(bmisize),4,1,fp); m_bytesRead+=4;
145   if (rc != 1) INVALID_FORMAT;
146
147   rc = fread((uint32_t  *)&(bmWidth),4,1,fp); m_bytesRead+=4;
148   if (rc != 1) INVALID_FORMAT;
149
150   rc = fread((uint32_t*)&(bmHeight),4,1,fp); m_bytesRead+=4;
151   if (rc != 1) INVALID_FORMAT;
152
153   rc = fread((uint16_t*)&(bmPlanes),2,1,fp); m_bytesRead+=2;
154   if (rc != 1) INVALID_FORMAT;
155
156   rc = fread((uint16_t*)&(bmBitsPixel),2,1,fp); m_bytesRead+=2;
157   if (rc != 1)  INVALID_FORMAT;
158
159   rc = fread((uint32_t*)&(compression),4,1,fp); m_bytesRead+=4;
160   if (rc != 1)  INVALID_FORMAT;
161
162   rc = fread((uint32_t*)&(sizeimage),4,1,fp); m_bytesRead+=4;
163   if (rc != 1)  INVALID_FORMAT;
164
165   rc = fread((uint32_t*)&(xscale),4,1,fp); m_bytesRead+=4;
166   if (rc != 1)  INVALID_FORMAT;
167
168   rc = fread((uint32_t*)&(yscale),4,1,fp); m_bytesRead+=4;
169   if (rc != 1)  INVALID_FORMAT;
170
171   rc = fread((uint32_t*)&(colors),4,1,fp); m_bytesRead+=4;
172   if (rc != 1)  INVALID_FORMAT;
173
174   rc = fread((uint32_t*)&(impcol),4,1,fp); m_bytesRead+=4;
175   if (rc != 1)  INVALID_FORMAT;
176
177   if (bmBitsPixel != 8)
178   {
179     g_FuncTable.m_pfnMessageBox (g_pWnd, "This is not an 8-bit image. GenSurf can't use it.",
180                                  "Bitmap", MB_ICONEXCLAMATION, NULL);
181      INVALID_FORMAT;
182   }
183
184   if (colors == 0)
185     colors = 1 << bmBitsPixel;
186
187   if (bmBitsPixel != 24)
188   {
189     int i;
190     for (i = 0; i < colors; i++)
191     {
192       unsigned char r ,g, b, dummy;
193
194       rc = fread(&b, 1, 1, fp);
195       m_bytesRead++;
196       if (rc!=1)
197       {
198                INVALID_FORMAT;
199       }
200
201       rc = fread(&g, 1, 1, fp); 
202       m_bytesRead++;
203       if (rc!=1)
204       {
205                INVALID_FORMAT;
206       }
207
208       rc = fread(&r, 1, 1, fp); 
209       m_bytesRead++;
210       if (rc != 1)
211       {
212                INVALID_FORMAT;
213       }
214
215       rc = fread(&dummy, 1, 1, fp); 
216       m_bytesRead++;
217       if (rc != 1)
218       {
219                INVALID_FORMAT;
220       }
221     }
222   }
223
224   if ((long)m_bytesRead > pixoff)
225   {
226            INVALID_FORMAT;
227   }
228
229   while ((long)m_bytesRead < pixoff)
230   {
231     char dummy;
232     fread(&dummy,1,1,fp);
233     m_bytesRead++;
234   }
235
236   int w = bmWidth;
237   int h = bmHeight;
238
239   // set the output params
240   image = (unsigned char*)malloc(w*h);
241
242   if (image != NULL) 
243   {
244     unsigned char* outbuf = image;
245     long row = 0;
246     long rowOffset = 0;
247
248     if (compression == 0) // BI_RGB
249     {
250       for (row = 0; row < bmHeight; row++)
251       {
252         // which row are we working on?
253         rowOffset = (long unsigned)row*w;                                                     
254
255         {
256           // pixels are packed as 1 , 4 or 8 bit vals. need to unpack them
257           int bit_count = 0;
258           unsigned long mask = (1 << bmBitsPixel) - 1;
259           unsigned char inbyte = 0;
260
261           for (int col=0;col<w;col++)
262           {
263             int pix = 0;
264
265             // if we need another byte
266             if (bit_count <= 0)
267             {
268               bit_count = 8;
269               if (fread(&inbyte,1,1,fp) != 1)
270               {
271                 free(image);
272                  INVALID_FORMAT;
273               }
274               m_bytesRead++;
275             }
276
277             // keep track of where we are in the bytes
278             bit_count -= bmBitsPixel;
279             pix = ( inbyte >> bit_count) & mask;
280
281             // lookup the color from the colormap - stuff it in our buffer
282             // swap red and blue
283             *(outbuf + rowOffset + col) = pix;
284           }
285
286           // read DWORD padding
287           while ((m_bytesRead-pixoff)&3)
288           {
289             char dummy;
290             if (fread(&dummy,1,1,fp)!=1)
291             {
292               free(image);
293                INVALID_FORMAT;
294             }
295             m_bytesRead++;
296           }
297         }
298       }
299     }
300     else    // compression != 0
301     {
302       int i, x = 0;
303       unsigned char c, c1 = 0, *pp;
304       row = 0;
305       pp = outbuf;
306
307       if (bmBitsPixel == 8)
308       {
309         while (row < bmHeight)
310         {
311           c = getc(fp);
312
313           if (c)
314           {
315             // encoded mode
316             c1 = getc(fp);
317             for (i = 0; i < c; x++, i++)
318             {
319               *pp = c1; pp++;
320             }
321           }
322           else
323           {
324             // c==0x00,  escape codes
325             c = getc(fp);
326
327             if (c == 0x00) // end of line
328             {
329               row++;
330               x = 0;
331               pp = outbuf + row*bmWidth;
332             }
333             else if (c == 0x01)
334               break; // end of pic
335             else if (c == 0x02) // delta
336             {
337               c = getc(fp);
338               x += c;
339               c = getc(fp);
340               row += c;
341               pp = outbuf + x + row*bmWidth;
342             }
343             else // absolute mode
344             {
345               for (i = 0; i < c; x++, i++)
346               {
347                 c1 = getc(fp);
348                 *pp = c1; pp++;
349               }
350
351               if (c & 1)
352                 getc(fp); // odd length run: read an extra pad byte
353             }
354           }
355         }
356       }
357       else if (bmBitsPixel == 4)
358       {
359         while (row < bmHeight)
360         {
361           c = getc(fp);
362
363           if (c)
364           {
365             // encoded mode
366             c1 = getc(fp);
367             for (i = 0; i < c; x++, i++)
368             {
369               *pp = (i&1) ? (c1 & 0x0f) : ((c1>>4)&0x0f); pp++;
370             }
371           }
372           else
373           {
374             // c==0x00,  escape codes
375             c = getc(fp);
376
377             if (c == 0x00) // end of line
378             {
379               row++;
380               x = 0;
381               pp = outbuf + bmHeight*bmWidth;
382             }
383             else if (c == 0x01)
384               break; // end of pic
385             else if (c == 0x02) // delta
386             {
387               c = getc(fp);
388               x += c;
389               c = getc(fp);
390               row += c;
391               pp = outbuf + x + row*bmWidth;
392             }
393             else // absolute mode
394             {
395               for (i = 0; i < c; x++, i++)
396               {
397                 if ((i&1) == 0)
398                   c1 = getc(fp);
399                 *pp = (i&1) ? (c1 & 0x0f) : ((c1>>4)&0x0f); pp++;
400               }
401
402               if (((c&3) == 1) || ((c&3) == 2))
403                 getc(fp); // odd length run: read an extra pad byte
404             }
405           }
406         }
407       }
408     }
409   }
410   fclose(fp);
411
412   gbmp.width = w;
413   gbmp.height = h;
414   if(gbmp.colors)
415         free(gbmp.colors);
416   gbmp.colors = image;
417   return image;
418
419
420 }
421
422 bool OpenBitmap ()
423 {
424
425   OpenBitmapFile ();
426
427   if (!gbmp.colors)
428   {
429     g_print("failed to load file gbmp %s\n",gbmp.name);
430     char Text[256];
431
432     sprintf (Text, "Error opening %s", gbmp.name);
433     g_FuncTable.m_pfnMessageBox (g_pWnd, Text, "Bitmap", MB_ICONEXCLAMATION, NULL);
434     strcpy (gbmp.name, "");
435   }
436
437   if (g_pWnd)
438   {
439     gtk_entry_set_text (GTK_ENTRY (g_object_get_data (G_OBJECT (g_pWnd), "bmp_file")), gbmp.name);
440     gtk_widget_set_sensitive (GTK_WIDGET (g_object_get_data (G_OBJECT (g_pWnd), "bmp_reload")),
441                               strlen (gbmp.name) ? TRUE : FALSE);
442
443     UpdatePreview (true);
444   }
445
446   return (gbmp.colors != NULL);
447 }