/* * PVVMUD a 3D MUD * Copyright (C) 1998-1999 Programvareverkstedet (pvv@pvv.org) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "pvvmud.H" #include #include #include #include "texture.H" #include "load_rgb.H" #include "exception.H" #include #define IMAGIC 0x01da #define IMAGIC_SWAP 0xda01 #define SWAP_SHORT_BYTES(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8)) #define SWAP_LONG_BYTES(x) (((((x) & 0xff) << 24) | (((x) & 0xff00) << 8)) | \ ((((x) & 0xff0000) >> 8) | (((x) & 0xff000000) >> 24))) typedef struct { unsigned short imagic; unsigned short type; unsigned short dim; unsigned short sizeX, sizeY, sizeZ; unsigned long min, max; unsigned long wasteBytes; char name[80]; unsigned long colorMap; FILE *file; unsigned char *tmp[5]; unsigned long rleEnd; unsigned long *rowStart; unsigned long *rowSize; } Image_RGB; static Image_RGB *ImageRGB_Open(char *fileName) { Image_RGB *image; unsigned long *rowStart, *rowSize, ulTmp; int x, i; image = (Image_RGB *)malloc(sizeof(Image_RGB)); if (image == NULL) { cdebug << "Out of memory!\n"; exit(-1); } if ((image->file = fopen(fileName, "rb")) == NULL) { perror(fileName); exit(-1); } /* * Read the image header */ fread(image, 1, 12, image->file); /* * Check byte order */ if (image->imagic == IMAGIC_SWAP) { image->type = SWAP_SHORT_BYTES(image->type); image->dim = SWAP_SHORT_BYTES(image->dim); image->sizeX = SWAP_SHORT_BYTES(image->sizeX); image->sizeY = SWAP_SHORT_BYTES(image->sizeY); image->sizeZ = SWAP_SHORT_BYTES(image->sizeZ); } for ( i = 0 ; i <= image->sizeZ ; i++ ) { image->tmp[i] = (unsigned char *)malloc(image->sizeX*256); if (image->tmp[i] == NULL ) { cdebug << "Out of memory!\n"; exit(-1); } } if ((image->type & 0xFF00) == 0x0100) /* RLE image */ { x = image->sizeY * image->sizeZ * sizeof(long); image->rowStart = (unsigned long *)malloc(x); image->rowSize = (unsigned long *)malloc(x); if (image->rowStart == NULL || image->rowSize == NULL) { cdebug << "Out of memory!\n"; exit(-1); } image->rleEnd = 512 + (2 * x); fseek(image->file, 512, SEEK_SET); fread(image->rowStart, 1, x, image->file); fread(image->rowSize, 1, x, image->file); if (image->imagic == IMAGIC_SWAP) { x /= sizeof(long); rowStart = image->rowStart; rowSize = image->rowSize; while (x--) { ulTmp = *rowStart; *rowStart++ = SWAP_LONG_BYTES(ulTmp); ulTmp = *rowSize; *rowSize++ = SWAP_LONG_BYTES(ulTmp); } } } return image; } static void ImageRGB_Close( Image_RGB *image) { int i; fclose(image->file); for ( i = 0 ; i <= image->sizeZ ; i++ ) free(image->tmp[i]); free(image); } static void ImageRGB_GetRow( Image_RGB *image, unsigned char *buf, int y, int z) { unsigned char *iPtr, *oPtr, pixel; int count; if ((image->type & 0xFF00) == 0x0100) /* RLE image */ { fseek(image->file, image->rowStart[y+z*image->sizeY], SEEK_SET); fread(image->tmp[0], 1, (unsigned int)image->rowSize[y+z*image->sizeY], image->file); iPtr = image->tmp[0]; oPtr = buf; while (1) { pixel = *iPtr++; count = (int)(pixel & 0x7F); if (!count) return; if (pixel & 0x80) { while (count--) { *oPtr++ = *iPtr++; } } else { pixel = *iPtr++; while (count--) { *oPtr++ = pixel; } } } } else /* verbatim image */ { fseek(image->file, 512+(y*image->sizeX)+(z*image->sizeX*image->sizeY), SEEK_SET); fread(buf, 1, image->sizeX, image->file); } } static void ImageRGB_GetRawData( Image_RGB *image, char *data) { int i, j, k; int remain; switch ( image->sizeZ ) { case 1: remain = image->sizeX % 4; break; case 2: remain = image->sizeX % 2; break; case 3: remain = (image->sizeX * 3) & 0x3; if (remain) remain = 4 - remain; break; case 4: remain = 0; break; } for (i = 0; i < image->sizeY; i++) { for ( k = 0; k < image->sizeZ ; k++ ) ImageRGB_GetRow(image, image->tmp[k+1], i, k); for (j = 0; j < image->sizeX; j++) for ( k = 1; k <= image->sizeZ ; k++ ) *data++ = *(image->tmp[k] + j); data += remain; } } void CTextureMap::loadRGB(char *fileName) { Image_RGB *image; IMAGE_RGB_t *final; int sx,ii,rgbIndex; unsigned char * rgbData; image = ImageRGB_Open(fileName); if (image == NULL){ throw new CException(); } final = (IMAGE_RGB_t *)malloc(sizeof(IMAGE_RGB_t)); if (final == NULL) { cdebug << "Out of memory!\n"; exit(-1); } final->imagic = image->imagic; final->type = image->type; final->dim = image->dim; final->sizeX = image->sizeX; final->sizeY = image->sizeY; final->sizeZ = image->sizeZ; /* * Round up so rows are long-word aligned */ sx = ( (image->sizeX) * (image->sizeZ) + 3) >> 2; rgbData = (unsigned char *)malloc( sx * image->sizeY * sizeof(unsigned int)); if (rgbData == NULL) { cdebug << "Out of memory!\n"; exit(-1); } final->data = (unsigned long *)malloc( image->sizeX * image->sizeY * sizeof(unsigned long)); if (final->data == NULL) { cdebug << "Out of memory!\n"; exit(-1); } ImageRGB_GetRawData(image, (char*)rgbData); ImageRGB_Close(image); m_width = final->sizeX; m_height = final->sizeY; rgbIndex = 0; for (ii = 0; ii < m_width*m_height; ii++){ final->data[ii] = ((DWORD)(rgbData[rgbIndex+2]) << 16) + ((DWORD)(rgbData[rgbIndex+1]) << 8) + (DWORD)(rgbData[rgbIndex]) + 0xFF000000; rgbIndex += 3; } m_data = (unsigned char*)final->data; free(final); free(rgbData); }