Torque3D/Engine/lib/lmng/bcb/mngrepair/mngrepair.cpp
2012-09-19 11:15:01 -04:00

489 lines
21 KiB
C++

/* ************************************************************************** */
/* * * */
/* * COPYRIGHT NOTICE: * */
/* * * */
/* * Copyright (c) 2000-2002 Gerard Juyn (gerard@libmng.com) * */
/* * [You may insert additional notices after this sentence if you modify * */
/* * this source] * */
/* * * */
/* * For the purposes of this copyright and license, "Contributing Authors" * */
/* * is defined as the following set of individuals: * */
/* * * */
/* * Gerard Juyn * */
/* * (hopefully some more to come...) * */
/* * * */
/* * The MNG Library is supplied "AS IS". The Contributing Authors * */
/* * disclaim all warranties, expressed or implied, including, without * */
/* * limitation, the warranties of merchantability and of fitness for any * */
/* * purpose. The Contributing Authors assume no liability for direct, * */
/* * indirect, incidental, special, exemplary, or consequential damages, * */
/* * which may result from the use of the MNG Library, even if advised of * */
/* * the possibility of such damage. * */
/* * * */
/* * Permission is hereby granted to use, copy, modify, and distribute this * */
/* * source code, or portions hereof, for any purpose, without fee, subject * */
/* * to the following restrictions: * */
/* * * */
/* * 1. The origin of this source code must not be misrepresented; * */
/* * you must not claim that you wrote the original software. * */
/* * * */
/* * 2. Altered versions must be plainly marked as such and must not be * */
/* * misrepresented as being the original source. * */
/* * * */
/* * 3. This Copyright notice may not be removed or altered from any source * */
/* * or altered source distribution. * */
/* * * */
/* * The Contributing Authors specifically permit, without fee, and * */
/* * encourage the use of this source code as a component to supporting * */
/* * the MNG and JNG file format in commercial products. If you use this * */
/* * source code in a product, acknowledgment would be highly appreciated. * */
/* * * */
/* ************************************************************************** */
/* * * */
/* * project : mngrepair * */
/* * file : mngrepair.cpp copyright (c) 2002 G.Juyn * */
/* * version : 1.0.0 * */
/* * * */
/* * purpose : main project file * */
/* * * */
/* * author : G.Juyn * */
/* * web : http://www.3-t.com * */
/* * email : mailto:info@3-t.com * */
/* * * */
/* * comment : mngrepair iterates tries to fix a couple of 'common' * */
/* * MNG encoding errors (such as in JASC Animation Shop) * */
/* * * */
/* * changes : * */
/* * * */
/* ************************************************************************** */
#define HAVE_BOOLEAN
#include <windows.h>
#pragma hdrstop
#include <condefs.h>
#include "libmng.h"
/* ************************************************************************** */
USERES("mngrepair.res");
USEUNIT("..\..\libmng_hlapi.c");
USEUNIT("..\..\libmng_callback_xs.c");
USEUNIT("..\..\libmng_prop_xs.c");
USEUNIT("..\..\libmng_chunk_xs.c");
USEUNIT("..\..\libmng_object_prc.c");
USEUNIT("..\..\libmng_chunk_prc.c");
USEUNIT("..\..\libmng_chunk_io.c");
USEUNIT("..\..\libmng_read.c");
USEUNIT("..\..\libmng_write.c");
USEUNIT("..\..\libmng_display.c");
USEUNIT("..\..\libmng_dither.c");
USEUNIT("..\..\libmng_pixels.c");
USEUNIT("..\..\libmng_filter.c");
USEUNIT("..\..\libmng_error.c");
USEUNIT("..\..\libmng_trace.c");
USEUNIT("..\..\libmng_cms.c");
USEUNIT("..\..\libmng_zlib.c");
USEUNIT("..\..\libmng_jpeg.c");
USEUNIT("..\..\..\zlib\adler32.c");
USEUNIT("..\..\..\zlib\compress.c");
USEUNIT("..\..\..\zlib\crc32.c");
USEUNIT("..\..\..\zlib\deflate.c");
USEUNIT("..\..\..\zlib\infblock.c");
USEUNIT("..\..\..\zlib\infcodes.c");
USEUNIT("..\..\..\zlib\inffast.c");
USEUNIT("..\..\..\zlib\inflate.c");
USEUNIT("..\..\..\zlib\inftrees.c");
USEUNIT("..\..\..\zlib\infutil.c");
USEUNIT("..\..\..\zlib\trees.c");
USEUNIT("..\..\..\zlib\uncompr.c");
USEUNIT("..\..\..\zlib\zutil.c");
//---------------------------------------------------------------------------
typedef struct user_struct {
FILE *hFileI; /* input file handle */
FILE *hFileO; /* output file handle */
mng_handle hHandleI; /* input mng handle */
mng_handle hHandleO; /* output mng handle */
mng_bool bHasSAVE; /* indicates a SAVE in the input */
mng_bool bHasTERM; /* indicates we saved the TERM */
mng_bool bIsJASC; /* indicates if this is an AS file */
mng_chunkid iLastchunk; /* last processed chunk */
mng_retcode iError; /* errorcode from function in callback */
mng_uint8 iTermaction; /* saved TERM parameters */
mng_uint8 iIteraction;
mng_uint32 iDelay;
mng_uint32 iItermax;
} userdata;
typedef userdata * userdatap;
/* ************************************************************************** */
#define MY_DECL /* get the right callback convention */
/* ************************************************************************** */
mng_ptr MY_DECL myalloc (mng_size_t iSize)
{ /* duh! */
return (mng_ptr)calloc (1, (size_t)iSize);
}
/* ************************************************************************** */
#pragma argsused
void MY_DECL myfree (mng_ptr pPtr, mng_size_t iSize)
{
free (pPtr); /* duh! */
return;
}
/* ************************************************************************** */
#pragma argsused
mng_bool MY_DECL myopenstream (mng_handle hMNG)
{
return MNG_TRUE; /* already opened in main function */
}
/* ************************************************************************** */
#pragma argsused
mng_bool MY_DECL myclosestream (mng_handle hMNG)
{
return MNG_TRUE; /* gets closed in main function */
}
/* ************************************************************************** */
mng_bool MY_DECL myreaddata (mng_handle hMNG,
mng_ptr pBuf,
mng_uint32 iSize,
mng_uint32 *iRead)
{ /* get to my file handle */
userdatap pMydata = (userdatap)mng_get_userdata (hMNG);
/* read it */
*iRead = fread (pBuf, 1, iSize, pMydata->hFileI);
/* iRead will indicate EOF */
return MNG_TRUE;
}
/* ************************************************************************** */
mng_bool MY_DECL mywritedata (mng_handle hMNG,
mng_ptr pBuf,
mng_uint32 iSize,
mng_uint32 *iWritten)
{ /* get to my file handle */
userdatap pMydata = (userdatap)mng_get_userdata (hMNG);
/* write it */
*iWritten = fwrite (pBuf, 1, iSize, pMydata->hFileO);
/* iWritten will indicate errors */
return MNG_TRUE;
}
/* ************************************************************************** */
mng_bool MY_DECL myprocesserror (mng_handle hMNG,
mng_int32 iErrorcode,
mng_int8 iSeverity,
mng_chunkid iChunkname,
mng_uint32 iChunkseq,
mng_int32 iExtra1,
mng_int32 iExtra2,
mng_pchar zErrortext)
{ /* sequence error for TERM we ignore ! */
if ((iErrorcode == MNG_SEQUENCEERROR) && (iChunkname == MNG_UINT_TERM))
return MNG_TRUE;
return MNG_FALSE; /* all others get dumped ! */
}
/* ************************************************************************** */
#pragma argsused
mng_bool MY_DECL myiterchunk (mng_handle hMNG,
mng_handle hChunk,
mng_chunkid iChunktype,
mng_uint32 iChunkseq)
{
mng_uint32 iWidth; /* temps for IHDR processing */
mng_uint32 iHeight;
mng_uint8 iBitdepth;
mng_uint8 iColortype;
mng_uint8 iCompression;
mng_uint8 iFilter;
mng_uint8 iInterlace;
mng_bool bEmpty; /* temps for FRAM processing */
mng_uint8 iMode;
mng_uint32 iNamesize;
mng_pchar zName;
mng_uint8 iChangedelay;
mng_uint8 iChangetimeout;
mng_uint8 iChangeclipping;
mng_uint8 iChangesyncid;
mng_uint32 iDelay;
mng_uint32 iTimeout;
mng_uint8 iBoundarytype;
mng_int32 iBoundaryl;
mng_int32 iBoundaryr;
mng_int32 iBoundaryt;
mng_int32 iBoundaryb;
mng_uint32 iCount;
mng_uint32p pSyncids;
/* get to my userdata */
userdatap pMydata = (userdatap)mng_get_userdata (hMNG);
if (pMydata->hFileO) /* are we writing this time ? */
{ /* do we need to 'forget' the TERM ? */
if ((iChunktype == MNG_UINT_TERM) && (pMydata->bHasTERM))
;
else
{ /* fix JASC AS frame_type ? */
if ((iChunktype == MNG_UINT_FRAM) && (pMydata->bIsJASC))
{
if ((pMydata->iError = mng_getchunk_fram (hMNG, hChunk,
&bEmpty, &iMode, &iNamesize, &zName,
&iChangedelay, &iChangetimeout,
&iChangeclipping, &iChangesyncid,
&iDelay, &iTimeout, &iBoundarytype,
&iBoundaryl, &iBoundaryr,
&iBoundaryt, &iBoundaryb,
&iCount, &pSyncids)) != 0)
{
fprintf (stderr, "Cannot get FRAM fields.\n");
return MNG_FALSE; /* stop the process ! */
}
if (iMode == 1) /* really ? */
iMode = 3;
if ((pMydata->iError = mng_putchunk_fram (pMydata->hHandleO,
bEmpty, iMode, iNamesize, zName,
iChangedelay, iChangetimeout,
iChangeclipping, iChangesyncid,
iDelay, iTimeout, iBoundarytype,
iBoundaryl, iBoundaryr,
iBoundaryt, iBoundaryb,
iCount, pSyncids)) != 0)
{
fprintf (stderr, "Cannot write FRAM chunk.\n");
return MNG_FALSE; /* stop the process ! */
}
}
else
{
if ((pMydata->iError = mng_copy_chunk (hMNG, hChunk, pMydata->hHandleO)) != 0)
{
fprintf (stderr, "Cannot copy the chunk.\n");
return MNG_FALSE; /* stop the process ! */
}
}
}
/* need to insert TERM in the proper place ? */
if ((iChunktype == MNG_UINT_MHDR) && (pMydata->bHasTERM))
{
if ((pMydata->iError = mng_putchunk_term (pMydata->hHandleO,
pMydata->iTermaction,
pMydata->iIteraction,
pMydata->iDelay,
pMydata->iItermax)) != 0)
{
fprintf (stderr, "Cannot write TERM chunk.\n");
return MNG_FALSE; /* stop the process ! */
}
}
}
else /* first iteration; just checking stuff */
{
if (iChunktype == MNG_UINT_SAVE) /* SAVE ? */
{
pMydata->bHasSAVE = MNG_TRUE; /* we got a SAVE ! */
pMydata->bIsJASC = MNG_FALSE; /* so it's definitely not an invalid AS file */
}
else
{ /* TERM ? */
if (iChunktype == MNG_UINT_TERM)
{ /* is it in the wrong place ? */
if ((pMydata->iLastchunk != MNG_UINT_MHDR) ||
(pMydata->iLastchunk != MNG_UINT_SAVE) )
{
pMydata->bHasTERM = MNG_TRUE;
if ((pMydata->iError = mng_getchunk_term (hMNG, hChunk,
&pMydata->iTermaction,
&pMydata->iIteraction,
&pMydata->iDelay,
&pMydata->iItermax)) != 0)
{
fprintf (stderr, "Cannot get TERM fields.\n");
return MNG_FALSE; /* stop the process ! */
}
}
}
else
{ /* IHDR ? */
if (iChunktype == MNG_UINT_IHDR)
{
if ((pMydata->iError = mng_getchunk_ihdr (hMNG, hChunk,
&iWidth, &iHeight, &iBitdepth,
&iColortype, &iCompression,
&iFilter, &iInterlace)) != 0)
{
fprintf (stderr, "Cannot get IHDR fields.\n");
return MNG_FALSE; /* stop the process ! */
}
/* is it not a typical JASC AS file */
if ((iBitdepth != 8) || (iColortype != 6))
pMydata->bIsJASC = MNG_FALSE;
}
}
}
pMydata->iLastchunk = iChunktype;
}
return MNG_TRUE; /* keep'm coming... */
}
/* ************************************************************************** */
int fixit (char * zFilenameI,
char * zFilenameO)
{
userdatap pMydata;
mng_retcode iRC;
/* get a data buffer */
pMydata = (userdatap)calloc (1, sizeof (userdata));
if (pMydata == NULL) /* oke ? */
{
fprintf (stderr, "Cannot allocate a data buffer.\n");
return 1;
}
pMydata->hFileO = 0; /* initialize some stuff! */
pMydata->hHandleI = MNG_NULL;
pMydata->hHandleO = MNG_NULL;
pMydata->bHasSAVE = MNG_FALSE;
pMydata->bHasTERM = MNG_FALSE;
pMydata->bIsJASC = MNG_TRUE;
pMydata->iLastchunk = MNG_UINT_HUH;
pMydata->iTermaction = 0;
pMydata->iIteraction = 0;
pMydata->iDelay = 0;
pMydata->iItermax = 0;
/* can we open the input file ? */
if ((pMydata->hFileI = fopen (zFilenameI, "rb")) == NULL)
{ /* error out if we can't */
fprintf (stderr, "Cannot open input file %s.\n", zFilenameI);
return 1;
}
/* let's initialize the library */
pMydata->hHandleI = mng_initialize ((mng_ptr)pMydata, myalloc, myfree, MNG_NULL);
if (!pMydata->hHandleI) /* did that work out ? */
{
fprintf (stderr, "Cannot initialize libmng.\n");
iRC = 1;
}
else
{ /* some informatory messages */
fprintf (stderr, "Compiled with libmng %s.\n", MNG_VERSION_TEXT);
fprintf (stderr, "Running with libmng %s.\n", mng_version_text());
/* setup callbacks */
if ( ((iRC = mng_setcb_openstream (pMydata->hHandleI, myopenstream )) != 0) ||
((iRC = mng_setcb_closestream (pMydata->hHandleI, myclosestream )) != 0) ||
((iRC = mng_setcb_readdata (pMydata->hHandleI, myreaddata )) != 0) ||
((iRC = mng_setcb_errorproc (pMydata->hHandleI, myprocesserror)) != 0) )
fprintf (stderr, "Cannot set callbacks for libmng.\n");
else
{ /* reaad the file into memory */
if ((iRC = mng_read (pMydata->hHandleI)) != 0)
fprintf (stderr, "Cannot read the input file.\n");
else
{ /* run through the chunk list to get TERM */
if ((iRC = mng_iterate_chunks (pMydata->hHandleI, 0, myiterchunk)) != 0)
fprintf (stderr, "Cannot iterate the chunks.\n");
else
{
if (pMydata->iError) /* did the iteration fail somehow ? */
iRC = pMydata->iError;
else
{ /* can we open the output file ? */
if ((pMydata->hFileO = fopen (zFilenameO, "wb")) == NULL)
{ /* error out if we can't */
fprintf (stderr, "Cannot open output file %s.\n", zFilenameO);
iRC = 1;
}
else
{ /* let's initialize the library */
pMydata->hHandleO = mng_initialize ((mng_ptr)pMydata, myalloc, myfree, MNG_NULL);
if (!pMydata->hHandleO) /* did that work out ? */
{
fprintf (stderr, "Cannot initialize libmng.\n");
iRC = 1;
}
else
{ /* setup callbacks */
if ( ((iRC = mng_setcb_openstream (pMydata->hHandleO, myopenstream )) != 0) ||
((iRC = mng_setcb_closestream (pMydata->hHandleO, myclosestream)) != 0) ||
((iRC = mng_setcb_writedata (pMydata->hHandleO, mywritedata )) != 0) )
fprintf (stderr, "Cannot set callbacks for libmng.\n");
else
{
if ((iRC = mng_create (pMydata->hHandleO)) != 0)
fprintf (stderr, "Cannot create a new MNG.\n");
else
{ /* run through the chunk again and create the new file */
if ((iRC = mng_iterate_chunks (pMydata->hHandleI, 0, myiterchunk)) != 0)
fprintf (stderr, "Cannot iterate the chunks.\n");
else
{ /* did the iteration fail somehow ? */
if (pMydata->iError)
iRC = pMydata->iError;
else
{ /* now write the created new file !! */
if ((iRC = mng_write (pMydata->hHandleO)) != 0)
fprintf (stderr, "Cannot write the output file.\n");
}
}
}
}
/* cleanup the library */
mng_cleanup (&pMydata->hHandleO);
}
/* cleanup output file */
fclose (pMydata->hFileO);
}
}
}
}
}
mng_cleanup (&pMydata->hHandleI); /* cleanup the library */
}
fclose (pMydata->hFileI); /* cleanup input file and userdata */
free (pMydata);
return iRC;
}
/* ************************************************************************** */
int main(int argc, char *argv[])
{
if (argc > 2) /* need two (2) parameters ! */
return fixit (argv[1], argv[2]);
else
fprintf (stdout, "\nUsage: mngrepair <input.mng> <output.mng>\n\n");
return 0;
}
/* ************************************************************************** */