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