281 lines
6.6 KiB
C
281 lines
6.6 KiB
C
/*
|
|
* 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 <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include "texture.H"
|
|
#include "load_rgb.H"
|
|
#include "exception.H"
|
|
#include <iostream.h>
|
|
|
|
#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);
|
|
}
|