780 lines
25 KiB
C++
780 lines
25 KiB
C++
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include "tc_pluginapi.h"
|
|
#include "tc_plugininternal.h"
|
|
#include "compressonator.h"
|
|
#include "tga.h"
|
|
|
|
CMIPS *TGA_CMips;
|
|
TGA_FileSaveParams g_FileSaveParams;
|
|
|
|
#ifdef BUILD_AS_PLUGIN_DLL
|
|
DECLARE_PLUGIN(Plugin_TGA)
|
|
SET_PLUGIN_TYPE("IMAGE")
|
|
SET_PLUGIN_NAME("TGA")
|
|
#else
|
|
void *make_Plugin_TGA() {
|
|
return new Plugin_TGA;
|
|
}
|
|
#endif
|
|
|
|
#ifndef _WIN32
|
|
typedef CMP_DWORD* LPDWORD;
|
|
#endif
|
|
/*
|
|
..\.\..\..\..\..\Common\Lib\Ext\OpenEXR\v1.4.0\lib_MT\$(Configuration)\$(Platform);
|
|
zlibstatic_d.lib
|
|
*/
|
|
|
|
#pragma comment(lib,"advapi32.lib") // for RegCloseKey and other Reg calls ...
|
|
|
|
Plugin_TGA::Plugin_TGA() {
|
|
//MessageBox(0,"Plugin_TGA","Plugin_TGA",MB_OK);
|
|
}
|
|
|
|
Plugin_TGA::~Plugin_TGA() {
|
|
//MessageBox(0,"Plugin_TGA","~Plugin_TGA",MB_OK);
|
|
}
|
|
|
|
int Plugin_TGA::TC_PluginSetSharedIO(void* Shared) {
|
|
if (Shared) {
|
|
TGA_CMips = static_cast<CMIPS *>(Shared);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
|
|
int Plugin_TGA::TC_PluginGetVersion(TC_PluginVersion* pPluginVersion) {
|
|
//MessageBox(0,"TC_PluginGetVersion","Plugin_TGA",MB_OK);
|
|
#ifdef _WIN32
|
|
pPluginVersion->guid = g_GUID;
|
|
#endif
|
|
pPluginVersion->dwAPIVersionMajor = TC_API_VERSION_MAJOR;
|
|
pPluginVersion->dwAPIVersionMinor = TC_API_VERSION_MINOR;
|
|
pPluginVersion->dwPluginVersionMajor = TC_PLUGIN_VERSION_MAJOR;
|
|
pPluginVersion->dwPluginVersionMinor = TC_PLUGIN_VERSION_MINOR;
|
|
return 0;
|
|
}
|
|
|
|
int Plugin_TGA::TC_PluginFileLoadTexture(const char* pszFilename, CMP_Texture *srcTexture) {
|
|
//MessageBox(0,"TC_PluginFileLoadTexture srcTexture","Plugin_TGA",MB_OK);
|
|
return 0;
|
|
|
|
}
|
|
|
|
int Plugin_TGA::TC_PluginFileSaveTexture(const char* pszFilename, CMP_Texture *srcTexture) {
|
|
//MessageBox(0,"TC_PluginFileSaveTexture srcTexture","Plugin_TGA",MB_OK);
|
|
return 0;
|
|
}
|
|
|
|
// #include "loadtga.h"
|
|
|
|
int Plugin_TGA::TC_PluginFileLoadTexture(const char* pszFilename, MipSet* pMipSet) {
|
|
CMP_CMIPS lCMips;
|
|
if (!TGA_CMips) {
|
|
TGA_CMips = &lCMips;
|
|
}
|
|
|
|
// ATI code
|
|
FILE* pFile = NULL;
|
|
pFile = fopen(pszFilename, ("rb"));
|
|
if(pFile == NULL) {
|
|
if (TGA_CMips)
|
|
TGA_CMips->PrintError(("Error(%d): TGA Plugin ID(%d) opening file = %s "), EL_Error, IDS_ERROR_FILE_OPEN, pszFilename);
|
|
return -1;
|
|
}
|
|
|
|
// Read the header
|
|
TGAHeader header;
|
|
if(fread(&header, sizeof(TGAHeader), 1, pFile) != 1) {
|
|
if (TGA_CMips)
|
|
TGA_CMips->PrintError(("Error(%d): TGA Plugin ID(%d) invalid TGA header. Filename = %s "), EL_Error, IDS_ERROR_NOT_TGA, pszFilename);
|
|
fclose(pFile);
|
|
return -1;
|
|
}
|
|
|
|
// Skip the ID field
|
|
if(header.cIDFieldLength)
|
|
fseek(pFile, header.cIDFieldLength, SEEK_CUR);
|
|
|
|
if(!TGA_CMips->AllocateMipSet(pMipSet, CF_8bit, TDT_ARGB, TT_2D, header.nWidth, header.nHeight, 1)) { // depthsupport, what should nDepth be set as here?
|
|
fclose(pFile);
|
|
return PE_Unknown;
|
|
}
|
|
|
|
if(header.cColorMapType == 0) {
|
|
if(header.cImageType == ImageType_ARGB8888 && header.cColorDepth == 32)
|
|
return LoadTGA_ARGB8888(pFile, pMipSet, header);
|
|
else if(header.cImageType == ImageType_ARGB8888_RLE && header.cColorDepth == 32)
|
|
return LoadTGA_ARGB8888_RLE(pFile, pMipSet, header);
|
|
else if(header.cImageType == ImageType_ARGB8888 && header.cColorDepth == 24)
|
|
return LoadTGA_RGB888(pFile, pMipSet, header);
|
|
else if(header.cImageType == ImageType_ARGB8888_RLE && header.cColorDepth == 24)
|
|
return LoadTGA_RGB888_RLE(pFile, pMipSet, header);
|
|
else if(header.cImageType == ImageType_G8 && header.cColorDepth == 8)
|
|
return LoadTGA_G8(pFile, pMipSet, header);
|
|
else if(header.cImageType == ImageType_G8_RLE && header.cColorDepth == 8)
|
|
return LoadTGA_G8_RLE(pFile, pMipSet, header);
|
|
}
|
|
|
|
if (TGA_CMips)
|
|
TGA_CMips->PrintError(("Error(%d): TGA Plugin ID(%d) unsupported type Filename = %s "), EL_Error, IDS_ERROR_UNSUPPORTED_TYPE, pszFilename);
|
|
fclose(pFile);
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
int Plugin_TGA::TC_PluginFileSaveTexture(const char* pszFilename, MipSet* pMipSet) {
|
|
CMP_CMIPS lCMips;
|
|
if (!TGA_CMips) {
|
|
TGA_CMips = &lCMips;
|
|
}
|
|
assert(pszFilename);
|
|
assert(pMipSet);
|
|
|
|
FILE* pFile = NULL;
|
|
pFile = fopen(pszFilename, ("wb"));
|
|
if(pFile == NULL) {
|
|
if (TGA_CMips)
|
|
TGA_CMips->PrintError(("Error(%d): TGA Plugin ID(%d) saving file = %s "), EL_Error, IDS_ERROR_FILE_OPEN, pszFilename);
|
|
return -1;
|
|
}
|
|
|
|
TGAHeader header;
|
|
memset(&header, 0, sizeof(header));
|
|
switch(pMipSet->m_dwFourCC) {
|
|
case CMP_MAKEFOURCC('G', '8', ' ', ' '):
|
|
header.cImageType = ImageType_G8_RLE;
|
|
header.cColorDepth = 8;
|
|
break;
|
|
case 0: // Not a FourCC texture
|
|
default:
|
|
if(pMipSet->m_TextureDataType == TDT_ARGB) {
|
|
header.cColorDepth = 32;
|
|
header.cFormatFlags = 0x8;
|
|
} else
|
|
header.cColorDepth = 24;
|
|
header.cImageType = ImageType_ARGB8888;
|
|
break;
|
|
}
|
|
|
|
// napatel need to add this somehow!
|
|
//if(pTGAFileSaveParams->bRLECompressed)
|
|
// header.cImageType |= 0x8;
|
|
|
|
header.nWidth = static_cast<short>(pMipSet->m_nWidth);
|
|
header.nHeight = static_cast<short>(pMipSet->m_nHeight);
|
|
|
|
fwrite(&header, sizeof(header), 1, pFile);
|
|
|
|
if(header.cImageType == ImageType_G8)
|
|
return SaveTGA_G8(pFile, pMipSet);
|
|
else if(header.cImageType == ImageType_G8_RLE)
|
|
return SaveTGA_G8_RLE(pFile, pMipSet);
|
|
else if(header.cImageType == ImageType_ARGB8888 && pMipSet->m_TextureDataType == TDT_ARGB)
|
|
return SaveTGA_ARGB8888(pFile, pMipSet);
|
|
else if(header.cImageType == ImageType_ARGB8888_RLE && pMipSet->m_TextureDataType == TDT_ARGB)
|
|
return SaveTGA_ARGB8888_RLE(pFile, pMipSet);
|
|
else if(header.cImageType == ImageType_ARGB8888 && pMipSet->m_TextureDataType == TDT_XRGB)
|
|
return SaveTGA_RGB888(pFile, pMipSet);
|
|
else if(header.cImageType == ImageType_ARGB8888_RLE && pMipSet->m_TextureDataType == TDT_XRGB)
|
|
return SaveTGA_RGB888_RLE(pFile, pMipSet);
|
|
|
|
if (TGA_CMips)
|
|
TGA_CMips->PrintError(("Error(%d): TGA Plugin ID(%d) unsupported type Filename = %s "), EL_Error, IDS_ERROR_UNSUPPORTED_TYPE, pszFilename);
|
|
fclose(pFile);
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
//---------------- TGA Code -----------------------------------
|
|
|
|
|
|
TC_PluginError LoadTGA_ARGB8888(FILE* pFile, MipSet* pMipSet, TGAHeader& Header) {
|
|
if(!TGA_CMips->AllocateMipLevelData(TGA_CMips->GetMipLevel(pMipSet, 0), Header.nWidth, Header.nHeight, CF_8bit, TDT_ARGB))
|
|
return PE_Unknown;
|
|
|
|
pMipSet->m_ChannelFormat = CF_8bit;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
pMipSet->m_dwFourCC = 0;
|
|
pMipSet->m_dwFourCC2 = 0;
|
|
pMipSet->m_format = CMP_FORMAT_ARGB_8888;
|
|
pMipSet->m_nMipLevels = 1;
|
|
|
|
// Allocate a temporary buffer and read the bitmap data into it
|
|
CMP_DWORD dwSize = pMipSet->m_nWidth * pMipSet->m_nHeight * sizeof(CMP_COLOR);
|
|
unsigned char* pTempData = static_cast<unsigned char*>(malloc(dwSize));
|
|
fread(pTempData, dwSize, 1, pFile);
|
|
fclose(pFile);
|
|
|
|
CMP_BYTE* pTempPtr = pTempData;
|
|
|
|
int nStart, nEnd, nIncrement;
|
|
// Bottom up ?
|
|
if(Header.cFormatFlags & 0x20) {
|
|
nStart = 0;
|
|
nEnd = pMipSet->m_nHeight;
|
|
nIncrement = 1;
|
|
} else {
|
|
nStart = pMipSet->m_nHeight-1;
|
|
nEnd = -1;
|
|
nIncrement = -1;
|
|
}
|
|
|
|
CMP_BYTE nBlue ;
|
|
CMP_BYTE nGreen;
|
|
CMP_BYTE nRed ;
|
|
CMP_BYTE nAlpha;
|
|
|
|
for(int j = nStart; j != nEnd; j+= nIncrement) {
|
|
CMP_BYTE* pData = (CMP_BYTE*) (TGA_CMips->GetMipLevel(pMipSet, 0)->m_pbData + (j * pMipSet->m_nWidth * sizeof(CMP_COLOR)));
|
|
for(int i=0; i < pMipSet->m_nWidth; i++) {
|
|
// Note MIPSet is RGBA
|
|
// TGA is saved as BGRA
|
|
nBlue = *pTempPtr++;
|
|
nGreen = *pTempPtr++;
|
|
nRed = *pTempPtr++;
|
|
nAlpha = *pTempPtr++;
|
|
|
|
// printf("{%d,%d,%d,%d}\n", nRed, nGreen, nBlue, nAlpha);
|
|
|
|
*pData++ = nRed;
|
|
*pData++ = nGreen;
|
|
*pData++ = nBlue;
|
|
*pData++ = nAlpha;
|
|
|
|
|
|
}
|
|
}
|
|
|
|
free(pTempData);
|
|
|
|
return PE_OK;
|
|
}
|
|
|
|
TC_PluginError LoadTGA_ARGB8888_RLE(FILE* pFile, MipSet* pMipSet, TGAHeader& Header) {
|
|
if(!TGA_CMips->AllocateMipLevelData(TGA_CMips->GetMipLevel(pMipSet, 0), Header.nWidth, Header.nHeight, CF_8bit, TDT_ARGB))
|
|
return PE_Unknown;
|
|
|
|
pMipSet->m_ChannelFormat = CF_8bit;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
pMipSet->m_dwFourCC = 0;
|
|
pMipSet->m_dwFourCC2 = 0;
|
|
pMipSet->m_format = CMP_FORMAT_ARGB_8888;
|
|
pMipSet->m_nMipLevels = 1;
|
|
|
|
// Allocate a temporary buffer and read the bitmap data into it
|
|
long lCurrPos = ftell(pFile);
|
|
fseek(pFile, 0, SEEK_END);
|
|
long lEndPos = ftell(pFile);
|
|
fseek(pFile, lCurrPos, SEEK_SET);
|
|
CMP_DWORD dwTempSize = lEndPos - lCurrPos;
|
|
unsigned char* pTempData = static_cast<unsigned char*>(malloc(dwTempSize));
|
|
fread(pTempData, dwTempSize, 1, pFile);
|
|
fclose(pFile);
|
|
|
|
CMP_DWORD dwPitch = pMipSet->m_nWidth * sizeof(CMP_COLOR);
|
|
CMP_BYTE* pTempPtr = pTempData;
|
|
|
|
int nStart, nEnd, nIncrement;
|
|
// Bottom up ?
|
|
if(Header.cFormatFlags & 0x20) {
|
|
nStart = 0;
|
|
nEnd = pMipSet->m_nHeight;
|
|
nIncrement = 1;
|
|
} else {
|
|
nStart = pMipSet->m_nHeight-1;
|
|
nEnd = -1;
|
|
nIncrement = -1;
|
|
}
|
|
|
|
for(int j = nStart; j != nEnd; j+= nIncrement) {
|
|
CMP_BYTE* pData = (CMP_BYTE*) (TGA_CMips->GetMipLevel(pMipSet, 0)->m_pbData + (j * dwPitch));
|
|
|
|
int nColumn =0;
|
|
while(nColumn < pMipSet->m_nWidth) {
|
|
unsigned char nLength = *pTempPtr++;
|
|
if(nLength & 0x80) {
|
|
int nRepeat = nLength - 0x7f;
|
|
CMP_BYTE nBlue = *pTempPtr++;
|
|
CMP_BYTE nGreen = *pTempPtr++;
|
|
CMP_BYTE nRed = *pTempPtr++;
|
|
CMP_BYTE nAlpha = *pTempPtr++;
|
|
|
|
while(nRepeat && nColumn < pMipSet->m_nWidth) {
|
|
*pData++ = nRed;
|
|
*pData++ = nGreen;
|
|
*pData++ = nBlue;
|
|
*pData++ = nAlpha;
|
|
nColumn++;
|
|
nRepeat--;
|
|
}
|
|
|
|
} else {
|
|
int nRepeat = nLength+1;
|
|
while(nRepeat && nColumn < pMipSet->m_nWidth) {
|
|
CMP_BYTE nBlue = *pTempPtr++;
|
|
CMP_BYTE nGreen = *pTempPtr++;
|
|
CMP_BYTE nRed = *pTempPtr++;
|
|
CMP_BYTE nAlpha = *pTempPtr++;
|
|
*pData++ = nRed;
|
|
*pData++ = nGreen;
|
|
*pData++ = nBlue;
|
|
*pData++ = nAlpha;
|
|
nColumn++;
|
|
nRepeat--;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
free(pTempData);
|
|
|
|
return PE_OK;
|
|
}
|
|
|
|
TC_PluginError LoadTGA_RGB888(FILE* pFile, MipSet* pMipSet, TGAHeader& Header) {
|
|
if(!TGA_CMips->AllocateMipLevelData(TGA_CMips->GetMipLevel(pMipSet, 0), Header.nWidth, Header.nHeight, CF_8bit, TDT_ARGB))
|
|
return PE_Unknown;
|
|
|
|
pMipSet->m_ChannelFormat = CF_8bit;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
pMipSet->m_dwFourCC = 0;
|
|
pMipSet->m_dwFourCC2 = 0;
|
|
pMipSet->m_nMipLevels = 1;
|
|
pMipSet->m_format = CMP_FORMAT_ARGB_8888;
|
|
|
|
// Allocate a temporary buffer and read the bitmap data into it
|
|
CMP_DWORD dwSize = pMipSet->m_nWidth * pMipSet->m_nHeight * 3;
|
|
unsigned char* pTempData = static_cast<unsigned char*>(malloc(dwSize));
|
|
fread(pTempData, dwSize, 1, pFile);
|
|
fclose(pFile);
|
|
|
|
CMP_BYTE* pTempPtr = pTempData;
|
|
|
|
int nStart, nEnd, nIncrement;
|
|
// Bottom up ?
|
|
if(Header.cFormatFlags & 0x20) {
|
|
nStart = 0;
|
|
nEnd = pMipSet->m_nHeight;
|
|
nIncrement = 1;
|
|
} else {
|
|
nStart = pMipSet->m_nHeight-1;
|
|
nEnd = -1;
|
|
nIncrement = -1;
|
|
}
|
|
|
|
CMP_BYTE nBlue;
|
|
CMP_BYTE nGreen;
|
|
CMP_BYTE nRed;
|
|
|
|
for(int j = nStart; j != nEnd; j+= nIncrement) {
|
|
CMP_BYTE* pData = (CMP_BYTE*) (TGA_CMips->GetMipLevel(pMipSet, 0)->m_pbData + (j * pMipSet->m_nWidth * sizeof(CMP_COLOR)));
|
|
for(int i=0; i < pMipSet->m_nWidth; i++) {
|
|
nBlue = *pTempPtr++;
|
|
nGreen = *pTempPtr++;
|
|
nRed = *pTempPtr++;
|
|
|
|
*pData++ = nRed;
|
|
*pData++ = nGreen;
|
|
*pData++ = nBlue;
|
|
*pData++ = 0xff;
|
|
}
|
|
}
|
|
|
|
free(pTempData);
|
|
|
|
return PE_OK;
|
|
}
|
|
|
|
TC_PluginError LoadTGA_RGB888_RLE(FILE* pFile, MipSet* pMipSet, TGAHeader& Header) {
|
|
if(!TGA_CMips->AllocateMipLevelData(TGA_CMips->GetMipLevel(pMipSet, 0), Header.nWidth, Header.nHeight, CF_8bit, TDT_ARGB))
|
|
return PE_Unknown;
|
|
|
|
pMipSet->m_ChannelFormat = CF_8bit;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
pMipSet->m_dwFourCC = 0;
|
|
pMipSet->m_dwFourCC2 = 0;
|
|
pMipSet->m_nMipLevels = 1;
|
|
pMipSet->m_format = CMP_FORMAT_ARGB_8888;
|
|
|
|
// Allocate a temporary buffer and read the bitmap data into it
|
|
long lCurrPos = ftell(pFile);
|
|
fseek(pFile, 0, SEEK_END);
|
|
long lEndPos = ftell(pFile);
|
|
fseek(pFile, lCurrPos, SEEK_SET);
|
|
CMP_DWORD dwTempSize = lEndPos - lCurrPos;
|
|
unsigned char* pTempData = static_cast<unsigned char*>(malloc(dwTempSize));
|
|
fread(pTempData, dwTempSize, 1, pFile);
|
|
fclose(pFile);
|
|
|
|
CMP_BYTE* pTempPtr = pTempData;
|
|
CMP_DWORD dwPitchOut = pMipSet->m_nWidth * sizeof(CMP_COLOR);
|
|
|
|
int nStart, nEnd, nIncrement;
|
|
// Bottom up ?
|
|
if(Header.cFormatFlags & 0x20) {
|
|
nStart = 0;
|
|
nEnd = pMipSet->m_nHeight;
|
|
nIncrement = 1;
|
|
} else {
|
|
nStart = pMipSet->m_nHeight-1;
|
|
nEnd = -1;
|
|
nIncrement = -1;
|
|
}
|
|
|
|
unsigned char nRepeat = 0;
|
|
unsigned char nLength = 0;
|
|
for(int j = nStart; j != nEnd; j+= nIncrement) {
|
|
CMP_BYTE* pData = (CMP_BYTE*) (TGA_CMips->GetMipLevel(pMipSet, 0)->m_pbData + (j * dwPitchOut));
|
|
|
|
int nColumn =0;
|
|
while(nColumn < pMipSet->m_nWidth) {
|
|
if(nRepeat == 0) {
|
|
nLength = *pTempPtr++;
|
|
nRepeat = (nLength & 0x7f) + 1;
|
|
}
|
|
|
|
if(nLength & 0x80) {
|
|
CMP_BYTE nBlue = *pTempPtr++;
|
|
CMP_BYTE nGreen = *pTempPtr++;
|
|
CMP_BYTE nRed = *pTempPtr++;
|
|
while(nRepeat && nColumn < pMipSet->m_nWidth) {
|
|
*pData++ = nRed;
|
|
*pData++ = nGreen;
|
|
*pData++ = nBlue;
|
|
*pData++ = 0xff;
|
|
nColumn++;
|
|
nRepeat--;
|
|
}
|
|
} else {
|
|
while(nRepeat && nColumn < pMipSet->m_nWidth) {
|
|
CMP_BYTE nBlue = *pTempPtr++;
|
|
CMP_BYTE nGreen = *pTempPtr++;
|
|
CMP_BYTE nRed = *pTempPtr++;
|
|
*pData++ = nRed;
|
|
*pData++ = nGreen;
|
|
*pData++ = nBlue;
|
|
*pData++ = 0xff;
|
|
nColumn++;
|
|
nRepeat--;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
free(pTempData);
|
|
|
|
return PE_OK;
|
|
}
|
|
|
|
TC_PluginError LoadTGA_G8(FILE* pFile, MipSet* pMipSet, TGAHeader& Header) {
|
|
if(!TGA_CMips->AllocateCompressedMipLevelData(TGA_CMips->GetMipLevel(pMipSet, 0), Header.nWidth, Header.nHeight, Header.nWidth * Header.nHeight))
|
|
return PE_Unknown;
|
|
|
|
pMipSet->m_ChannelFormat = CF_Compressed;
|
|
pMipSet->m_TextureDataType = TDT_XRGB;
|
|
pMipSet->m_dwFourCC = CMP_MAKEFOURCC('G', '8', ' ', ' ');
|
|
pMipSet->m_dwFourCC2 = 0;
|
|
pMipSet->m_nMipLevels = 1;
|
|
|
|
// Allocate a temporary buffer and read the bitmap data into it
|
|
CMP_DWORD dwSize = pMipSet->m_nWidth * pMipSet->m_nHeight * sizeof(CMP_BYTE);
|
|
unsigned char* pTempData = static_cast<unsigned char*>(malloc(dwSize));
|
|
fread(pTempData, dwSize, 1, pFile);
|
|
fclose(pFile);
|
|
|
|
CMP_BYTE* pTempPtr = pTempData;
|
|
|
|
int nStart, nEnd, nIncrement;
|
|
// Bottom up ?
|
|
if(Header.cFormatFlags & 0x20) {
|
|
nStart = 0;
|
|
nEnd = pMipSet->m_nHeight;
|
|
nIncrement = 1;
|
|
} else {
|
|
nStart = pMipSet->m_nHeight-1;
|
|
nEnd = -1;
|
|
nIncrement = -1;
|
|
}
|
|
|
|
for(int j = nStart; j != nEnd; j+= nIncrement) {
|
|
CMP_BYTE* pData = (CMP_BYTE*) (TGA_CMips->GetMipLevel(pMipSet, 0)->m_pbData + (j * pMipSet->m_nWidth));
|
|
memcpy(pData, pTempPtr, pMipSet->m_nWidth);
|
|
pTempPtr += pMipSet->m_nWidth;
|
|
}
|
|
|
|
free(pTempData);
|
|
|
|
return PE_OK;
|
|
}
|
|
|
|
TC_PluginError LoadTGA_G8_RLE(FILE* pFile, MipSet* pMipSet, TGAHeader& Header) {
|
|
if(!TGA_CMips->AllocateMipLevelData(TGA_CMips->GetMipLevel(pMipSet, 0), Header.nWidth, Header.nHeight, CF_8bit, TDT_ARGB))
|
|
return PE_Unknown;
|
|
|
|
pMipSet->m_ChannelFormat = CF_8bit;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
pMipSet->m_dwFourCC = 0;
|
|
pMipSet->m_dwFourCC2 = 0;
|
|
pMipSet->m_nMipLevels = 1;
|
|
pMipSet->m_format = CMP_FORMAT_ARGB_8888;
|
|
|
|
// Allocate a temporary buffer and read the bitmap data into it
|
|
long lCurrPos = ftell(pFile);
|
|
fseek(pFile, 0, SEEK_END);
|
|
long lEndPos = ftell(pFile);
|
|
fseek(pFile, lCurrPos, SEEK_SET);
|
|
CMP_DWORD dwTempSize = lEndPos - lCurrPos;
|
|
unsigned char* pTempData = static_cast<unsigned char*>(malloc(dwTempSize));
|
|
fread(pTempData, dwTempSize, 1, pFile);
|
|
fclose(pFile);
|
|
|
|
CMP_BYTE* pTempPtr = pTempData;
|
|
|
|
int nStart, nEnd, nIncrement;
|
|
// Bottom up ?
|
|
if(Header.cFormatFlags & 0x20) {
|
|
nStart = 0;
|
|
nEnd = pMipSet->m_nHeight;
|
|
nIncrement = 1;
|
|
} else {
|
|
nStart = pMipSet->m_nHeight-1;
|
|
nEnd = -1;
|
|
nIncrement = -1;
|
|
}
|
|
|
|
for(int j = nStart; j != nEnd; j+= nIncrement) {
|
|
CMP_BYTE* pData = (CMP_BYTE*) (TGA_CMips->GetMipLevel(pMipSet, 0)->m_pbData + (j * pMipSet->m_nWidth * sizeof(CMP_COLOR)));
|
|
|
|
int nColumn =0;
|
|
while(nColumn < pMipSet->m_nWidth) {
|
|
unsigned char nLength = *pTempPtr++;
|
|
if(nLength & 0x80) {
|
|
int nRepeat = nLength - 0x7f;
|
|
CMP_BYTE gray = *pTempPtr++;
|
|
while(nRepeat && nColumn < pMipSet->m_nWidth) {
|
|
*pData++ = gray;
|
|
*pData++ = gray;
|
|
*pData++ = gray;
|
|
*pData++ = 0xff;
|
|
nColumn++;
|
|
nRepeat--;
|
|
}
|
|
} else {
|
|
int nRepeat = nLength+1;
|
|
CMP_BYTE gray = *pTempPtr++;
|
|
while(nRepeat && nColumn < pMipSet->m_nWidth) {
|
|
*pData++ = gray;
|
|
*pData++ = gray;
|
|
*pData++ = gray;
|
|
*pData++ = 0xff;
|
|
nColumn++;
|
|
nRepeat--;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
free(pTempData);
|
|
|
|
return PE_OK;
|
|
}
|
|
|
|
CMP_BYTE CalcRunLength(CMP_BYTE* pThis, CMP_BYTE* pEnd, int nSize, int nOffset) {
|
|
CMP_BYTE* pNext = pThis + nOffset;
|
|
CMP_BYTE cRunLength = 1;
|
|
|
|
while(pNext < pEnd && memcmp(pThis, pNext, nSize) == 0 && cRunLength < 0x80) {
|
|
cRunLength++;
|
|
pNext += nOffset;
|
|
}
|
|
|
|
return cRunLength;
|
|
}
|
|
|
|
CMP_BYTE CalcRawLength(CMP_BYTE* pThis, CMP_BYTE* pEnd, int nSize, int nOffset) {
|
|
CMP_BYTE* pNext = pThis + nOffset;
|
|
CMP_BYTE cRawLength = 1;
|
|
|
|
while(pNext < pEnd && memcmp(pThis, pNext, nSize) != 0 && cRawLength < 0x80) {
|
|
cRawLength++;
|
|
pThis += nOffset;
|
|
pNext += nOffset;
|
|
}
|
|
|
|
return cRawLength;
|
|
}
|
|
|
|
|
|
// *** NOTE ****
|
|
// The Save data code needs to be rewored as
|
|
// TGA is saved as BGRA and our MipSet is using RGBA
|
|
//
|
|
// Current implementation is saving in wronge format as RGBA
|
|
//
|
|
// Need to Fix this
|
|
|
|
void SaveLineRLE(FILE* pFile, CMP_BYTE* pThis, CMP_BYTE* pEnd, int nSize, int nOffset) {
|
|
while (pThis < pEnd) {
|
|
CMP_BYTE* pNext = pThis + nOffset;
|
|
// Are the next two pixel the same ?
|
|
if(pNext < pEnd && memcmp(pThis, pNext, nSize) == 0) {
|
|
CMP_BYTE cRunLength = CalcRunLength(pThis, pEnd, nSize, nOffset);
|
|
CMP_BYTE cRepetitionCount = (cRunLength - 1) | 0x80;
|
|
fwrite(&cRepetitionCount, sizeof(cRepetitionCount), 1, pFile);
|
|
fwrite(pThis, nSize, 1, pFile);
|
|
pThis += (cRunLength * nOffset);
|
|
} else {
|
|
CMP_BYTE cRawLength = CalcRawLength(pThis, pEnd, nSize, nOffset);
|
|
CMP_BYTE cRepetitionCount = (cRawLength - 1);
|
|
fwrite(&cRepetitionCount, sizeof(cRepetitionCount), 1, pFile);
|
|
if(nSize == nOffset) {
|
|
fwrite(pThis, nSize*cRawLength, 1, pFile);
|
|
pThis += (cRawLength * nOffset);
|
|
} else {
|
|
for(CMP_BYTE i = 0; i < cRawLength; i++) {
|
|
fwrite(pThis, nSize, 1, pFile);
|
|
pThis += nOffset;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TC_PluginError SaveRLE(FILE* pFile, const MipSet* pMipSet, int nSize, int nOffset) {
|
|
CMP_DWORD dwPitch = pMipSet->m_nWidth * nOffset;
|
|
for(int j=pMipSet->m_nHeight-1; j>=0; j--) {
|
|
CMP_BYTE* pThis = (CMP_BYTE*) (TGA_CMips->GetMipLevel(pMipSet, 0)->m_pbData + (j * dwPitch));
|
|
CMP_BYTE* pEnd = (CMP_BYTE*) (TGA_CMips->GetMipLevel(pMipSet, 0)->m_pbData + ((j+1) * dwPitch));
|
|
|
|
SaveLineRLE(pFile, pThis, pEnd, nSize, nOffset);
|
|
}
|
|
|
|
fclose(pFile);
|
|
|
|
return PE_OK;
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// Source mipset should now always be RGBA
|
|
// Code using the pMipSet->m_swizzle should be reviewed
|
|
//--------------------------------------------------------
|
|
|
|
TC_PluginError SaveTGA_ARGB8888(FILE* pFile, const MipSet* pMipSet) {
|
|
CMP_DWORD dwPitch = pMipSet->m_nWidth * 4;
|
|
|
|
//if (pMipSet->m_swizzle)
|
|
{
|
|
CMP_BYTE RGBA[4];
|
|
for (int j = pMipSet->m_nHeight - 1; j >= 0; j--) {
|
|
CMP_BYTE* pData = (CMP_BYTE*)(TGA_CMips->GetMipLevel(pMipSet, 0)->m_pbData + (j * dwPitch));
|
|
for (int i = 0; i < pMipSet->m_nWidth; i++) {
|
|
RGBA[2] = (CMP_BYTE)*pData++;
|
|
RGBA[1] = (CMP_BYTE)*pData++;
|
|
RGBA[0] = (CMP_BYTE)*pData++;
|
|
RGBA[3] = (CMP_BYTE)*pData++;
|
|
fwrite(RGBA, 4, 1, pFile);
|
|
}
|
|
}
|
|
}
|
|
//else
|
|
//{
|
|
// for (int j = pMipSet->m_nHeight - 1; j >= 0; j--)
|
|
// {
|
|
// CMP_BYTE* pData = (CMP_BYTE*)(TGA_CMips->GetMipLevel(pMipSet, 0)->m_pbData + (j * dwPitch));
|
|
// fwrite(pData, dwPitch, 1, pFile);
|
|
// }
|
|
//}
|
|
|
|
fclose(pFile);
|
|
|
|
|
|
return PE_OK;
|
|
}
|
|
|
|
TC_PluginError SaveTGA_ARGB8888_RLE(FILE* pFile, const MipSet* pMipSet) {
|
|
return SaveRLE(pFile, pMipSet, sizeof(CMP_COLOR), sizeof(CMP_COLOR));
|
|
}
|
|
|
|
TC_PluginError SaveTGA_RGB888(FILE* pFile, const MipSet* pMipSet) {
|
|
CMP_DWORD dwPitch = pMipSet->m_nWidth * sizeof(CMP_COLOR);
|
|
for(int j=pMipSet->m_nHeight-1; j>=0; j--)
|
|
// for(int j=0; j < pMipSet->m_nHeight-1; j++)
|
|
{
|
|
CMP_BYTE* pData = (CMP_BYTE*) (TGA_CMips->GetMipLevel(pMipSet, 0)->m_pbData + (j * dwPitch));
|
|
for(int i=0; i < pMipSet->m_nWidth; i++) {
|
|
fwrite(pData, 3, 1, pFile);
|
|
pData += sizeof(CMP_COLOR);
|
|
}
|
|
}
|
|
|
|
fclose(pFile);
|
|
|
|
return PE_OK;
|
|
}
|
|
|
|
TC_PluginError SaveTGA_RGB888_RLE(FILE* pFile, const MipSet* pMipSet) {
|
|
return SaveRLE(pFile, pMipSet, 3, sizeof(CMP_COLOR));
|
|
}
|
|
|
|
TC_PluginError SaveTGA_G8(FILE* pFile, const MipSet* pMipSet) {
|
|
for(int j=pMipSet->m_nHeight-1; j>=0; j--) {
|
|
CMP_BYTE* pData = (CMP_BYTE*) (TGA_CMips->GetMipLevel(pMipSet, 0)->m_pbData + (j * pMipSet->m_nWidth));
|
|
fwrite(pData, pMipSet->m_nWidth, 1, pFile);
|
|
}
|
|
|
|
fclose(pFile);
|
|
|
|
return PE_OK;
|
|
}
|
|
|
|
TC_PluginError SaveTGA_G8_RLE(FILE* pFile, const MipSet* pMipSet) {
|
|
return SaveRLE(pFile, pMipSet, sizeof(CMP_BYTE), sizeof(CMP_BYTE));
|
|
}
|
|
|
|
|
|
// ------------ Registry!
|
|
#define DEFAULT_JPG_QUALITY 75
|
|
const char szKeyTGAPlugin[] = ("Software\\ATI Research, Inc.\\TextureAPI\\Plugins\\TGA");
|
|
|
|
void LoadRegistryKeyDefaults(TGA_FileSaveParams* pParams) {
|
|
memset(pParams, 0, sizeof(TGA_FileSaveParams));
|
|
pParams->dwSize = sizeof(TGA_FileSaveParams);
|
|
|
|
pParams->bRLECompressed = true;
|
|
}
|
|
|
|
void LoadRegistryKeys(TGA_FileSaveParams* pParams) {
|
|
#ifdef _WIN32
|
|
LoadRegistryKeyDefaults(pParams);
|
|
|
|
HKEY hKey;
|
|
CMP_DWORD dwSize;
|
|
RegOpenKeyEx(HKEY_CURRENT_USER, szKeyTGAPlugin, 0, KEY_ALL_ACCESS, &hKey);
|
|
|
|
CMP_DWORD dwTemp;
|
|
if(RegQueryValueEx(hKey, ("RLECompressed"), NULL, NULL, (CMP_BYTE*)&dwTemp, (LPDWORD)&dwSize) != ERROR_SUCCESS)
|
|
pParams->bRLECompressed = dwTemp ? true : false;
|
|
|
|
RegCloseKey(hKey);
|
|
#endif
|
|
}
|
|
|
|
void SaveRegistryKeys(const TGA_FileSaveParams* pParams) {
|
|
#ifdef _WIN32
|
|
HKEY hKey;
|
|
RegCreateKeyEx(HKEY_CURRENT_USER, szKeyTGAPlugin, 0, (""), REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL);
|
|
|
|
CMP_DWORD dwTemp;
|
|
dwTemp = pParams->bRLECompressed ? 1 : 0;
|
|
RegSetValueEx(hKey, ("RLECompressed"), NULL, REG_DWORD, (CMP_BYTE*) &dwTemp, sizeof(CMP_DWORD));
|
|
|
|
RegCloseKey(hKey);
|
|
#endif
|
|
}
|