mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-19 20:24:49 +00:00
232 lines
7.7 KiB
C++
232 lines
7.7 KiB
C++
//-----------------------------------------------------------------------------
|
|
// Copyright (c) 2012 GarageGames, LLC
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to
|
|
// deal in the Software without restriction, including without limitation the
|
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
// sell copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
// IN THE SOFTWARE.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#include "platform/platform.h"
|
|
|
|
#include "core/stream/fileStream.h"
|
|
#include "core/util/path.h"
|
|
|
|
#include "gfx/bitmap/gBitmap.h"
|
|
|
|
// This must come after our headers due to a conflicting definition of VoidPtr
|
|
#include "lungif/gif_lib.h"
|
|
|
|
|
|
using namespace Torque;
|
|
|
|
static bool sReadGIF(Stream &stream, GBitmap *bitmap);
|
|
static bool sWriteGIF(GBitmap *bitmap, Stream &stream, U32 compressionLevel);
|
|
|
|
static struct _privateRegisterGIF
|
|
{
|
|
_privateRegisterGIF()
|
|
{
|
|
GBitmap::Registration reg;
|
|
|
|
reg.extensions.push_back( "gif" );
|
|
|
|
reg.readFunc = sReadGIF;
|
|
reg.writeFunc = sWriteGIF;
|
|
|
|
GBitmap::sRegisterFormat( reg );
|
|
}
|
|
} sStaticRegisterGIF;
|
|
|
|
//-------------------------------------- Replacement I/O for standard LIBjpeg
|
|
// functions. we don't wanna use
|
|
// FILE*'s...
|
|
static S32 gifReadDataFn(GifFileType *gifinfo, GifByteType *data, S32 length)
|
|
{
|
|
Stream *stream = (Stream*)gifinfo->UserData;
|
|
AssertFatal(stream != NULL, "gifReadDataFn::No stream.");
|
|
int pos = stream->getPosition();
|
|
if (stream->read(length, data))
|
|
return length;
|
|
|
|
if (stream->getStatus() == Stream::EOS)
|
|
return (stream->getPosition()-pos);
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
|
|
//--------------------------------------
|
|
#if 0
|
|
// CodeReview - until we can write these, get rid of warning by disabling method.
|
|
static S32 gifWriteDataFn(GifFileType *gifinfo, GifByteType *data, S32 length)
|
|
{
|
|
Stream *stream = (Stream*)gifinfo->UserData;
|
|
AssertFatal(stream != NULL, "gifWriteDataFn::No stream.");
|
|
if (stream->write(length, data))
|
|
return length;
|
|
else
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
//--------------------------------------
|
|
static bool sReadGIF( Stream &stream, GBitmap *bitmap )
|
|
{
|
|
GifFileType *gifinfo = DGifOpen( (void*)&stream, gifReadDataFn);
|
|
if (!gifinfo)
|
|
return false;
|
|
|
|
GifRecordType recordType;
|
|
do
|
|
{
|
|
if (DGifGetRecordType(gifinfo, &recordType) == GIF_ERROR)
|
|
break;
|
|
|
|
if (recordType == IMAGE_DESC_RECORD_TYPE)
|
|
{
|
|
if (DGifGetImageDesc(gifinfo) == GIF_ERROR)
|
|
break;
|
|
|
|
GFXFormat format = (gifinfo->SBackGroundColor == 0 ) ? GFXFormatR8G8B8 : GFXFormatR8G8B8A8;
|
|
bitmap->allocateBitmap(gifinfo->SWidth, gifinfo->SHeight, false, format);
|
|
|
|
// Assume no transparency until proven otherwise
|
|
bitmap->setHasTransparency(false);
|
|
|
|
U32 gwidth = gifinfo->Image.Width ? gifinfo->Image.Width : bitmap->getWidth();
|
|
U32 gheight= gifinfo->Image.Height ? gifinfo->Image.Height : bitmap->getHeight();
|
|
U32 gifSize = gwidth * gheight;
|
|
U8 *data = new U8[gifSize];
|
|
|
|
if (DGifGetLine(gifinfo, data, gifSize) != GIF_ERROR)
|
|
{
|
|
// use the global or local color table ?
|
|
GifColorType *color = NULL;
|
|
if (gifinfo->Image.ColorMap)
|
|
color = gifinfo->Image.ColorMap->Colors;
|
|
else if (gifinfo->SColorMap)
|
|
color = gifinfo->SColorMap->Colors;
|
|
|
|
if (color)
|
|
{
|
|
U8 *dst = bitmap->getAddress(gifinfo->Image.Left, gifinfo->Image.Top);
|
|
U8 *src = data;
|
|
U32 right = gifinfo->Image.Left + gwidth;
|
|
U32 bottom = gifinfo->Image.Top + gheight;
|
|
U32 next = (bitmap->getWidth() - gwidth) * bitmap->getBytesPerPixel();
|
|
|
|
if (format == GFXFormatR8G8B8A8)
|
|
{
|
|
for (U32 y=gifinfo->Image.Top; y<bottom; y++)
|
|
{
|
|
for (U32 x=gifinfo->Image.Left; x<right; x++, src++)
|
|
{
|
|
if (*src == gifinfo->SBackGroundColor)
|
|
{
|
|
// this is a transparent pixel
|
|
dst[0] = 0; // red
|
|
dst[1] = 0; // green
|
|
dst[2] = 0; // blue
|
|
dst[3] = 0; // alpha
|
|
|
|
bitmap->setHasTransparency(true);
|
|
}
|
|
else
|
|
{
|
|
dst[0] = color[*src].Red;
|
|
dst[1] = color[*src].Green;
|
|
dst[2] = color[*src].Blue;
|
|
dst[3] = 0; // alpha
|
|
}
|
|
dst += bitmap->getBytesPerPixel();
|
|
}
|
|
dst += next;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (U32 y=gifinfo->Image.Top; y<bottom; y++)
|
|
{
|
|
for (U32 x=gifinfo->Image.Left; x<right; x++, src++)
|
|
{
|
|
dst[0] = color[*src].Red;
|
|
dst[1] = color[*src].Green;
|
|
dst[2] = color[*src].Blue;
|
|
dst += bitmap->getBytesPerPixel();
|
|
}
|
|
dst += next;
|
|
}
|
|
}
|
|
delete [] data;
|
|
DGifCloseFile(gifinfo);
|
|
return true;
|
|
}
|
|
}
|
|
// failure
|
|
delete [] data;
|
|
break;
|
|
}
|
|
else if (recordType == EXTENSION_RECORD_TYPE)
|
|
{
|
|
GifByteType *extension;
|
|
S32 extCode;
|
|
|
|
// Skip any extension blocks in file
|
|
if (DGifGetExtension(gifinfo, &extCode, &extension) != GIF_ERROR)
|
|
{
|
|
while (extension != NULL)
|
|
{
|
|
if (DGifGetExtensionNext(gifinfo, &extension) == GIF_ERROR)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// There used to be a break right here. This caused the while condition to
|
|
// never get processed, and so it never looped through all the records in
|
|
// the GIF. I took a quick peek back at TGB and TGE histories and I am not
|
|
// sure where this change got made, but I can't figure out why the loading
|
|
// worked at all, ever, with that break in there. The only case I can think
|
|
// of is if the first record in the GIF was the bitmap data.
|
|
// [6/6/2007 Pat]
|
|
|
|
}while (recordType != TERMINATE_RECORD_TYPE);
|
|
|
|
|
|
DGifCloseFile(gifinfo);
|
|
return true;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
static bool sWriteGIF(GBitmap *bitmap, Stream &stream, U32 compressionLevel)
|
|
{
|
|
TORQUE_UNUSED( bitmap );
|
|
TORQUE_UNUSED( stream );
|
|
TORQUE_UNUSED( compressionLevel );
|
|
|
|
return false;
|
|
}
|
|
|
|
|