]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - contrib/gtkgensurf/bitmap.cpp
uncrustify! 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
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         double value;
37         double C0, C1;
38         double x, y;
39         int i, j;
40         int O00,O01,O10,O11;
41         int r0, r1, c0, c1;
42         int color;
43         unsigned char       *colors;
44
45         if ( !gbmp.colors ) {
46                 return;
47         }
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 #define INVALID_FORMAT do {     \
90                 fprintf( stderr,"%s:%d: Error file '%s' is malformed.\n",__FILE__,__LINE__,gbmp.name ); \
91                 fclose( fp ); \
92                 return NULL; \
93 } while ( 0 )
94
95         int32_t bmWidth;
96         int32_t bmHeight;
97         uint16_t bmPlanes;
98         uint16_t bmBitsPixel;
99         uint8_t m1,m2;
100         uint32_t sizeimage;
101         int16_t res1,res2;
102         int32_t filesize, pixoff;
103         int32_t bmisize, compression;
104         int32_t xscale, yscale;
105         int32_t colors, impcol;
106         uint32_t m_bytesRead = 0;
107         unsigned char *image;
108         FILE *fp;
109
110         fp = fopen( gbmp.name, "rb" );
111         if ( fp == NULL ) {
112                 fprintf( stderr,"Error: Invalid filename '%s'\n",gbmp.name );
113                 return NULL;
114         }
115
116         long rc;
117         rc = fread( &m1, 1, 1, fp );
118         m_bytesRead++;
119         if ( rc == -1 ) {
120                 fclose( fp );
121                 return NULL;
122         }
123
124         rc = fread( &m2, 1, 1, fp );
125         m_bytesRead++;
126         if ( ( m1 != 'B' ) || ( m2 != 'M' ) ) {
127                 INVALID_FORMAT;
128         }
129
130         rc = fread( (uint32_t*)&( filesize ),4,1,fp ); m_bytesRead += 4;
131         if ( rc != 1 ) {
132                 INVALID_FORMAT;
133         }
134
135         rc = fread( (uint16_t*)&( res1 ),2,1,fp ); m_bytesRead += 2;
136         if ( rc != 1 ) {
137                 INVALID_FORMAT;
138         }
139
140         rc = fread( (uint16_t*)&( res2 ),2,1,fp ); m_bytesRead += 2;
141         if ( rc != 1 ) {
142                 INVALID_FORMAT;
143         }
144
145         rc = fread( (uint32_t*)&( pixoff ),4,1,fp ); m_bytesRead += 4;
146         if ( rc != 1 ) {
147                 INVALID_FORMAT;
148         }
149
150         rc = fread( (uint32_t*)&( bmisize ),4,1,fp ); m_bytesRead += 4;
151         if ( rc != 1 ) {
152                 INVALID_FORMAT;
153         }
154
155         rc = fread( (uint32_t  *)&( bmWidth ),4,1,fp ); m_bytesRead += 4;
156         if ( rc != 1 ) {
157                 INVALID_FORMAT;
158         }
159
160         rc = fread( (uint32_t*)&( bmHeight ),4,1,fp ); m_bytesRead += 4;
161         if ( rc != 1 ) {
162                 INVALID_FORMAT;
163         }
164
165         rc = fread( (uint16_t*)&( bmPlanes ),2,1,fp ); m_bytesRead += 2;
166         if ( rc != 1 ) {
167                 INVALID_FORMAT;
168         }
169
170         rc = fread( (uint16_t*)&( bmBitsPixel ),2,1,fp ); m_bytesRead += 2;
171         if ( rc != 1 ) {
172                 INVALID_FORMAT;
173         }
174
175         rc = fread( (uint32_t*)&( compression ),4,1,fp ); m_bytesRead += 4;
176         if ( rc != 1 ) {
177                 INVALID_FORMAT;
178         }
179
180         rc = fread( (uint32_t*)&( sizeimage ),4,1,fp ); m_bytesRead += 4;
181         if ( rc != 1 ) {
182                 INVALID_FORMAT;
183         }
184
185         rc = fread( (uint32_t*)&( xscale ),4,1,fp ); m_bytesRead += 4;
186         if ( rc != 1 ) {
187                 INVALID_FORMAT;
188         }
189
190         rc = fread( (uint32_t*)&( yscale ),4,1,fp ); m_bytesRead += 4;
191         if ( rc != 1 ) {
192                 INVALID_FORMAT;
193         }
194
195         rc = fread( (uint32_t*)&( colors ),4,1,fp ); m_bytesRead += 4;
196         if ( rc != 1 ) {
197                 INVALID_FORMAT;
198         }
199
200         rc = fread( (uint32_t*)&( impcol ),4,1,fp ); m_bytesRead += 4;
201         if ( rc != 1 ) {
202                 INVALID_FORMAT;
203         }
204
205         if ( bmBitsPixel != 8 ) {
206                 g_FuncTable.m_pfnMessageBox( g_pWnd, "This is not an 8-bit image. GenSurf can't use it.",
207                                                                          "Bitmap", MB_ICONEXCLAMATION, NULL );
208                 INVALID_FORMAT;
209         }
210
211         if ( colors == 0 ) {
212                 colors = 1 << bmBitsPixel;
213         }
214
215         if ( bmBitsPixel != 24 ) {
216                 int i;
217                 for ( i = 0; i < colors; i++ )
218                 {
219                         unsigned char r,g, b, dummy;
220
221                         rc = fread( &b, 1, 1, fp );
222                         m_bytesRead++;
223                         if ( rc != 1 ) {
224                                 INVALID_FORMAT;
225                         }
226
227                         rc = fread( &g, 1, 1, fp );
228                         m_bytesRead++;
229                         if ( rc != 1 ) {
230                                 INVALID_FORMAT;
231                         }
232
233                         rc = fread( &r, 1, 1, fp );
234                         m_bytesRead++;
235                         if ( rc != 1 ) {
236                                 INVALID_FORMAT;
237                         }
238
239                         rc = fread( &dummy, 1, 1, fp );
240                         m_bytesRead++;
241                         if ( rc != 1 ) {
242                                 INVALID_FORMAT;
243                         }
244                 }
245         }
246
247         if ( (long)m_bytesRead > pixoff ) {
248                 INVALID_FORMAT;
249         }
250
251         while ( (long)m_bytesRead < pixoff )
252         {
253                 char dummy;
254                 fread( &dummy,1,1,fp );
255                 m_bytesRead++;
256         }
257
258         int w = bmWidth;
259         int h = bmHeight;
260
261         // set the output params
262         image = (unsigned char*)malloc( w * h );
263
264         if ( image != NULL ) {
265                 unsigned char* outbuf = image;
266                 long row = 0;
267                 long rowOffset = 0;
268
269                 if ( compression == 0 ) { // BI_RGB
270                         for ( row = 0; row < bmHeight; row++ )
271                         {
272                                 // which row are we working on?
273                                 rowOffset = (long unsigned)row * w;
274
275                                 {
276                                         // pixels are packed as 1 , 4 or 8 bit vals. need to unpack them
277                                         int bit_count = 0;
278                                         unsigned long mask = ( 1 << bmBitsPixel ) - 1;
279                                         unsigned char inbyte = 0;
280
281                                         for ( int col = 0; col < w; col++ )
282                                         {
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                                         {
307                                                 char dummy;
308                                                 if ( fread( &dummy,1,1,fp ) != 1 ) {
309                                                         free( image );
310                                                         INVALID_FORMAT;
311                                                 }
312                                                 m_bytesRead++;
313                                         }
314                                 }
315                         }
316                 }
317                 else // compression != 0
318                 {
319                         int i, x = 0;
320                         unsigned char c, c1 = 0, *pp;
321                         row = 0;
322                         pp = outbuf;
323
324                         if ( bmBitsPixel == 8 ) {
325                                 while ( row < bmHeight )
326                                 {
327                                         c = getc( fp );
328
329                                         if ( c ) {
330                                                 // encoded mode
331                                                 c1 = getc( fp );
332                                                 for ( i = 0; i < c; x++, i++ )
333                                                 {
334                                                         *pp = c1; pp++;
335                                                 }
336                                         }
337                                         else
338                                         {
339                                                 // c==0x00,  escape codes
340                                                 c = getc( fp );
341
342                                                 if ( c == 0x00 ) { // end of line
343                                                         row++;
344                                                         x = 0;
345                                                         pp = outbuf + row * bmWidth;
346                                                 }
347                                                 else if ( c == 0x01 ) {
348                                                         break; // end of pic
349                                                 }
350                                                 else if ( c == 0x02 ) { // delta
351                                                         c = getc( fp );
352                                                         x += c;
353                                                         c = getc( fp );
354                                                         row += c;
355                                                         pp = outbuf + x + row * bmWidth;
356                                                 }
357                                                 else // absolute mode
358                                                 {
359                                                         for ( i = 0; i < c; x++, i++ )
360                                                         {
361                                                                 c1 = getc( fp );
362                                                                 *pp = c1; pp++;
363                                                         }
364
365                                                         if ( c & 1 ) {
366                                                                 getc( fp ); // odd length run: read an extra pad byte
367                                                         }
368                                                 }
369                                         }
370                                 }
371                         }
372                         else if ( bmBitsPixel == 4 ) {
373                                 while ( row < bmHeight )
374                                 {
375                                         c = getc( fp );
376
377                                         if ( c ) {
378                                                 // encoded mode
379                                                 c1 = getc( fp );
380                                                 for ( i = 0; i < c; x++, i++ )
381                                                 {
382                                                         *pp = ( i & 1 ) ? ( c1 & 0x0f ) : ( ( c1 >> 4 ) & 0x0f ); pp++;
383                                                 }
384                                         }
385                                         else
386                                         {
387                                                 // c==0x00,  escape codes
388                                                 c = getc( fp );
389
390                                                 if ( c == 0x00 ) { // end of line
391                                                         row++;
392                                                         x = 0;
393                                                         pp = outbuf + bmHeight * bmWidth;
394                                                 }
395                                                 else if ( c == 0x01 ) {
396                                                         break; // end of pic
397                                                 }
398                                                 else if ( c == 0x02 ) { // delta
399                                                         c = getc( fp );
400                                                         x += c;
401                                                         c = getc( fp );
402                                                         row += c;
403                                                         pp = outbuf + x + row * bmWidth;
404                                                 }
405                                                 else // absolute mode
406                                                 {
407                                                         for ( i = 0; i < c; x++, i++ )
408                                                         {
409                                                                 if ( ( i & 1 ) == 0 ) {
410                                                                         c1 = getc( fp );
411                                                                 }
412                                                                 *pp = ( i & 1 ) ? ( c1 & 0x0f ) : ( ( c1 >> 4 ) & 0x0f ); pp++;
413                                                         }
414
415                                                         if ( ( ( c & 3 ) == 1 ) || ( ( c & 3 ) == 2 ) ) {
416                                                                 getc( fp ); // odd length run: read an extra pad byte
417                                                         }
418                                                 }
419                                         }
420                                 }
421                         }
422                 }
423         }
424         fclose( fp );
425
426         gbmp.width = w;
427         gbmp.height = h;
428         if ( gbmp.colors ) {
429                 free( gbmp.colors );
430         }
431         gbmp.colors = image;
432         return image;
433
434
435 }
436
437 bool OpenBitmap(){
438
439         OpenBitmapFile();
440
441         if ( !gbmp.colors ) {
442                 g_print( "failed to load file gbmp %s\n",gbmp.name );
443                 char Text[256];
444
445                 sprintf( Text, "Error opening %s", gbmp.name );
446                 g_FuncTable.m_pfnMessageBox( g_pWnd, Text, "Bitmap", MB_ICONEXCLAMATION, NULL );
447                 strcpy( gbmp.name, "" );
448         }
449
450         if ( g_pWnd ) {
451                 gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "bmp_file" ) ), gbmp.name );
452                 gtk_widget_set_sensitive( GTK_WIDGET( g_object_get_data( G_OBJECT( g_pWnd ), "bmp_reload" ) ),
453                                                                   strlen( gbmp.name ) ? TRUE : FALSE );
454
455                 UpdatePreview( true );
456         }
457
458         return ( gbmp.colors != NULL );
459 }