/* GenSurf plugin for GtkRadiant Copyright (C) 2001 David Hyde, Loki software and qeradiant.com This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include "gensurf.h" void GenerateBitmapMapping(){ double value; double C0, C1; double x, y; int i, j; int O00,O01,O10,O11; int r0, r1, c0, c1; int color; unsigned char *colors; if ( !gbmp.colors ) { return; } colors = gbmp.colors; for ( j = 0; j <= NV; j++ ) { y = (double)( j * ( gbmp.height - 1 ) ) / (double)NV; r0 = (int)floor( y ); r1 = (int)ceil( y ); for ( i = 0; i <= NH; i++ ) { x = (double)( i * ( gbmp.width - 1 ) ) / (double)NH; c0 = (int)floor( x ); c1 = (int)ceil( x ); O00 = r0 * gbmp.width + c0; O01 = r0 * gbmp.width + c1; O10 = r1 * gbmp.width + c0; O11 = r1 * gbmp.width + c1; C0 = (double)colors[O00] + (double)( colors[O01] - colors[O00] ) * ( x - (double)c0 ); C1 = (double)colors[O10] + (double)( colors[O11] - colors[O10] ) * ( x - (double)c0 ); color = (int)( C0 + ( C1 - C0 ) * ( y - r0 ) ); value = CalculateSnapValue( gbmp.black_value + color * ( ( gbmp.white_value - gbmp.black_value ) / 255. ) ); switch ( Plane ) { case PLANE_XZ0: case PLANE_XZ1: xyz[i][j].p[1] = value; break; case PLANE_YZ0: case PLANE_YZ1: xyz[i][j].p[0] = value; break; default: xyz[i][j].p[2] = value; } } } } static unsigned char* OpenBitmapFile(){ #define INVALID_FORMAT do { \ fprintf( stderr,"%s:%d: Error file '%s' is malformed.\n",__FILE__,__LINE__,gbmp.name ); \ fclose( fp ); \ return NULL; \ } while ( 0 ); int32_t bmWidth; int32_t bmHeight; uint16_t bmPlanes; uint16_t bmBitsPixel; uint8_t m1,m2; uint32_t sizeimage; int16_t res1,res2; int32_t filesize, pixoff; int32_t bmisize, compression; int32_t xscale, yscale; int32_t colors, impcol; uint32_t m_bytesRead = 0; unsigned char *image; FILE *fp; fp = fopen( gbmp.name, "rb" ); if ( fp == NULL ) { fprintf( stderr,"Error: Invalid filename '%s'\n",gbmp.name ); return NULL; } long rc; rc = fread( &m1, 1, 1, fp ); m_bytesRead++; if ( rc == -1 ) { INVALID_FORMAT; } rc = fread( &m2, 1, 1, fp ); m_bytesRead++; if ( ( m1 != 'B' ) || ( m2 != 'M' ) ) { INVALID_FORMAT; } rc = fread( (uint32_t*)&( filesize ),4,1,fp ); m_bytesRead += 4; if ( rc != 1 ) { INVALID_FORMAT; } rc = fread( (uint16_t*)&( res1 ),2,1,fp ); m_bytesRead += 2; if ( rc != 1 ) { INVALID_FORMAT; } rc = fread( (uint16_t*)&( res2 ),2,1,fp ); m_bytesRead += 2; if ( rc != 1 ) { INVALID_FORMAT; } rc = fread( (uint32_t*)&( pixoff ),4,1,fp ); m_bytesRead += 4; if ( rc != 1 ) { INVALID_FORMAT; } rc = fread( (uint32_t*)&( bmisize ),4,1,fp ); m_bytesRead += 4; if ( rc != 1 ) { INVALID_FORMAT; } rc = fread( (uint32_t *)&( bmWidth ),4,1,fp ); m_bytesRead += 4; if ( rc != 1 ) { INVALID_FORMAT; } rc = fread( (uint32_t*)&( bmHeight ),4,1,fp ); m_bytesRead += 4; if ( rc != 1 ) { INVALID_FORMAT; } rc = fread( (uint16_t*)&( bmPlanes ),2,1,fp ); m_bytesRead += 2; if ( rc != 1 ) { INVALID_FORMAT; } rc = fread( (uint16_t*)&( bmBitsPixel ),2,1,fp ); m_bytesRead += 2; if ( rc != 1 ) { INVALID_FORMAT; } rc = fread( (uint32_t*)&( compression ),4,1,fp ); m_bytesRead += 4; if ( rc != 1 ) { INVALID_FORMAT; } rc = fread( (uint32_t*)&( sizeimage ),4,1,fp ); m_bytesRead += 4; if ( rc != 1 ) { INVALID_FORMAT; } rc = fread( (uint32_t*)&( xscale ),4,1,fp ); m_bytesRead += 4; if ( rc != 1 ) { INVALID_FORMAT; } rc = fread( (uint32_t*)&( yscale ),4,1,fp ); m_bytesRead += 4; if ( rc != 1 ) { INVALID_FORMAT; } rc = fread( (uint32_t*)&( colors ),4,1,fp ); m_bytesRead += 4; if ( rc != 1 ) { INVALID_FORMAT; } rc = fread( (uint32_t*)&( impcol ),4,1,fp ); m_bytesRead += 4; if ( rc != 1 ) { INVALID_FORMAT; } if ( bmBitsPixel != 8 ) { g_FuncTable.m_pfnMessageBox( g_pWnd, "This is not an 8-bit image. GenSurf can't use it.", "Bitmap", eMB_OK, eMB_ICONWARNING ); fclose( fp ); return NULL; } if ( colors == 0 ) { colors = 1 << bmBitsPixel; } if ( bmBitsPixel != 24 ) { int i; for ( i = 0; i < colors; i++ ) { unsigned char r,g, b, dummy; rc = fread( &b, 1, 1, fp ); m_bytesRead++; if ( rc != 1 ) { INVALID_FORMAT; } rc = fread( &g, 1, 1, fp ); m_bytesRead++; if ( rc != 1 ) { INVALID_FORMAT; } rc = fread( &r, 1, 1, fp ); m_bytesRead++; if ( rc != 1 ) { INVALID_FORMAT; } rc = fread( &dummy, 1, 1, fp ); m_bytesRead++; if ( rc != 1 ) { INVALID_FORMAT; } } } if ( (long)m_bytesRead > pixoff ) { INVALID_FORMAT; } while ( (long)m_bytesRead < pixoff ) { char dummy; fread( &dummy,1,1,fp ); m_bytesRead++; } int w = bmWidth; int h = bmHeight; // set the output params image = (unsigned char*)malloc( w * h ); if ( image != NULL ) { unsigned char* outbuf = image; long row = 0; long rowOffset = 0; if ( compression == 0 ) { // BI_RGB for ( row = 0; row < bmHeight; row++ ) { // which row are we working on? rowOffset = (long unsigned)row * w; { // pixels are packed as 1 , 4 or 8 bit vals. need to unpack them int bit_count = 0; unsigned long mask = ( 1 << bmBitsPixel ) - 1; unsigned char inbyte = 0; for ( int col = 0; col < w; col++ ) { int pix = 0; // if we need another byte if ( bit_count <= 0 ) { bit_count = 8; if ( fread( &inbyte,1,1,fp ) != 1 ) { free( image ); INVALID_FORMAT; } m_bytesRead++; } // keep track of where we are in the bytes bit_count -= bmBitsPixel; pix = ( inbyte >> bit_count ) & mask; // lookup the color from the colormap - stuff it in our buffer // swap red and blue *( outbuf + rowOffset + col ) = pix; } // read DWORD padding while ( ( m_bytesRead - pixoff ) & 3 ) { char dummy; if ( fread( &dummy,1,1,fp ) != 1 ) { free( image ); INVALID_FORMAT; } m_bytesRead++; } } } } else // compression != 0 { int i, x = 0; unsigned char c, c1 = 0, *pp; row = 0; pp = outbuf; if ( bmBitsPixel == 8 ) { while ( row < bmHeight ) { c = getc( fp ); if ( c ) { // encoded mode c1 = getc( fp ); for ( i = 0; i < c; x++, i++ ) { *pp = c1; pp++; } } else { // c==0x00, escape codes c = getc( fp ); if ( c == 0x00 ) { // end of line row++; x = 0; pp = outbuf + row * bmWidth; } else if ( c == 0x01 ) { break; // end of pic } else if ( c == 0x02 ) { // delta c = getc( fp ); x += c; c = getc( fp ); row += c; pp = outbuf + x + row * bmWidth; } else // absolute mode { for ( i = 0; i < c; x++, i++ ) { c1 = getc( fp ); *pp = c1; pp++; } if ( c & 1 ) { getc( fp ); // odd length run: read an extra pad byte } } } } } else if ( bmBitsPixel == 4 ) { while ( row < bmHeight ) { c = getc( fp ); if ( c ) { // encoded mode c1 = getc( fp ); for ( i = 0; i < c; x++, i++ ) { *pp = ( i & 1 ) ? ( c1 & 0x0f ) : ( ( c1 >> 4 ) & 0x0f ); pp++; } } else { // c==0x00, escape codes c = getc( fp ); if ( c == 0x00 ) { // end of line row++; x = 0; pp = outbuf + bmHeight * bmWidth; } else if ( c == 0x01 ) { break; // end of pic } else if ( c == 0x02 ) { // delta c = getc( fp ); x += c; c = getc( fp ); row += c; pp = outbuf + x + row * bmWidth; } else // absolute mode { for ( i = 0; i < c; x++, i++ ) { if ( ( i & 1 ) == 0 ) { c1 = getc( fp ); } *pp = ( i & 1 ) ? ( c1 & 0x0f ) : ( ( c1 >> 4 ) & 0x0f ); pp++; } if ( ( ( c & 3 ) == 1 ) || ( ( c & 3 ) == 2 ) ) { getc( fp ); // odd length run: read an extra pad byte } } } } } } } fclose( fp ); gbmp.width = w; gbmp.height = h; if ( gbmp.colors ) { free( gbmp.colors ); } gbmp.colors = image; return image; } bool OpenBitmap(){ OpenBitmapFile(); if ( !gbmp.colors ) { char Text[256]; sprintf( Text, "Error opening %s", gbmp.name ); g_FuncTable.m_pfnMessageBox( g_pWnd, Text, "Bitmap", eMB_OK, eMB_ICONWARNING ); strcpy( gbmp.name, "" ); } if ( g_pWnd ) { gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "bmp_file" ) ), gbmp.name ); gtk_widget_set_sensitive( g_object_get_data( G_OBJECT( g_pWnd , "bmp_reload" ) ), strlen( gbmp.name ) ? TRUE : FALSE ); UpdatePreview( true ); } return ( gbmp.colors != NULL ); }