Jump to content
  • Advertisement
Sign in to follow this  
Decrius

Images included _into_ the .exe?

This topic is 4589 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I can included bmp's now with NeHe's bmp including code, is there any code lookign that same like the BMP code, but than for JPEG? However, my main question: how to include the image files into the .exe? Now I have to give users the textures and the .exe, but than they can steal the textures. So, how to include the image file into .exe? With resources...? (Can I, with resources, still load the bmp with nehe's code?) Thx for any help :D Decrius

Share this post


Link to post
Share on other sites
Advertisement
I haven't done this yet, but if I recall from prior threads it has something to do with defining your images as a resource, and then referencing that resource instead of calling your image loading routine. I'm specifically referring to MS Visual Studio as that's the only one I read about. I think by defining the resource it will also load the image, so it might be tied to bitmap images. Try searching for something like "embedded resources" and see what you get.

I will also see if I can find the article later tonight.

hth
F451

Share this post


Link to post
Share on other sites
I found out this example from a website more than a few years ago as it allows you to store BMPs, JPG, PNG and TGA files with either a normail file loader or a resource loader which you can load from inside your exe. Firstly include your JPG files as you usually would a BMP, but instead being put into the IDB/BMP section, it will be placed into IDR, which allows any other image file format.

I used to use this years ago, as i found it on the net, with minor adjustments, as it a surefire way of working within your Win32 application.

res_texture.h

#ifndef _TEXTURE_LOADER_H_
#define _TEXTURE_LOADER_H_

#include "main.h" // includes all important header files such as windows.h, stdlib.h, etc
#include "resource.h"

// Define Interface Data Types / Structures
//
typedef enum {
txUnknown = 0, // images
txBmp = 1,
txJpg = 2,
txPng = 3,
txTga = 4,
txGif = 5,
txIco = 6,
txEmf = 7,
txWmf = 8,
// add new ones at the end
} eglTexType;

typedef enum {
txNoFilter = 0,
txBilinear = 1,
txTrilinear = 2,
// add new ones at the end
} eglTexFilterType;

typedef struct
{
GLuint TextureID; // Texture ID Used To Select A Texture
eglTexType TexType; // Texture Format
GLuint Width; // Image Width
GLuint Height; // Image Height
GLuint Type; // Image Type (GL_RGB, GL_RGBA)
GLuint Bpp; // Image Color Depth In Bits Per Pixel
} glTexture;

typedef struct {
float s;
float t;
} _glTexturCord;


typedef struct {
_glTexturCord TopRight;
_glTexturCord TopLeft;
_glTexturCord BottomLeft;
_glTexturCord BottomRight;
} glTexturCordTable;

// Define Private Structurs
//

// Header
typedef struct {
unsigned char ImgIdent;
unsigned char ignored[ 1 ];
unsigned char ImgType;
unsigned char ignored2[ 9 ];
unsigned char WidthLo;
unsigned char WidthHi;
unsigned char HeightLo;
unsigned char HeightHi;
unsigned char Bpp;
unsigned char ignored3[ 1 ];
} _TGAHeader;

// define TextureLoader Class
//
class TextureLoader
{
public:
// methods
TextureLoader();
virtual ~TextureLoader();
void SetAlphaMatch(GLboolean fEnabled, GLubyte RedAlphaMatch, GLubyte GreenAlphaMatch, GLubyte BlueAlphaMatch);
void SetHighQualityTextures(GLboolean fEnabled);
void SetMipMapping(GLboolean fEnabled);
void SetTextureFilter(eglTexFilterType type);

int LoadTextureFromDisk(char *szFileName, glTexture *pglTexture);
int LoadTextureFromRam(unsigned char *pData, int Length, glTexture *pglTexture, eglTexType TexType);
int LoadTextureFromResource(unsigned int ResourceName, char *pResourceType, glTexture *pglTexture, eglTexType TexType);
void FreeTexture(glTexture *pglTexture);
// variables

private:
// methods
int BuildTexture(char *szPathName, glTexture *pglTexture);
int LoadTGAFromDisk(char *pszFileName, glTexture *pglTexture);

int LoadJPG_GIFResource(char *pResourceName, char *pResourceType, glTexture *pglTexture);
int LoadTGAResource(char *pResourceName, char *pResourceType, glTexture *pglTexture);

int GenerateTexture(glTexture *pglTexture, GLubyte *pImgData);

void ExtensionFromFilename(char *szFileName, char *szExtension);

// variables
GLboolean m_fAlphaConversion;
GLboolean m_fHighQualityTextures;
GLboolean m_fMipMapping;
eglTexFilterType m_TextureFilterType;

GLubyte m_RedAlphaMatch;
GLubyte m_GreenAlphaMatch;
GLubyte m_BlueAlphaMatch;
};

#endif // _TEXTURE_LOADER_H_



Here is the source...

res_texture.cpp

#include "res_texture.h" // Our Header

#include "jpeglib.h"

#pragma comment(lib,"/lib/jpeg.lib")

// Constructor
//
TextureLoader::TextureLoader()
{
// default to alpha matching BLACK
SetAlphaMatch(TRUE, 0, 0, 0); // Set the Alpha Matching State

// default to full sized textures
SetHighQualityTextures(TRUE);

// no mipmap textures
SetMipMapping(FALSE);

// no texture filtering
SetTextureFilter(txNoFilter);
}

// Destructor
//
TextureLoader::~TextureLoader()
{
}


// Set Alpha Matching State and Match Colour
//
void TextureLoader::SetAlphaMatch(GLboolean fEnabled, GLubyte RedAlphaMatch, GLubyte GreenAlphaMatch, GLubyte BlueAlphaMatch)
{
m_fAlphaConversion = fEnabled;
// only set the colour match if the conversion is enabled
if (fEnabled == TRUE)
{
m_RedAlphaMatch = RedAlphaMatch;
m_GreenAlphaMatch = GreenAlphaMatch;
m_BlueAlphaMatch = BlueAlphaMatch;
}
}


// set the high quality texture flag
//
void TextureLoader::SetHighQualityTextures(GLboolean fEnabled)
{
m_fHighQualityTextures = fEnabled;
}


// set the mipmapping flag
//
void TextureLoader::SetMipMapping(GLboolean fEnabled)
{
m_fMipMapping = fEnabled;
}


// set the texture filtering flag
//
void TextureLoader::SetTextureFilter(eglTexFilterType type)
{
m_TextureFilterType = type;
}


// Load A Texture from Disk (based on the current location of the executable)
//
int TextureLoader::LoadTextureFromDisk(char *szFileName, glTexture *pglTexture)
{
char szFullPath[MAX_PATH+1]; // Full Path To Picture
char szExtension[16]; // Extenstion of Picture

if (strstr(szFileName, "http://")) // If PathName Contains http:// Then...
{
strcpy(szFullPath, szFileName); // Append The PathName To FullPath
}
else // Otherwise... We Are Loading From A File
{
GetCurrentDirectory(MAX_PATH, szFullPath); // Get Our Working Directory
strcat(szFullPath, "\\"); // Append "\" After The Working Directory
strcat(szFullPath, szFileName); // Append The PathName
}

ExtensionFromFilename(szFileName, szExtension);

// if the file is a TGA then use the TGA file loader
if (lstrcmpi(szExtension, "tga") == 0)
{
return(LoadTGAFromDisk(szFullPath, pglTexture)); // Load TGA (Compressed/Uncompressed)
}
else
{
// else load BMP, JPG, GIF

pglTexture->TexType = txUnknown;
if (lstrcmpi(szExtension, "bmp") == 0)
{
pglTexture->TexType = txBmp;
}
else if ((lstrcmpi(szExtension, "jpg") == 0) ||
(lstrcmpi(szExtension, "jpeg") == 0) )
{
pglTexture->TexType = txJpg;
}
else if (lstrcmpi(szExtension, "gif") == 0)
{
pglTexture->TexType = txGif;
}
else if (lstrcmpi(szExtension, "ico") == 0)
{
pglTexture->TexType = txIco;
}
else if (lstrcmpi(szExtension, "emf") == 0)
{
pglTexture->TexType = txEmf;
}
else if (lstrcmpi(szExtension, "wmf") == 0)
{
pglTexture->TexType = txWmf;
}

return(BuildTexture(szFullPath, pglTexture)); // Load BMP, JPG, GIF etc..
}
}


// Load A Texture from RAM
//
int TextureLoader::LoadTextureFromRam(unsigned char *pData, int Length, glTexture *pglTexture, eglTexType TexType)
{
// it would be much easier to allocate some global memory and make a stream out of it but that
// would require changing the TGA loading code to use RAM and not Disk access commands

char szTempFileName[MAX_PATH+1];

GetCurrentDirectory(MAX_PATH, szTempFileName); // Get Our Working Directory
lstrcat(szTempFileName, "glTEMP$$.tmp");

HANDLE hFile = CreateFile(szTempFileName,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_TEMPORARY,
NULL);

if (hFile != INVALID_HANDLE_VALUE)
{
int rc;
DWORD BytesWritten;

WriteFile(hFile, pData, Length, &BytesWritten, NULL); // Write The Data To disk (To A Temp File)

CloseHandle(hFile); // Close The File

// set the texture type
pglTexture->TexType = TexType;

// if the file is a TGA then use the TGA file loader
if (TexType == txTga)
{
rc = LoadTGAFromDisk(szTempFileName, pglTexture);
}
else
{
// else load BMP, JPG, GIF
rc = BuildTexture(szTempFileName, pglTexture);
}

DeleteFile(szTempFileName); // Delete The Temp File

return (rc); // Teturn State Of Texture Load
}
else
{
return FALSE; // Return Failed
}
}


// Load A Texture from the project Resource
//
int TextureLoader::LoadTextureFromResource(unsigned int ResourceName, char *pResourceType, glTexture *pglTexture, eglTexType TexType)
{
int rc = FALSE;

if ((TexType == txJpg) ||
(TexType == txGif) )
{
// set the texture type
pglTexture->TexType = TexType;

rc = LoadJPG_GIFResource(MAKEINTRESOURCE(ResourceName), pResourceType, pglTexture);
}

if (TexType == txBmp)
{
// set the texture type
pglTexture->TexType = TexType;

// some bug with the bitmap resource loader..
//rc = LoadJPG_GIFResource(MAKEINTRESOURCE(ResourceName), pResourceType, pglTexture);
//rc = LoadBMPResource(pResourceName, pResourceType, pglTexture);
}

if (TexType == txTga)
{
// set the texture type
pglTexture->TexType = TexType;

rc = LoadTGAResource(MAKEINTRESOURCE(ResourceName), pResourceType, pglTexture);
}

return (rc);
}


// Free a Texture from openGL
//
void TextureLoader::FreeTexture(glTexture *pglTexture)
{
glDeleteTextures(1, &pglTexture->TextureID);
}


// Load BMP, GIF and JPG and Convert To A Texture
//
int TextureLoader::BuildTexture(char *szPathName, glTexture *pglTexture)
{
HDC hdcTemp; // The DC To Hold Our Bitmap
HBITMAP hbmpTemp; // Holds The Bitmap Temporarily
IPicture *pPicture; // IPicture Interface
OLECHAR wszPath[MAX_PATH+1]; // Full Path To Picture (WCHAR)
long lWidth; // Width In Logical Units
long lHeight; // Height In Logical Units
long lWidthPixels; // Width In Pixels
long lHeightPixels; // Height In Pixels
GLint glMaxTexDim; // Holds Maximum Texture Size

MultiByteToWideChar(CP_ACP, 0, szPathName, -1, wszPath, MAX_PATH); // Convert From ASCII To Unicode
/* HRESULT hr = OleLoadPicturePath(wszPath, // Path
NULL, // punkCaller
0, // Reserved
0, // Reserved Transparent Colour
IID_IPicture, // riid of Inertface to return
(void**)&pPicture); // pointer to returned interface


if(FAILED(hr)) // If Loading Failed
{
return FALSE; // Return False
}
*/

hdcTemp = CreateCompatibleDC(GetDC(0)); // Create The Windows Compatible Device Context
if(!hdcTemp) // Did Creation Fail?
{
pPicture->Release(); // Decrements IPicture Reference Count
return FALSE; // Return False (Failure)
}

glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glMaxTexDim); // Get Maximum Texture Size Supported

pPicture->get_Width(&lWidth); // Get IPicture Width (Convert To Pixels)
lWidthPixels = MulDiv(lWidth, GetDeviceCaps(hdcTemp, LOGPIXELSX), 2540);
pPicture->get_Height(&lHeight); // Get IPicture Height (Convert To Pixels)
lHeightPixels = MulDiv(lHeight, GetDeviceCaps(hdcTemp, LOGPIXELSY), 2540);

// Resize Image To Closest Power Of Two
if (lWidthPixels <= glMaxTexDim) // Is Image Width Less Than Or Equal To Cards Limit
{
lWidthPixels = 1 << (int)floor((log((double)lWidthPixels)/log(2.0f)) + 0.5f);
}
else // Otherwise Set Width To "Max Power Of Two" That The Card Can Handle
{
lWidthPixels = glMaxTexDim;
}

if (lHeightPixels <= glMaxTexDim) // Is Image Height Greater Than Cards Limit
{
lHeightPixels = 1 << (int)floor((log((double)lHeightPixels)/log(2.0f)) + 0.5f);
}
else // Otherwise Set Height To "Max Power Of Two" That The Card Can Handle
{
lHeightPixels = glMaxTexDim;
}

// if low quality textures then make them halve the size which saved 4 times the texture space
if ((m_fHighQualityTextures == FALSE) && (lWidthPixels > 64))
{
lWidthPixels /= 2;
lHeightPixels /= 2;
}

// Create A Temporary Bitmap
BITMAPINFO bi = {0}; // The Type Of Bitmap We Request
DWORD *pBits = 0; // Pointer To The Bitmap Bits

bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); // Set Structure Size
bi.bmiHeader.biBitCount = 32; // 32 Bit
bi.bmiHeader.biWidth = lWidthPixels; // Power Of Two Width
bi.bmiHeader.biHeight = lHeightPixels; // Make Image Top Up (Positive Y-Axis)
bi.bmiHeader.biCompression = BI_RGB; // RGB Encoding
bi.bmiHeader.biPlanes = 1; // 1 Bitplane

// Creating A Bitmap This Way Allows Us To Specify Color Depth And Gives Us Imediate Access To The Bits
hbmpTemp = CreateDIBSection(hdcTemp,
&bi,
DIB_RGB_COLORS,
(void**)&pBits,
0,
0);

if(!hbmpTemp) // Did Creation Fail?
{
DeleteDC(hdcTemp); // Delete The Device Context
pPicture->Release(); // Decrements IPicture Reference Count
return FALSE; // Return False (Failure)
}

SelectObject(hdcTemp, hbmpTemp); // Select Handle To Our Temp DC And Our Temp Bitmap Object

// Render The IPicture On To The Bitmap
pPicture->Render(hdcTemp,
0,
0,
lWidthPixels,
lHeightPixels,
0,
lHeight,
lWidth,
-lHeight,
0);

// Convert From BGR To RGB Format And Add An Alpha Value Of 255
if (m_fAlphaConversion == TRUE)
{
// it is important to remember that the colour order is different as we are reading in a DWORD
// so the intel processor will read it in as little endian so the order is reversed (ABGR)
DWORD AlphaMatch = (((m_RedAlphaMatch) | (m_GreenAlphaMatch << 8)) | (m_BlueAlphaMatch << 16));

DWORD *pRGBA = (DWORD*)pBits;

long NumPixels = lWidthPixels * lHeightPixels;
while(NumPixels--) // Loop Through All Of The Pixels
{
DWORD tempRGB;

tempRGB = *pRGBA;
// swap red and blue over
tempRGB = ((tempRGB & 0x00FF0000) >> 16) | (tempRGB & 0x0000FF00) | ((tempRGB & 0x000000FF) << 16);

if (AlphaMatch != tempRGB)
{
tempRGB |= 0xFF000000;
}

*pRGBA++ = tempRGB;
}
}
else
{
BYTE *pPixel = (BYTE*)pBits; // Grab The Current Pixel

long NumPixels = lWidthPixels * lHeightPixels;
while(NumPixels--)
{

BYTE temp = pPixel[0]; // Store 1st Color In Temp Variable (Blue)
pPixel[0] = pPixel[2]; // Move Red Value To Correct Position (1st)
pPixel[2] = temp; // Move Temp Value To Correct Blue Position (3rd)
pPixel[3] = 255; // Set The Alpha Value To 255
pPixel += 4;
}
}

pglTexture->Width = bi.bmiHeader.biWidth;
pglTexture->Height = bi.bmiHeader.biHeight;
pglTexture->Bpp = bi.bmiHeader.biBitCount; // Image Color Depth In Bits Per Pixel
pglTexture->Type = GL_RGBA;

glGenTextures(1, &pglTexture->TextureID); // Create The Texture

// generate the texture using the filtering model selected
(void)GenerateTexture(pglTexture, (BYTE *)pBits);

DeleteObject(hbmpTemp); // Delete The Object
DeleteDC(hdcTemp); // Delete The Device Context

pPicture->Release(); // Decrements IPicture Reference Count

return TRUE; // Return True (All Good)
}


// Load a TGA file
//
int TextureLoader::LoadTGAFromDisk(char *pszFileName, glTexture *pglTexture)
{
FILE *fTGA; // File pointer to texture file
_TGAHeader header;
GLubyte *pImgData;
GLint glMaxTexDim; // Holds Maximum Texture Size

fTGA = fopen(pszFileName, "rb"); // Open file for reading

if(fTGA == NULL) // If it didn't open....
{
return FALSE; // Exit function
}

if(fread(&header, sizeof(_TGAHeader), 1, fTGA) == 0) // Attempt to read 12 byte header from file
{
if(fTGA != NULL) // Check to seeiffile is still open
{
fclose(fTGA); // If it is, close it
}
return FALSE; // Exit function
}

// Precalc some values from the header
const unsigned int imageType = header.ImgType;
const unsigned int imageWidth = header.WidthLo + header.WidthHi * 256;
const unsigned int imageHeight = header.HeightLo + header.HeightHi * 256;
const unsigned int imageBytesPerPel = header.Bpp / 8;
const unsigned int imageSize = imageWidth * imageHeight * imageBytesPerPel;

// load up our texture information
pglTexture->Width = imageWidth;
pglTexture->Height = imageHeight;
pglTexture->Bpp = header.Bpp;

if(pglTexture->Bpp == 24) // If the BPP of the image is 24...
{
pglTexture->Type = GL_RGB; // Set Image type to GL_RGB
}
else // Else if its 32 BPP
{
pglTexture->Type = GL_RGBA; // Set image type to GL_RGBA
}

// Validate header info
if( ( imageType != 2 && imageType != 10 ) ||
( imageWidth == 0 ) || ( imageHeight == 0 ) ||
( imageBytesPerPel != 3 && imageBytesPerPel != 4 ) )
{
// invalid header, bomb out
fclose( fTGA );
return (FALSE);
}

// Allocate the memory for the image size
pImgData = (GLubyte *)malloc(imageSize);

if(pImgData == NULL) // If no space was allocated
{
fclose(fTGA); // Close the file
return FALSE; // Return failed
}

// Skip image ident field
if( header.ImgIdent > 0 )
{
fseek(fTGA, header.ImgIdent, SEEK_CUR);
}

// un-compresses image ?
if (imageType == 2)
{
if(fread(pImgData, 1, imageSize, fTGA) != imageSize) // Attempt to read image data
{
if(pImgData != NULL) // If imagedata has data in it
{
free(pImgData); // Delete data from memory
}

fclose(fTGA); // Close file
return FALSE; // Return failed
}

// Byte Swapping Optimized By Steve Thomas
for(GLuint cswap = 0; cswap < imageSize; cswap += imageBytesPerPel)
{
pImgData[cswap] ^= pImgData[cswap+2] ^=
pImgData[cswap] ^= pImgData[cswap+2];
}
}
else
{
// compressed image
GLuint pixelcount = imageHeight * imageWidth; // Nuber of pixels in the image
GLuint currentpixel = 0; // Current pixel being read
GLuint currentbyte = 0; // Current byte
GLubyte * colorbuffer = (GLubyte *)malloc(imageBytesPerPel); // Storage for 1 pixel

do
{
GLubyte chunkheader = 0; // Storage for "chunk" header

if(fread(&chunkheader, sizeof(GLubyte), 1, fTGA) == 0) // Read in the 1 byte header
{
if(fTGA != NULL) // If file is open
{
fclose(fTGA); // Close file
}
if(pImgData != NULL) // If there is stored image data
{
free(pImgData); // Delete image data
}
return FALSE; // Return failed
}

if(chunkheader < 128) // If the ehader is < 128, it means the that is the number of RAW color packets minus 1
{ // that follow the header
chunkheader++; // add 1 to get number of following color values
for(short counter = 0; counter < chunkheader; counter++) // Read RAW color values
{
if(fread(colorbuffer, 1, imageBytesPerPel, fTGA) != imageBytesPerPel) // Try to read 1 pixel
{
if(fTGA != NULL) // See if file is open
{
fclose(fTGA); // If so, close file
}

if(colorbuffer != NULL) // See if colorbuffer has data in it
{
free(colorbuffer); // If so, delete it
}

if(pImgData != NULL) // See if there is stored Image data
{
free(pImgData); // If so, delete it too
}

return FALSE; // Return failed
}
// write to memory
pImgData[currentbyte ] = colorbuffer[2]; // Flip R and B vcolor values around in the process
pImgData[currentbyte + 1 ] = colorbuffer[1];
pImgData[currentbyte + 2 ] = colorbuffer[0];

if (imageBytesPerPel == 4) // if its a 32 bpp image
{
pImgData[currentbyte + 3] = colorbuffer[3]; // copy the 4th byte
}

currentbyte += imageBytesPerPel; // Increase thecurrent byte by the number of bytes per pixel
currentpixel++; // Increase current pixel by 1

if(currentpixel > pixelcount) // Make sure we havent read too many pixels
{
if(fTGA != NULL) // If there is a file open
{
fclose(fTGA); // Close file
}

if(colorbuffer != NULL) // If there is data in colorbuffer
{
free(colorbuffer); // Delete it
}

if(pImgData != NULL) // If there is Image data
{
free(pImgData); // delete it
}

return FALSE; // Return failed
}
}
}
else // chunkheader > 128 RLE data, next color reapeated chunkheader - 127 times
{
chunkheader -= 127; // Subtract 127 to get rid of the ID bit
if(fread(colorbuffer, 1, imageBytesPerPel, fTGA) != imageBytesPerPel) // Attempt to read following color values
{
if(fTGA != NULL) // If thereis a file open
{
fclose(fTGA); // Close it
}

if(colorbuffer != NULL) // If there is data in the colorbuffer
{
free(colorbuffer); // delete it
}

if(pImgData != NULL) // If there is image data
{
free(pImgData); // delete it
}

return FALSE; // return failed
}

for(short counter = 0; counter < chunkheader; counter++)// copy the color into the image data as many times as dictated
{ // by the header
pImgData[currentbyte ] = colorbuffer[2]; // switch R and B bytes areound while copying
pImgData[currentbyte + 1 ] = colorbuffer[1];
pImgData[currentbyte + 2 ] = colorbuffer[0];

if(imageBytesPerPel == 4) // If TGA images is 32 bpp
{
pImgData[currentbyte + 3] = colorbuffer[3]; // Copy 4th byte
}

currentbyte += imageBytesPerPel; // Increase current byte by the number of bytes per pixel
currentpixel++; // Increase pixel count by 1

if(currentpixel > pixelcount) // Make sure we havent written too many pixels
{
if(fTGA != NULL) // If there is a file open
{
fclose(fTGA); // Close file
}

if(colorbuffer != NULL) // If there is data in colorbuffer
{
free(colorbuffer); // Delete it
}

if(pImgData != NULL) // If there is Image data
{
free(pImgData); // delete it
}

return FALSE; // Return failed
}
} // for(counter)
} // if(chunkheader)
}
while(currentpixel < pixelcount); // Loop while there are still pixels left
} // if (imageType == 2)

fclose (fTGA); // Close the TGA file

/*
** Scale Image to be a power of 2
*/


glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glMaxTexDim); // Get Maximum Texture Size Supported

int lWidthPixels = imageWidth;
int lHeightPixels = imageHeight;

// Resize Image To Closest Power Of Two
if (lWidthPixels <= glMaxTexDim) // Is Image Width Less Than Or Equal To Cards Limit
lWidthPixels = 1 << (int)floor((log((double)lWidthPixels)/log(2.0f)) + 0.5f);
else // Otherwise Set Width To "Max Power Of Two" That The Card Can Handle
lWidthPixels = glMaxTexDim;

if (lHeightPixels <= glMaxTexDim) // Is Image Height Greater Than Cards Limit
lHeightPixels = 1 << (int)floor((log((double)lHeightPixels)/log(2.0f)) + 0.5f);
else // Otherwise Set Height To "Max Power Of Two" That The Card Can Handle
lHeightPixels = glMaxTexDim;

// if low quality textures then make them halve the size which saved 4 times the texture space
if ((m_fHighQualityTextures == FALSE) && (lWidthPixels > 64))
{
lWidthPixels /= 2;
lHeightPixels /= 2;
}

// if the size needs to change, the rescale the raw image data
if ( (lWidthPixels != (int)imageWidth) &&
(lHeightPixels != (int)imageHeight) )
{
// allocated the some memory for the new texture
GLubyte *pNewImgData = (GLubyte *)malloc(lWidthPixels * lHeightPixels * imageBytesPerPel);

GLenum format;
if (imageBytesPerPel == 4)
{
format = GL_RGBA;
}
else
{
format = GL_RGB;
}

gluScaleImage(format, imageWidth, imageHeight, GL_UNSIGNED_BYTE, pImgData,
lWidthPixels, lHeightPixels, GL_UNSIGNED_BYTE, pNewImgData);

// free the original image data
free(pImgData);

// old becomes new..
pImgData = pNewImgData;

// update our texture structure
pglTexture->Width = lWidthPixels;
pglTexture->Height = lHeightPixels;
}

// Typical Texture Generation Using Data From The TGA loader
glGenTextures(1, &pglTexture->TextureID); // Create The Texture

// generate the texture using the filtering model selected
(void)GenerateTexture(pglTexture, (BYTE *)pImgData);

// free the memory allocated
free(pImgData);

return TRUE; // All went well, continue on
}


// extract the extension from the specified filename
//
int TextureLoader::LoadJPG_GIFResource(char *pResourceName, char *pResourceType, glTexture *pglTexture)
{
HDC hdcTemp; // The DC To Hold Our Bitmap
HBITMAP hbmpTemp; // Holds The Bitmap Temporarily
IPicture *pPicture; // IPicture Interface
long lWidth; // Width In Logical Units
long lHeight; // Height In Logical Units
long lWidthPixels; // Width In Pixels
long lHeightPixels; // Height In Pixels
GLint glMaxTexDim ; // Holds Maximum Texture Size

// from resources
HRSRC hRes;
hRes = FindResource(NULL, pResourceName, pResourceType);

DWORD dwDataSize = SizeofResource(NULL,hRes);
HGLOBAL hGlob = LoadResource(NULL,hRes);
LPVOID pData = LockResource(hGlob);

HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwDataSize);
void* pData2 = GlobalLock(hGlobal);
memcpy(pData2, pData, dwDataSize);
GlobalUnlock(hGlobal);
UnlockResource(hGlob);
FreeResource(hGlob);

IStream* pStream = NULL;
pPicture = NULL;
HRESULT hr;

if (CreateStreamOnHGlobal(hGlobal, TRUE, &pStream) == S_OK)
{
hr = OleLoadPicture(pStream, 0, 0, IID_IPicture, (void**)&pPicture);
pStream->Release();
}

if(FAILED(hr)) // If Loading Failed
return FALSE; // Return False

hdcTemp = CreateCompatibleDC(GetDC(0)); // Create The Windows Compatible Device Context
if(!hdcTemp) // Did Creation Fail?
{
pPicture->Release(); // Decrements IPicture Reference Count
return FALSE; // Return False (Failure)
}

glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glMaxTexDim); // Get Maximum Texture Size Supported

pPicture->get_Width(&lWidth); // Get IPicture Width (Convert To Pixels)
lWidthPixels = MulDiv(lWidth, GetDeviceCaps(hdcTemp, LOGPIXELSX), 2540);
pPicture->get_Height(&lHeight); // Get IPicture Height (Convert To Pixels)
lHeightPixels = MulDiv(lHeight, GetDeviceCaps(hdcTemp, LOGPIXELSY), 2540);

// Resize Image To Closest Power Of Two
if (lWidthPixels <= glMaxTexDim) // Is Image Width Less Than Or Equal To Cards Limit
lWidthPixels = 1 << (int)floor((log((double)lWidthPixels)/log(2.0f)) + 0.5f);
else // Otherwise Set Width To "Max Power Of Two" That The Card Can Handle
lWidthPixels = glMaxTexDim;

if (lHeightPixels <= glMaxTexDim) // Is Image Height Greater Than Cards Limit
lHeightPixels = 1 << (int)floor((log((double)lHeightPixels)/log(2.0f)) + 0.5f);
else // Otherwise Set Height To "Max Power Of Two" That The Card Can Handle
lHeightPixels = glMaxTexDim;

// if low quality textures then make them halve the size which saved 4 times the texture space
if ((m_fHighQualityTextures == FALSE) && (lWidthPixels > 64))
{
lWidthPixels /= 2;
lHeightPixels /= 2;
}

// Create A Temporary Bitmap
BITMAPINFO bi = {0}; // The Type Of Bitmap We Request
DWORD *pBits = 0; // Pointer To The Bitmap Bits

bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); // Set Structure Size
bi.bmiHeader.biBitCount = 32; // 32 Bit
bi.bmiHeader.biWidth = lWidthPixels; // Power Of Two Width
bi.bmiHeader.biHeight = lHeightPixels; // Make Image Top Up (Positive Y-Axis)
bi.bmiHeader.biCompression = BI_RGB; // RGB Encoding
bi.bmiHeader.biPlanes = 1; // 1 Bitplane

// Creating A Bitmap This Way Allows Us To Specify Color Depth And Gives Us Imediate Access To The Bits
hbmpTemp = CreateDIBSection(hdcTemp, &bi, DIB_RGB_COLORS, (void**)&pBits, 0, 0);

if(!hbmpTemp) // Did Creation Fail?
{
DeleteDC(hdcTemp); // Delete The Device Context
pPicture->Release(); // Decrements IPicture Reference Count
return FALSE; // Return False (Failure)
}

SelectObject(hdcTemp, hbmpTemp); // Select Handle To Our Temp DC And Our Temp Bitmap Object

// Render The IPicture On To The Bitmap
pPicture->Render(hdcTemp, 0, 0, lWidthPixels, lHeightPixels, 0, lHeight, lWidth, -lHeight, 0);

// Convert From BGR To RGB Format And Add An Alpha Value Of 255
if ((m_fAlphaConversion == TRUE) && (pglTexture->TexType != txJpg))
{
// it is important to remember that the colour order is different as we are reading in a DWORD
// so the intel processor will read it in as little endian so the order is reversed (ABGR)
DWORD AlphaMatch = (((m_RedAlphaMatch) | (m_GreenAlphaMatch << 8)) | (m_BlueAlphaMatch << 16));

DWORD *pRGBA = (DWORD*)pBits;

long NumPixels = lWidthPixels * lHeightPixels;
while(NumPixels--) // Loop Through All Of The Pixels
{
DWORD tempRGB;

tempRGB = *pRGBA;
// swap red and blue over
tempRGB = ((tempRGB & 0x00FF0000) >> 16) | (tempRGB & 0x0000FF00) | ((tempRGB & 0x000000FF) << 16);

if (AlphaMatch != tempRGB)
{
tempRGB |= 0xFF000000;
}

*pRGBA++ = tempRGB;
}
}
else
{
BYTE *pPixel = (BYTE*)pBits; // Grab The Current Pixel

long NumPixels = lWidthPixels * lHeightPixels;
while(NumPixels--)
{

BYTE temp = pPixel[0]; // Store 1st Color In Temp Variable (Blue)
pPixel[0] = pPixel[2]; // Move Red Value To Correct Position (1st)
pPixel[2] = temp; // Move Temp Value To Correct Blue Position (3rd)
pPixel[3] = 255; // Set The Alpha Value To 255
pPixel += 4;
}
}

pglTexture->Width = bi.bmiHeader.biWidth;
pglTexture->Height = bi.bmiHeader.biHeight;
pglTexture->Bpp = bi.bmiHeader.biBitCount; // Image Color Depth In Bits Per Pixel
pglTexture->Type = GL_RGBA;

glGenTextures(1, &pglTexture->TextureID); // Create The Texture

// generate the texture using the filtering model selected
(void)GenerateTexture(pglTexture, (BYTE *)pBits);

DeleteObject(hbmpTemp); // Delete The Object
DeleteDC(hdcTemp); // Delete The Device Context

pPicture->Release(); // Decrements IPicture Reference Count

return TRUE; // Return True (All Good)
}


int TextureLoader::LoadTGAResource(char *pResourceName, char *pResourceType, glTexture *pglTexture)
{
// from resources
HRSRC hRes;
hRes = FindResource(NULL, pResourceName, pResourceType);

DWORD dwDataSize = SizeofResource(NULL,hRes);
HGLOBAL hGlob = LoadResource(NULL,hRes);
LPVOID pData = LockResource(hGlob);

// allocate some global memory and copy the resource data into it..
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwDataSize);
void* pData2 = GlobalLock(hGlobal);
memcpy(pData2, pData, dwDataSize);

// unlock and free the resource
GlobalUnlock(hGlobal);
UnlockResource(hGlob);
FreeResource(hGlob);

// load it
int rc = LoadTextureFromRam((unsigned char *)pData2, dwDataSize, pglTexture, txTga);

// free our global memory (16 bit os's only)
GlobalFree(hGlobal);

return rc;
}


// Set the Texture parameters to match the type of filtering we want.
//
int TextureLoader::GenerateTexture(glTexture *pglTexture, GLubyte *pImgData)
{
int result = 0;

int components;
// set the bytes per pixel
if (pglTexture->Type == GL_RGBA)
{
components = 4;
}
else
{
components = 3;
}

// Typical Texture Generation Using Data From The Bitmap
glBindTexture(GL_TEXTURE_2D, pglTexture->TextureID); // Bind To The Texture ID

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);

BOOL Mipping;

switch(m_TextureFilterType)
{
default:
case txNoFilter: glPixelStorei(GL_UNPACK_ALIGNMENT, 1 );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
Mipping = FALSE;
break;

case txBilinear: if (m_fMipMapping == FALSE)
{
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
// set the build type flag
Mipping = FALSE;
}
else
{
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
Mipping = TRUE;
}
break;

case txTrilinear: glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
// always mip mapping for trilinear
Mipping = TRUE;
break;
}


// crank out the texture
if (Mipping == FALSE)
{
glTexImage2D(GL_TEXTURE_2D,
0,
components,
pglTexture->Width,
pglTexture->Height,
0,
pglTexture->Type,
GL_UNSIGNED_BYTE,
pImgData);
}
else
{
// Build Mipmaps (builds different versions of the picture for distances - looks better)
result = gluBuild2DMipmaps(GL_TEXTURE_2D,
components,
pglTexture->Width,
pglTexture->Height,
pglTexture->Type,
GL_UNSIGNED_BYTE,
pImgData);
}

return 0;
}


// extract the extension from the specified filename
//
void TextureLoader::ExtensionFromFilename(char *szFileName, char *szExtension)
{
int len = lstrlen(szFileName);

for (int begin=len;begin>=0;begin--)
{
if (szFileName[begin] == '.')
{
begin++;
break;
}
}

if (begin <= 0)
{
szExtension[0] = '\0';
}
else
{
lstrcpy(szExtension, &szFileName[begin]);
}
}



Place this snippet into your application cpp code where you intend to load texture or image files. Its an easy class to follow and implement as it has many purposes hence the long lines of code. The parameters are as follows as I can remember

 // Dont forget header file!
#include "res_texture.h"

// place this into where you want to load textures
LoadTextureFromResource(IDR_JPG1[loop], "JPG",&Texture[loop], txJpg);


IDR_JPG - Your resource identifier which will be stored in your EXE (loop is optional)
JPG - Identifies which part of the Resource files it is stored, for exaple the JPG section
&Texture - Where you store your bitmap within OpenGL or whatever surface you are rendering with
txJpg - Allows the image loader to see which file format it will load

If you are worried about if someone hacks into your EXE once you have included the images, just use a very good EXE compressor like UPX - The Ultimate Packer for Executables. It not only shrinks your exe by a considerable amount, it will make taking resource files impossible to hack with such tools as ResourceHacker.It definately will guarantee to work.

I hope i have helped you as i admit, i havent use this code for years. Happy coding...

Share this post


Link to post
Share on other sites
Thats the "right" way to do it, but this way is cross compiler compatible (but probably considered more than a little bit of a hack)

compile this and run with the appropriate command line options, and it will convert any file into a c style array, effectively embedding it into your program (it spits out a text file i believe with the c source code) from there any image library that will take a chunk of data already in memory as opposed to a file, will be able to load your image. I was going to use it to embed a "texture not found" image in bmp format in my app, but then I decided against it, mostly because it didnt work well with my current system (for ensuring that textures never got loaded twice, as they depended on file names)


// bin2c.c
//
// convert a binary file into a C source vector
//
// put into the public domain by Sandro Sigala
//
// syntax: bin2c [-c] [-z] <input_file> <output_file>
//
// -c add the "const" keyword to definition
// -z terminate the array with a zero (useful for embedded C strings)
//
// examples:
// bin2c -c myimage.png myimage_png.cpp
// bin2c -z sometext.txt sometext_txt.cpp

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifndef PATH_MAX
#define PATH_MAX 1024
#endif

int useconst = 0;
int zeroterminated = 0;

int myfgetc(FILE *f)
{
int c = fgetc(f);
if (c == EOF && zeroterminated) {
zeroterminated = 0;
return 0;
}
return c;
}

void process(const char *ifname, const char *ofname)
{
FILE *ifile, *ofile;
ifile = fopen(ifname, "rb");
if (ifile == NULL) {
fprintf(stderr, "cannot open %s for reading\n", ifname);
exit(1);
}
ofile = fopen(ofname, "wb");
if (ofile == NULL) {
fprintf(stderr, "cannot open %s for writing\n", ofname);
exit(1);
}
char buf[PATH_MAX], *p;
const char *cp;
if ((cp = strrchr(ifname, '/')) != NULL)
++cp;
else {
if ((cp = strrchr(ifname, '\\')) != NULL)
++cp;
else
cp = ifname;
}
strcpy(buf, cp);
for (p = buf; *p != '\0'; ++p)
if (!isalnum(*p))
*p = '_';
fprintf(ofile, "static %sunsigned char %s[] = {\n", useconst ? "const " : "", buf);
int c, col = 1;
while ((c = myfgetc(ifile)) != EOF) {
if (col >= 78 - 6) {
fputc('\n', ofile);
col = 1;
}
fprintf(ofile, "0x%.2x, ", c);
col += 6;

}
fprintf(ofile, "\n};\n");

fclose(ifile);
fclose(ofile);
}

void usage(void)
{
fprintf(stderr, "usage: bin2c [-cz] <input_file> <output_file>\n");
exit(1);
}

int main(int argc, char **argv)
{
while (argc > 3) {
if (!strcmp(argv[1], "-c")) {
useconst = 1;
--argc;
++argv;
} else if (!strcmp(argv[1], "-z")) {
zeroterminated = 1;
--argc;
++argv;
} else {
usage();
}
}
if (argc != 3) {
usage();
}
process(argv[1], argv[2]);
return 0;
}



hope that helps
-Dan

Share this post


Link to post
Share on other sites
Quote:
Original post by WillPash
If you are worried about if someone hacks into your EXE once you have included the images, just use a very good EXE compressor like UPX - The Ultimate Packer for Executables. It not only shrinks your exe by a considerable amount, it will make taking resource files impossible to hack with such tools as ResourceHacker.It definately will guarantee to work.

I guess you aren't aware of the fact that any EXE compressed with UPX can also be uncompressed with it as well? UPX does not protect your EXE from any kind of hacking. It is a compressor -- that is all.

If you still want to try to keep your resources from hacking, then I suggest you implement some kind of encryption. This will at least keep away the casual hackers, but any one who is determined to hack your EXE can and will. No protection is unbeatable.

Share this post


Link to post
Share on other sites
I doubt anyone would bother decrypting the exe, they would just wait for your program to do it and then take the decrypted texture data.

Share this post


Link to post
Share on other sites
If your program can read it, anyone can read it. You can stall them for a time, but if they really want to do it, they will. Making it a resource won't help at all. Encrypting it will slow them down slightly.

Hell, all you really have to do is hook glTexImage2D, and save off the buffer that's passed in. Takes all of 10 minutes of work, if you have any idea what you're doing. Maybe less.

Share this post


Link to post
Share on other sites
Thank you all for the reply's :D, I didn't thought I could make images invisible, if someone want to get the images, he will get it, but I was just wondering how to make it invisible for the rookies, if I just hide it into the .exe most ppl won't find it, and that enuf :p.

However, I took a look at the JPEG section, came across 'APRONS TUTORIALS OPENGL', and he had tut's for bmp, jpg, tga etc

So I started with bmp, everthing works fine, but when I included the JPG section the same way, something weird happened. I have to include the jpeglib.h for the JPEG section, and than my compiler gives a warning (after change 'boolean' into 'bool', else it gave errors lol).

Project : OpenGL Application
Compiler : GNU GCC Compiler (called directly)
Directory : C:\C\Projects\OGL_Atoom--------------------------------------------------------------------------------
Switching to target: default
mingw32-g++.exe -c main.cpp -o .objs\main.o
In file included from C:/Program Files/CodeBlocks/bin/../lib/gcc/mingw32/3.4.4/../../../../include/c++/3.4.4/backward/iostream.h:31,
from C:/Program Files/CodeBlocks/bin/../lib/gcc/mingw32/3.4.4/../../../../include/taco/jpeglib.h:41,
from texture.h:2,
from opengl.h:1,
from main.cpp:25:
C:/Program Files/CodeBlocks/bin/../lib/gcc/mingw32/3.4.4/../../../../include/c++/3.4.4/backward/backward_warning.h:32:2: warning: #warning This file includes at least one deprecated or antiquated header. Please consider using one of the 32 headers found in section 17.4.1.2 of the C++ standard. Examples include substituting the <X> header for the <X.h> header for C++ includes, or <iostream> instead of the deprecated header <iostream.h>. To disable this warning use -Wno-deprecated.
mingw32-g++.exe -L"C:\Program Files\CodeBlocks\lib" -o C:\C\Projects\OGL_Atoom\OpenGL.exe .objs\main.o .objs\resource.res -lopengl32 -lglu32 -lgdi32 -luser32 -lkernel32 -mwindows
.objs\main.o:main.cpp:(.text+0x6d6): undefined reference to `jpeg_std_error'
.objs\main.o:main.cpp:(.text+0x6fa): undefined reference to `jpeg_CreateDecompress'
.objs\main.o:main.cpp:(.text+0x712): undefined reference to `jpeg_stdio_src'
.objs\main.o:main.cpp:(.text+0x74a): undefined reference to `jpeg_destroy_decompress'
.objs\main.o:main.cpp:(.text+0x786): undefined reference to `jpeg_read_header'
.objs\main.o:main.cpp:(.text+0x791): undefined reference to `jpeg_start_decompress'
.objs\main.o:main.cpp:(.text+0x860): undefined reference to `jpeg_read_scanlines'
.objs\main.o:main.cpp:(.text+0x885): undefined reference to `jpeg_finish_decompress'
collect2: ld returned 1 exit status
Process terminated with status 1 (0 minutes, 1 seconds)


Especially the warning:

warning: #warning This file includes at least one deprecated or antiquated header. Please consider using one of the 32 headers found in section 17.4.1.2 of the C++ standard. Examples include substituting the <X> header for the <X.h> header for C++ includes, or <iostream> instead of the deprecated header <iostream.h>. To disable this warning use -Wno-deprecated.

How to prevent this? And what is actually wrong? By english isn't good enuf (lol). I think its in the jpeglib.h file...

Decrius

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!