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