2025-04-27 07:49:33 -04:00

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;
}