Game Development Community

Torque3D support .alpha.jpg?

by Nabarro · in Torque 3D Professional · 10/13/2009 (9:50 am) · 4 replies

I need to support *.alpha.jpg file, just like that in TGE1.5. In TGE1.5, there are codes as below:

// CAF: if a jpg, and RGB, look for file.alpha.jpg as alpha channel
if ( (!sgForcePalettedTexture || !dglDoesSupportPalettedTexture()) && !dStricmp(extArray[i],".jpg") && bmp && bmp->getFormat()==GBitmap::RGB)
{
dStrcpy(fileNameBuffer + len, ".alpha.jpg");
GBitmap * bmpAlpha = (GBitmap*)ResourceManager->loadInstance(fileNameBuffer);
S32 w = bmp->getWidth();
S32 h = bmp->getHeight();
if (bmpAlpha && bmpAlpha->getWidth() == w && bmpAlpha->getHeight() == h && bmpAlpha->bytesPerPixel==1)
{
GBitmap * bmp2 = new GBitmap(w,h,false,GBitmap::RGBA);
U8 * rgbBits = bmp->getWritableBits();
U8 * alphaBits = bmpAlpha->getWritableBits();
U8 * bmpBits = bmp2->getWritableBits();
for (S32 wi=0; wi<w; wi++)
{
for (S32 hi=0; hi<h; hi++)
{
bmpBits[wi*4 + hi*4*w + 0] = rgbBits[wi*3 + hi*3*w + 0];
bmpBits[wi*4 + hi*4*w + 1] = rgbBits[wi*3 + hi*3*w + 1];
bmpBits[wi*4 + hi*4*w + 2] = rgbBits[wi*3 + hi*3*w + 2];
bmpBits[wi*4 + hi*4*w + 3] = alphaBits[wi + hi*w];
}
}
delete bmpAlpha;
delete bmp;
bmp = bmp2;
}
}

But when I ported above codes to Torque3D(just change GBitmap::RGB and GBitmap::RGBA to GFXFormatR8G8B8 and DGSFormatR8G8B8A8), while it doesn't work, I can see neither *.jpg nor *.alpha.jpg texture.

Anyone may help me with this? Very appreciated.

#1
10/28/2009 (4:37 pm)
Out of curiosity why not use an image format with an alpha channel? Unless your doing something like an image gallery which reads from a folder of random images that you have no control of at the source, it's far more worthwhile to just convert your images to PNG or DDS(if your wanting texture compression in memory). jpegs are low quality by design as long as it's compressed(otherwise what's the point), and PNG is lossless while having a really good compression. If loading speed is important then DDS is the best because the image has moderate compression on hard-drive and then when loaded to GPU keeps the same compression without any extra processing.
#2
10/28/2009 (10:57 pm)
Yea i'm also curious as to why you need the old '.alpha.jpg' hack in this case.
#3
10/29/2009 (1:36 pm)
If, like us, you are porting a project from an older version of Torque then the '.alpha.jpg' hack can be quite useful until you get your source data converted to a more suitable format.

Replace the top of gfx\bitmap\loaders\bitmapJpeg.cpp with the following:

//-----------------------------------------------------------------------------
// Torque Shader Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------

#include "ljpeg/jpeglib.h"

#include "core/stream/fileStream.h"
#include "core/util/path.h"

#include "gfx/bitmap/gBitmap.h"


using namespace Torque;

static GBitmap *sImportJpgImage(const Path &inPath);

static bool sReadJPG(Stream &stream, GBitmap *bitmap);
static bool sWriteJPG(GBitmap *bitmap, Stream &stream, U32 compressionLevel);

static struct _privateRegisterJPG
{
   _privateRegisterJPG()
   {
      GBitmap::Registration reg;

      reg.extensions.push_back( "jpeg" );
      reg.extensions.push_back( "jpg" );

      reg.readFunc = sReadJPG;
      reg.writeFunc = sWriteJPG;

      GBitmap::sRegisterFormat( reg );
   }
} sStaticRegisterJPG;

//-----------------------------------------------------------------------------
/// This gives us a chance to handle it before invoking the Resource<GBitmap>::create() function
/// This will only accept the .jpg extension.  If you want to handle others, you'll have to change
/// this function to look for them.
static bool  sJPGHandleLoadSignal(const Path &inPath, void **outPtr)
{
   static const String  sgJPGStr( "jpg" );

   const String   &ext = inPath.getExtension();

   if ( (outPtr == NULL) || (ext.isNotEmpty() && sgJPGStr.compare( ext, 3, String::NoCase ) ) )
      return true;

#ifdef TORQUE_DEBUG_RES_MANAGER
   Con::printf( "[Bitmap] sJPGHandleLoadSignal - [%s]", inPath.getFullPath().c_str() );
#endif

   Path  fullPath( inPath );

   if ( ext.isEmpty() )
      fullPath.setExtension( sgJPGStr );

   GBitmap *res = sImportJpgImage( fullPath );

   *outPtr = res;

   return( res == NULL );
}

static ResourceRegisterLoadSignal<GBitmap> sgAuto( sJPGHandleLoadSignal );

static GBitmap *sImportJpgImage( const Path &inPath )
{
	FileStream  stream;
   stream.open(inPath.getFullPath(), Torque::FS::File::Read);

   if (stream.getStatus() != Stream::Ok)
	{
      return NULL;
	}

   GBitmap* bmp = new GBitmap;
   const String extension = inPath.getExtension();
	bool readSuccess = bmp->readBitmap(extension, stream);
	if (readSuccess && bmp->getFormat() == GFXFormatR8G8B8)
	{
		Path inPathAlpha = inPath;
		inPathAlpha.setFileName(inPathAlpha.getFileName() + ".alpha");

		stream.close();
		stream.open(inPathAlpha.getFullPath(), Torque::FS::File::Read);

		if (stream.getStatus() == Stream::Ok)
		{
			GBitmap* bmpAlpha = new GBitmap;
			bool readSuccess = bmpAlpha->readBitmap(extension, stream);

			S32 w = bmp->getWidth();
			S32 h = bmp->getHeight();
			if (readSuccess && bmpAlpha->getWidth() == w && bmpAlpha->getHeight() == h && bmpAlpha->getBytesPerPixel() == 1)
			{
				GBitmap* bmp2 = new GBitmap(w, h, false, GFXFormatR8G8B8A8);
				U8* rgbBits = bmp->getWritableBits();
				U8* alphaBits = bmpAlpha->getWritableBits();
				U8* bmpBits = bmp2->getWritableBits();
				for (S32 wi = 0; wi < w; wi++)
				{
					for (S32 hi = 0; hi < h; hi++)
					{
						bmpBits[wi * 4 + hi * 4 * w + 0] = rgbBits[wi * 3 + hi * 3 * w + 0];
						bmpBits[wi * 4 + hi * 4 * w + 1] = rgbBits[wi * 3 + hi * 3 * w + 1];
						bmpBits[wi * 4 + hi * 4 * w + 2] = rgbBits[wi * 3 + hi * 3 * w + 2];
						bmpBits[wi * 4 + hi * 4 * w + 3] = alphaBits[wi + hi * w];
					}
				}
				delete bmpAlpha;
				delete bmp;
				bmp = bmp2;
			}
		}
	}
	else
	{
		delete bmp;
		bmp = NULL;
	}

	return bmp;
}

Hope that helps!

Cheers,

Stephane
#4
10/29/2009 (10:15 pm)
Thanks, Stephane. Appreciated with your help.