318 lines
7.5 KiB
C++
318 lines
7.5 KiB
C++
/*==========================================================================
|
|
*
|
|
* Copyright (C) 1996 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: loadppm.c
|
|
*
|
|
***************************************************************************/
|
|
|
|
#include "pch.cpp"
|
|
#pragma hdrstop
|
|
|
|
#include "util.h"
|
|
#include "loadppm.h"
|
|
|
|
#define MAXPATH 256
|
|
#define PATHSEP ';'
|
|
#define FILESEP '\\'
|
|
#define MAXCONTENTS 25
|
|
|
|
static int PathListInitialised = FALSE;
|
|
|
|
struct {
|
|
int count;
|
|
char *contents[MAXCONTENTS];
|
|
} PathList;
|
|
|
|
|
|
void
|
|
AddPathList(const char *path)
|
|
{
|
|
char *p;
|
|
char *elt;
|
|
int len;
|
|
|
|
while (path) {
|
|
p = strchr(path, PATHSEP);
|
|
if (p)
|
|
len = p - path;
|
|
else
|
|
len = lstrlen(path);
|
|
elt = (char *) malloc(len + 1);
|
|
if (elt == NULL)
|
|
return;
|
|
lstrcpyn(elt, path, len + 1);
|
|
elt[len] = '\0';
|
|
PathList.contents[PathList.count] = elt;
|
|
PathList.count++;
|
|
if (p)
|
|
path = p + 1;
|
|
else
|
|
path = NULL;
|
|
if (PathList.count == MAXCONTENTS)
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
|
|
#define RESPATH "Software\\Microsoft\\Direct3D"
|
|
static void
|
|
InitialisePathList()
|
|
{
|
|
long result;
|
|
HKEY key;
|
|
DWORD type, size;
|
|
static char buf[512];
|
|
char* path;
|
|
|
|
if (PathListInitialised)
|
|
return;
|
|
PathListInitialised = TRUE;
|
|
|
|
PathList.count = 0;
|
|
path = getenv("D3DPATH");
|
|
if (path != NULL) {
|
|
AddPathList(path);
|
|
return;
|
|
}
|
|
result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, RESPATH, 0, KEY_READ, &key);
|
|
if (result == ERROR_SUCCESS) {
|
|
size = sizeof(buf);
|
|
result = RegQueryValueEx(key, "D3D Path", NULL, &type, (LPBYTE) buf,
|
|
&size);
|
|
RegCloseKey(key);
|
|
if (result == ERROR_SUCCESS && type == REG_SZ)
|
|
AddPathList(buf);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Open a file using the current search path.
|
|
*/
|
|
FILE *
|
|
FindFile(const char *name, const char *mode)
|
|
{
|
|
FILE *fp;
|
|
char buf[MAXPATH];
|
|
static char filesep[] = {FILESEP, 0};
|
|
int i;
|
|
|
|
InitialisePathList();
|
|
|
|
fp = fopen(name, mode);
|
|
if (fp != NULL)
|
|
return fp;
|
|
|
|
for (i = 0; i < PathList.count; i++) {
|
|
lstrcpy(buf, PathList.contents[i]);
|
|
lstrcat(buf, filesep);
|
|
lstrcat(buf, name);
|
|
fp = fopen(buf, mode);
|
|
if (fp)
|
|
return fp;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void
|
|
ReleasePathList(void)
|
|
{
|
|
int i;
|
|
for (i = 0; i < PathList.count; i++) {
|
|
free(PathList.contents[i]);
|
|
PathList.contents[i] = NULL;
|
|
}
|
|
PathList.count = 0;
|
|
PathListInitialised = FALSE;
|
|
}
|
|
|
|
/*
|
|
* LoadPPM
|
|
* Loads a ppm file into memory
|
|
* Performs quantization if requested
|
|
*/
|
|
BOOL LoadPPM(LPCSTR pszFile, ImageFormat *pifDst, Image *pim)
|
|
{
|
|
int i;
|
|
FILE *pfile;
|
|
char achLine[100];
|
|
int nPixels;
|
|
int cbBytes;
|
|
int cbPixelSize;
|
|
BYTE *pbRgb, *pbFinal;
|
|
BYTE *pbSrc, *pbDst;
|
|
BOOL bSucc;
|
|
|
|
bSucc = FALSE;
|
|
|
|
pfile = FindFile(pszFile, "rb");
|
|
if (pfile == NULL)
|
|
{
|
|
Msg("LoadPPM: Cannot find %s.\n", pszFile);
|
|
return FALSE;
|
|
}
|
|
fgets(achLine, sizeof(achLine), pfile);
|
|
if (lstrcmp(achLine, "P6\n"))
|
|
{
|
|
Msg("LoadPPM: %s is not a PPM file.\n", pszFile);
|
|
goto EH_pfile;
|
|
}
|
|
|
|
/*
|
|
* Skip comment
|
|
*/
|
|
do
|
|
{
|
|
fgets(achLine, sizeof(achLine), pfile);
|
|
} while (achLine[0] == '#');
|
|
sscanf(achLine, "%d %d\n", &pim->uiWidth, &pim->uiHeight);
|
|
fgets(achLine, sizeof(achLine), pfile); /* skip next line */
|
|
|
|
cbPixelSize = (pifDst->nColorBits+7)/8;
|
|
nPixels = pim->uiWidth*pim->uiHeight;
|
|
cbBytes = nPixels*cbPixelSize;
|
|
|
|
// Allocate space for raw RGB data and final data
|
|
pbRgb = new BYTE[nPixels*3];
|
|
if (pbRgb == NULL)
|
|
{
|
|
Msg("LoadPPM: Unable to allocate memory.\n");
|
|
goto EH_pfile;
|
|
}
|
|
pbSrc = pbRgb;
|
|
|
|
pbFinal = new BYTE[cbBytes];
|
|
if (pbFinal == NULL)
|
|
{
|
|
Msg("LoadPPM: Unable to allocate memory.\n");
|
|
goto EH_pbRgb;
|
|
}
|
|
pbDst = pbFinal;
|
|
|
|
// Read in raw RGB data
|
|
fread(pbRgb, 3, nPixels, pfile);
|
|
|
|
/*
|
|
* If the surface is not 8-bit quantized, it's easy
|
|
*/
|
|
if (!pifDst->bQuantize)
|
|
{
|
|
ULONG *pul;
|
|
USHORT *pus;
|
|
ULONG ulTmp;
|
|
int iRedScale;
|
|
int iGreenScale;
|
|
int iBlueScale;
|
|
|
|
iRedScale = 255 / ((1 << pifDst->iRedBits)-1);
|
|
iGreenScale = 255 / ((1 << pifDst->iGreenBits)-1);
|
|
iBlueScale = 255 / ((1 << pifDst->iBlueBits)-1);
|
|
switch (pifDst->nColorBits)
|
|
{
|
|
case 32:
|
|
pul = (unsigned long *)pbDst;
|
|
for (i = 0; i < nPixels; i++)
|
|
{
|
|
*pul++ =
|
|
((((ULONG)*(pbSrc+0)) / iRedScale) <<
|
|
pifDst->iRedShift) |
|
|
((((ULONG)*(pbSrc+1)) / iGreenScale) <<
|
|
pifDst->iGreenShift) |
|
|
((((ULONG)*(pbSrc+2)) / iBlueScale) <<
|
|
pifDst->iBlueShift);
|
|
pbSrc += 3;
|
|
}
|
|
break;
|
|
case 24:
|
|
// Even though both source and destination are 24bpp
|
|
// the byte ordering may be different so we still need
|
|
// to do the shifts
|
|
for (i = 0; i < nPixels; i++)
|
|
{
|
|
ulTmp =
|
|
(((ULONG)*(pbSrc+0)) << pifDst->iRedShift) |
|
|
(((ULONG)*(pbSrc+1)) << pifDst->iGreenShift) |
|
|
(((ULONG)*(pbSrc+2)) << pifDst->iBlueShift);
|
|
pbSrc += 3;
|
|
*pbDst++ = *((BYTE *)&ulTmp+0);
|
|
*pbDst++ = *((BYTE *)&ulTmp+1);
|
|
*pbDst++ = *((BYTE *)&ulTmp+2);
|
|
}
|
|
break;
|
|
case 16:
|
|
pus = (unsigned short *)pbDst;
|
|
for (i = 0; i < nPixels; i++)
|
|
{
|
|
*pus++ =
|
|
((((USHORT)*(pbSrc+0)) / iRedScale) <<
|
|
pifDst->iRedShift) |
|
|
((((USHORT)*(pbSrc+1)) / iGreenScale) <<
|
|
pifDst->iGreenShift) |
|
|
((((USHORT)*(pbSrc+2)) / iBlueScale) <<
|
|
pifDst->iBlueShift);
|
|
pbSrc += 3;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
Msg("LoadPPM: Unknown pixel format.");
|
|
goto EH_pbFinal;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UINT uiIdx;
|
|
UINT nColors;
|
|
UINT nColMax;
|
|
D3DCOLOR dcol;
|
|
D3DCOLOR *pdcol;
|
|
|
|
/*
|
|
* Otherwise, we must palettize it
|
|
*/
|
|
nColMax = 1 << pifDst->nColorBits;
|
|
nColors = 0;
|
|
pdcol = pim->dcolPalette;
|
|
for (i = 0; i < nPixels; i++)
|
|
{
|
|
dcol = RGB_MAKE(*pbSrc, *(pbSrc+1), *(pbSrc+2));
|
|
pbSrc += 3;
|
|
for (uiIdx = 0; uiIdx < nColors; uiIdx++)
|
|
{
|
|
if (dcol == pdcol[uiIdx])
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if (uiIdx == nColors)
|
|
{
|
|
if (nColors == nColMax)
|
|
{
|
|
Msg("LoadPPM: Palette overflow in quantization.\n");
|
|
goto EH_pbFinal;
|
|
}
|
|
|
|
pdcol[nColors++] = dcol;
|
|
}
|
|
|
|
*pbDst++ = (BYTE)uiIdx;
|
|
}
|
|
|
|
pim->nColors = nColors;
|
|
}
|
|
|
|
pim->pvImage = pbFinal;
|
|
bSucc = TRUE;
|
|
|
|
EH_pbRgb:
|
|
delete [] pbRgb;
|
|
EH_pfile:
|
|
fclose(pfile);
|
|
return bSucc;
|
|
|
|
EH_pbFinal:
|
|
delete [] pbFinal;
|
|
goto EH_pbRgb;
|
|
}
|
|
|