SSIMAGE.C

/******************************Module*Header*******************************\ 
* Module Name: ssimage.c
*
* Operations on .rgb files
*
* Copyright 1995 - 1998 Microsoft Corporation
*
\**************************************************************************/

#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "sscommon.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 _rawImageRec {
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;
HANDLE file;
unsigned char *tmp, *tmpR, *tmpG, *tmpB;
unsigned long rleEnd;
unsigned long *rowStart;
long *rowSize;
// !!! Hack to stick in a pointer to the resource data - shouldn't be
// a problem, since rgb files always have 512 byte header
unsigned char *data;
} rawImageRec;

static void RawImageClose(rawImageRec *raw);

/**************************************************************************\
*
* Hacked form of tk_RGBImageLoad(), for reading a .rgb file from a resource
*
* Copyright 1995 - 1998 Microsoft Corporation
*
\**************************************************************************/

#include <windows.h>
static rawImageRec *RawImageOpen( PVOID pv )
{
rawImageRec *raw;
unsigned long *rowStart, *rowSize, ulTmp;
int x;

raw = (rawImageRec *)malloc(sizeof(rawImageRec));
if (raw == NULL) {
return 0;
}

// Make a copy of the resource header, since we may be doing some byte
// swapping, and resources are read-only
*raw = *((rawImageRec *) pv);

if (raw->imagic == IMAGIC_SWAP) {
raw->type = SWAP_SHORT_BYTES(raw->type);
raw->dim = SWAP_SHORT_BYTES(raw->dim);
raw->sizeX = SWAP_SHORT_BYTES(raw->sizeX);
raw->sizeY = SWAP_SHORT_BYTES(raw->sizeY);
raw->sizeZ = SWAP_SHORT_BYTES(raw->sizeZ);
}

raw->tmp = (unsigned char *)malloc(raw->sizeX*256);
raw->tmpR = (unsigned char *)malloc(raw->sizeX*256);
raw->tmpG = (unsigned char *)malloc(raw->sizeX*256);
raw->tmpB = (unsigned char *)malloc(raw->sizeX*256);
if (raw->tmp == NULL || raw->tmpR == NULL || raw->tmpG == NULL ||
raw->tmpB == NULL) {
RawImageClose(raw);
return 0;
}

if ((raw->type & 0xFF00) == 0x0100) {
x = raw->sizeY * raw->sizeZ * sizeof(long);
raw->rowStart = (unsigned long *)malloc(x);
raw->rowSize = (long *)malloc(x);
if (raw->rowStart == NULL || raw->rowSize == NULL) {
RawImageClose(raw);
return 0;
}
raw->rleEnd = 512 + (2 * x);

raw->data = ((unsigned char *) pv);
RtlCopyMemory( raw->rowStart, raw->data + 512, x );
RtlCopyMemory( raw->rowSize, raw->data + 512 + x, x );

if (raw->imagic == IMAGIC_SWAP) {
x /= sizeof(long);
rowStart = raw->rowStart;
rowSize = (unsigned long *) raw->rowSize;
while (x--) {
ulTmp = *rowStart;
*rowStart++ = SWAP_LONG_BYTES(ulTmp);
ulTmp = *rowSize;
*rowSize++ = SWAP_LONG_BYTES(ulTmp);
}
}
}
return raw;
}

static void RawImageClose(rawImageRec *raw)
{
if( !raw )
return;
if( raw->tmp ) free(raw->tmp);
if( raw->tmpR ) free(raw->tmpR);
if( raw->tmpG ) free(raw->tmpG);
if( raw->tmpB ) free(raw->tmpB);
free(raw);
}

static void RawImageGetRow(rawImageRec *raw, unsigned char *buf, int y, int z)
{
unsigned char *iPtr, *oPtr, pixel;
int count;

if ((raw->type & 0xFF00) == 0x0100) {
RtlCopyMemory(raw->tmp, raw->data + raw->rowStart[y+z*raw->sizeY],
(unsigned int)raw->rowSize[y+z*raw->sizeY] );
iPtr = raw->tmp;
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 {
iPtr = raw->data + 512 + (y*raw->sizeX)+(z*raw->sizeX*raw->sizeY);
RtlCopyMemory( buf, iPtr, raw->sizeX );
}
}

static void RawImageGetData(rawImageRec *raw, TEXTURE *ptex)
{
unsigned char *ptr;
int i, j;

ptex->data = (unsigned char *)malloc((raw->sizeX+1)*(raw->sizeY+1)*4);
if (ptex->data == NULL) {
return;
}

ptr = ptex->data;
for (i = 0; i < raw->sizeY; i++) {
RawImageGetRow(raw, raw->tmpR, i, 0);
RawImageGetRow(raw, raw->tmpG, i, 1);
RawImageGetRow(raw, raw->tmpB, i, 2);
for (j = 0; j < raw->sizeX; j++) {
*ptr++ = *(raw->tmpR + j);
*ptr++ = *(raw->tmpG + j);
*ptr++ = *(raw->tmpB + j);
}
}
}

BOOL ss_RGBImageLoad( PVOID pv, TEXTURE *ptex )
{
rawImageRec *raw;

if( !(raw = RawImageOpen( pv )) )
return FALSE;

ptex->width = raw->sizeX;
ptex->height = raw->sizeY;
ptex->format = GL_RGB;
ptex->components = 3;
ptex->pal_size = 0;
ptex->pal = NULL;
RawImageGetData(raw, ptex);
RawImageClose(raw);
return TRUE;
}

/******************************Public*Routine******************************\
*
* bVerifyRGB
*
* Stripped down version of tkRGBImageLoadAW that verifies that an rgb
* file is valid and, if so, returns the bitmap dimensions.
*
* Returns:
* TRUE if valid rgb file; otherwise, FALSE.
*
\**************************************************************************/

BOOL
bVerifyRGB(LPTSTR pszFileName, ISIZE *pSize )
{
rawImageRec *raw;
DWORD dwBytesRead;
BOOL bRet = FALSE;

raw = (rawImageRec *)
LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT, sizeof(rawImageRec) );

if (raw == NULL) {
goto bVerifyRGB_cleanup;
}

raw->file = CreateFile((LPTSTR) pszFileName, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, 0, 0);

if (raw->file == INVALID_HANDLE_VALUE) {
goto bVerifyRGB_cleanup;
}

ReadFile(raw->file, (LPVOID) raw, 12, &dwBytesRead, (LPOVERLAPPED) NULL);

if( raw->imagic == IMAGIC_SWAP ) {
raw->sizeX = SWAP_SHORT_BYTES(raw->sizeX);
raw->sizeY = SWAP_SHORT_BYTES(raw->sizeY);
bRet = TRUE;
} else if( raw->imagic == IMAGIC)
bRet = TRUE;

bVerifyRGB_cleanup:

if( bRet && pSize ) {
pSize->width = raw->sizeX;
pSize->height = raw->sizeY;
}

if( raw->file )
CloseHandle( raw->file );

if( raw )
LocalFree( raw );

return bRet;
}