hello world

This commit is contained in:
Timothee 'TTimo' Besset
2011-11-22 15:28:15 -06:00
commit fb1609f554
2155 changed files with 1017022 additions and 0 deletions

View File

@@ -0,0 +1,105 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "../../../idlib/precompiled.h"
#pragma hdrstop
#include "roq.h"
void R_LoadImage( const char *name, byte **pic, int *width, int *height, ID_TIME_T *timestamp, bool makePowerOf2 );
NSBitmapImageRep::NSBitmapImageRep( void ) {
bmap = NULL;
width = 0;
height = 0;
timestamp = 0;
}
NSBitmapImageRep::NSBitmapImageRep( const char *filename ) {
R_LoadImage( filename, &bmap, &width, &height, &timestamp, false );
if (!width || !height) {
common->FatalError( "roqvq: unable to load image %s\n", filename );
}
}
NSBitmapImageRep::NSBitmapImageRep( int wide, int high ) {
bmap = (byte *)Mem_ClearedAlloc( wide * high * 4 );
width = wide;
height = high;
}
void R_StaticFree( void *data );
NSBitmapImageRep::~NSBitmapImageRep() {
R_StaticFree( bmap );
bmap = NULL;
}
int NSBitmapImageRep::samplesPerPixel( void ) {
return 4;
}
int NSBitmapImageRep::pixelsWide( void ) {
return width;
}
int NSBitmapImageRep::pixelsHigh( void ) {
return height;
}
byte * NSBitmapImageRep::bitmapData( void ) {
return bmap;
}
bool NSBitmapImageRep::hasAlpha( void ) {
return false;
}
bool NSBitmapImageRep::isPlanar( void ) {
return false;
}
NSBitmapImageRep &NSBitmapImageRep::operator=( const NSBitmapImageRep &a ) {
// check for assignment to self
if ( this == &a ) {
return *this;
}
if (bmap) {
Mem_Free(bmap);
}
bmap = (byte *)Mem_Alloc( a.width * a.height * 4 );
memcpy( bmap, a.bmap, a.width * a.height * 4 );
width = a.width;
height = a.height;
timestamp = a.timestamp;
return *this;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,108 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __codec_h__
#define __codec_h__
#define MAXERRORMAX 200
#define IPSIZE int
const float MOTION_MIN = 1.0f;
const float MIN_SNR = 3.0f;
#define FULLFRAME 0
#define JUSTMOTION 1
#define VQDATA double
#include "gdefs.h"
#include "roq.h"
#include "quaddefs.h"
class codec {
public:
codec();
~codec();
void SparseEncode( void );
void EncodeNothing( void );
void IRGBtab(void);
void InitImages(void);
void QuadX( int startX, int startY, int quadSize);
void InitQStatus();
float Snr(byte *old, byte *bnew, int size);
void FvqData( byte *bitmap, int size, int realx, int realy, quadcel *pquad, bool clamp);
void GetData( unsigned char *iData, int qSize, int startX, int startY, NSBitmapImageRep *bitmap);
int ComputeMotionBlock( byte *old, byte *bnew, int size);
void VqData8( byte *cel, quadcel *pquad);
void VqData4( byte *cel, quadcel *pquad);
void VqData2( byte *cel, quadcel *pquad);
int MotMeanY(void);
int MotMeanX(void);
void SetPreviousImage( const char*filename, NSBitmapImageRep *timage );
int BestCodeword( unsigned char *tempvector, int dimension, VQDATA **codebook );
private:
void VQ( const int numEntries, const int dimension, const unsigned char *vectors, float *snr, VQDATA **codebook, const bool optimize );
void Sort( float *list, int *intIndex, int numElements );
void Segment( int *alist, float *flist, int numElements, float rmse);
void LowestQuad( quadcel*qtemp, int* status, float* snr, int bweigh);
void MakePreviousImage( quadcel *pquad );
float GetCurrentRMSE( quadcel *pquad );
int GetCurrentQuadOutputSize( quadcel *pquad );
int AddQuad( quadcel *pquad, int lownum );
NSBitmapImageRep *image;
NSBitmapImageRep *newImage;
NSBitmapImageRep *previousImage[2]; // the ones in video ram and offscreen ram
int numQuadCels;
int whichFrame;
int slop;
bool detail;
int onQuad;
int initRGBtab;
quadcel *qStatus;
int dxMean;
int dyMean;
int codebooksize;
int index2[256];
int overAmount;
int pixelsWide;
int pixelsHigh;
int codebookmade;
bool used2[256];
bool used4[256];
int dimension2;
int dimension4;
byte luty[256];
byte *luti;
VQDATA **codebook2;
VQDATA **codebook4;
};
#endif // __codec_h__

View File

@@ -0,0 +1,68 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __gdefs_h__
#define __gdefs_h__
/*==================*
* TYPE DEFINITIONS *
*==================*/
typedef unsigned char byte;
typedef unsigned short word;
#pragma once
#define dabs(a) (((a)<0) ? -(a) : (a))
#define CLAMP(v,l,h) ((v)<(l) ? (l) : (v)>(h) ? (h) : v)
#define xswap(a,b) { a^=b; b^=a; a^=b; }
#define lum(a) ( 0.2990*(a>>16) + 0.5870*((a>>8)&0xff) + 0.1140*(a&0xff) )
#define gsign(a) ((a) < 0 ? -1 : 1)
#define mnint(a) ((a) < 0 ? (int)(a - 0.5) : (int)(a + 0.5))
#define mmax(a, b) ((a) > (b) ? (a) : (b))
#define mmin(a, b) ((a) < (b) ? (a) : (b))
#define RGBDIST( src0, src1 ) ( ((src0[0]-src1[0])*(src0[0]-src1[0])) + \
((src0[1]-src1[1])*(src0[1]-src1[1])) + \
((src0[2]-src1[2])*(src0[2]-src1[2])) )
#define RGBADIST( src0, src1 ) ( ((src0[0]-src1[0])*(src0[0]-src1[0])) + \
((src0[1]-src1[1])*(src0[1]-src1[1])) + \
((src0[2]-src1[2])*(src0[2]-src1[2])) + \
((src0[3]-src1[3])*(src0[3]-src1[3])) )
#define RMULT 0.2990f // use these for televisions
#define GMULT 0.5870f
#define BMULT 0.1140f
#define RIEMULT -0.16874f
#define RQEMULT 0.50000f
#define GIEMULT -0.33126f
#define GQEMULT -0.41869f
#define BIEMULT 0.50000f
#define BQEMULT -0.08131f
#endif // gdefs

View File

@@ -0,0 +1,131 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __quaddefs_h__
#define __quaddefs_h__
#pragma once
#define DEP 0
#define FCC 1
#define CCC 2
#define SLD 3
#define PAT 4
#define MOT 5
#define DEAD 6
#define COLA 0
#define COLB 1
#define COLC 2
#define COLS 3
#define COLPATA 4
#define COLPATB 5
#define COLPATS 6
#define GENERATION 7
#define CCCBITMAP 0
#define FCCDOMAIN 1
#define PATNUMBER 2
#define PATNUMBE2 3
#define PATNUMBE3 4
#define PATNUMBE4 5
#define PATNUMBE5 6
#define MAXSIZE 16
#define MINSIZE 4
#define RoQ_ID 0x1084
#define RoQ_QUAD 0x1000
#define RoQ_PUZZLE_QUAD 0x1003
#define RoQ_QUAD_HANG 0x1013
#define RoQ_QUAD_SMALL 0x1010
#define RoQ_QUAD_INFO 0x1001
#define RoQ_QUAD_VQ 0x1011
#define RoQ_QUAD_JPEG 0x1012
#define RoQ_QUAD_CODEBOOK 0x1002
typedef struct {
byte size; // 32, 16, 8, or 4
word xat; // where is it at on the screen
word yat; //
} shortQuadCel;
typedef struct {
byte size; // 32, 16, 8, or 4
word xat; // where is it at on the screen
word yat; //
float cccsnr; // ccc bitmap snr to actual image
float fccsnr; // fcc bitmap snr to actual image
float motsnr; // delta snr to previous image
float sldsnr; // solid color snr
float patsnr;
float dctsnr;
float rsnr; // what's the current snr
unsigned int cola; // color a for ccc
unsigned int colb; // color b for ccc
unsigned int colc; // color b for ccc
unsigned int sldcol; // sold color
unsigned int colpata;
unsigned int colpatb;
unsigned int colpats;
unsigned int bitmap; // ccc bitmap
word domain; // where to copy from for fcc
word patten[5]; // which pattern
int status;
bool mark;
float snr[DEAD+1]; // snrssss
} quadcel;
typedef struct {
float snr[DEAD+1]; // snrssss
unsigned int cols[8];
unsigned int bitmaps[7]; // ccc bitmap
} dataQuadCel;
typedef struct {
float normal;
unsigned short int index;
} norm;
typedef struct {
unsigned char dtlMap[256];
int r[4];
int g[4];
int b[4];
int a[4];
float ymean;
} dtlCel;
typedef struct {
byte r,g,b,a;
} pPixel;
#endif // quaddef

View File

@@ -0,0 +1,855 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "../../../idlib/precompiled.h"
#pragma hdrstop
#include "roq.h"
#include "codec.h"
roq *theRoQ; // current roq file
roq::roq( void )
{
image = 0;
quietMode = false;
encoder = 0;
previousSize = 0;
lastFrame = false;
dataStuff=false;
}
roq::~roq( void )
{
if (image) delete image;
if (encoder) delete encoder;
return;
}
void roq::EncodeQuietly( bool which )
{
quietMode = which;
}
bool roq::IsQuiet( void )
{
return quietMode;
}
bool roq::IsLastFrame( void )
{
return lastFrame;
}
bool roq::Scaleable( void )
{
return paramFile->IsScaleable();
}
bool roq::ParamNoAlpha( void )
{
return paramFile->NoAlpha();
}
bool roq::MakingVideo( void )
{
return true; //paramFile->timecode];
}
bool roq::SearchType( void )
{
return paramFile->SearchType();
}
bool roq::HasSound( void )
{
return paramFile->HasSound();
}
int roq::PreviousFrameSize( void )
{
return previousSize;
}
int roq::FirstFrameSize( void )
{
return paramFile->FirstFrameSize();
}
int roq::NormalFrameSize( void )
{
return paramFile->NormalFrameSize();
}
const char * roq::CurrentFilename( void )
{
return currentFile.c_str();
}
void roq::EncodeStream( const char *paramInputFile )
{
int onFrame;
idStr f0, f1, f2;
int morestuff;
onFrame = 1;
encoder = new codec;
paramFile = new roqParam;
paramFile->numInputFiles = 0;
paramFile->InitFromFile( paramInputFile );
if (!paramFile->NumberOfFrames()) {
return;
}
InitRoQFile( paramFile->outputFilename);
numberOfFrames = paramFile->NumberOfFrames();
if (paramFile->NoAlpha()==true) common->Printf("encodeStream: eluding alpha\n");
f0 = "";
f1 = paramFile->GetNextImageFilename();
if (( paramFile->MoreFrames() == true )) {
f2 = paramFile->GetNextImageFilename();
}
morestuff = numberOfFrames;
while( morestuff ) {
LoadAndDisplayImage( f1 );
if (onFrame==1) {
encoder->SparseEncode();
// WriteLossless();
} else {
if (!strcmp( f0, f1 ) && strcmp( f1, f2) ) {
WriteHangFrame();
} else {
encoder->SparseEncode();
}
}
onFrame++;
f0 = f1;
f1 = f2;
if (paramFile->MoreFrames() == true) {
f2 = paramFile->GetNextImageFilename();
}
morestuff--;
session->UpdateScreen();
}
// if (numberOfFrames != 1) {
// if (image->hasAlpha() && paramFile->NoAlpha()==false) {
// lastFrame = true;
// encoder->SparseEncode();
// } else {
// WriteLossless();
// }
// }
CloseRoQFile();
}
void roq::Write16Word( word *aWord, idFile *stream )
{
byte a, b;
a = *aWord & 0xff;
b = *aWord >> 8;
stream->Write( &a, 1 );
stream->Write( &b, 1 );
}
void roq::Write32Word( unsigned int *aWord, idFile *stream )
{
byte a, b, c, d;
a = *aWord & 0xff;
b = (*aWord >> 8) & 0xff;
c = (*aWord >> 16) & 0xff;
d = (*aWord >> 24) & 0xff;
stream->Write( &a, 1 );
stream->Write( &b, 1 );
stream->Write( &c, 1 );
stream->Write( &d, 1 );
}
int roq::SizeFile( idFile *ftosize )
{
return ftosize->Length();
}
/* Expanded data destination object for stdio output */
typedef struct {
struct jpeg_destination_mgr pub; /* public fields */
byte* outfile; /* target stream */
int size;
} my_destination_mgr;
typedef my_destination_mgr * my_dest_ptr;
/*
* Initialize destination --- called by jpeg_start_compress
* before any data is actually written.
*/
void roq::JPEGInitDestination (j_compress_ptr cinfo) {
my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
dest->pub.next_output_byte = dest->outfile;
dest->pub.free_in_buffer = dest->size;
}
/*
* Empty the output buffer --- called whenever buffer fills up.
*
* In typical applications, this should write the entire output buffer
* (ignoring the current state of next_output_byte & free_in_buffer),
* reset the pointer & count to the start of the buffer, and return true
* indicating that the buffer has been dumped.
*
* In applications that need to be able to suspend compression due to output
* overrun, a FALSE return indicates that the buffer cannot be emptied now.
* In this situation, the compressor will return to its caller (possibly with
* an indication that it has not accepted all the supplied scanlines). The
* application should resume compression after it has made more room in the
* output buffer. Note that there are substantial restrictions on the use of
* suspension --- see the documentation.
*
* When suspending, the compressor will back up to a convenient restart point
* (typically the start of the current MCU). next_output_byte & free_in_buffer
* indicate where the restart point will be if the current call returns FALSE.
* Data beyond this point will be regenerated after resumption, so do not
* write it out when emptying the buffer externally.
*/
boolean roq::JPEGEmptyOutputBuffer (j_compress_ptr cinfo) {
return true;
}
/*
* Compression initialization.
* Before calling this, all parameters and a data destination must be set up.
*
* We require a write_all_tables parameter as a failsafe check when writing
* multiple datastreams from the same compression object. Since prior runs
* will have left all the tables marked sent_table=true, a subsequent run
* would emit an abbreviated stream (no tables) by default. This may be what
* is wanted, but for safety's sake it should not be the default behavior:
* programmers should have to make a deliberate choice to emit abbreviated
* images. Therefore the documentation and examples should encourage people
* to pass write_all_tables=true; then it will take active thought to do the
* wrong thing.
*/
void roq::JPEGStartCompress (j_compress_ptr cinfo, bool write_all_tables) {
if (cinfo->global_state != CSTATE_START)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
if (write_all_tables)
jpeg_suppress_tables(cinfo, FALSE); /* mark all tables to be written */
/* (Re)initialize error mgr and destination modules */
(*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
(*cinfo->dest->init_destination) (cinfo);
/* Perform master selection of active modules */
jinit_compress_master(cinfo);
/* Set up for the first pass */
(*cinfo->master->prepare_for_pass) (cinfo);
/* Ready for application to drive first pass through jpeg_write_scanlines
* or jpeg_write_raw_data.
*/
cinfo->next_scanline = 0;
cinfo->global_state = (cinfo->raw_data_in ? CSTATE_RAW_OK : CSTATE_SCANNING);
}
/*
* Write some scanlines of data to the JPEG compressor.
*
* The return value will be the number of lines actually written.
* This should be less than the supplied num_lines only in case that
* the data destination module has requested suspension of the compressor,
* or if more than image_height scanlines are passed in.
*
* Note: we warn about excess calls to jpeg_write_scanlines() since
* this likely signals an application programmer error. However,
* excess scanlines passed in the last valid call are *silently* ignored,
* so that the application need not adjust num_lines for end-of-image
* when using a multiple-scanline buffer.
*/
JDIMENSION roq::JPEGWriteScanlines (j_compress_ptr cinfo, JSAMPARRAY scanlines, JDIMENSION num_lines) {
JDIMENSION row_ctr, rows_left;
if (cinfo->global_state != CSTATE_SCANNING)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
if (cinfo->next_scanline >= cinfo->image_height)
WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
/* Call progress monitor hook if present */
if (cinfo->progress != NULL) {
cinfo->progress->pass_counter = (long) cinfo->next_scanline;
cinfo->progress->pass_limit = (long) cinfo->image_height;
(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
}
/* Give master control module another chance if this is first call to
* jpeg_write_scanlines. This lets output of the frame/scan headers be
* delayed so that application can write COM, etc, markers between
* jpeg_start_compress and jpeg_write_scanlines.
*/
if (cinfo->master->call_pass_startup)
(*cinfo->master->pass_startup) (cinfo);
/* Ignore any extra scanlines at bottom of image. */
rows_left = cinfo->image_height - cinfo->next_scanline;
if (num_lines > rows_left)
num_lines = rows_left;
row_ctr = 0;
(*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, num_lines);
cinfo->next_scanline += row_ctr;
return row_ctr;
}
/*
* Terminate destination --- called by jpeg_finish_compress
* after all data has been written. Usually needs to flush buffer.
*
* NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
* application must deal with any cleanup that should happen even
* for error exit.
*/
static int hackSize;
void roq::JPEGTermDestination (j_compress_ptr cinfo) {
my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
size_t datacount = dest->size - dest->pub.free_in_buffer;
hackSize = datacount;
}
/*
* Prepare for output to a stdio stream.
* The caller must have already opened the stream, and is responsible
* for closing it after finishing compression.
*/
void roq::JPEGDest (j_compress_ptr cinfo, byte* outfile, int size) {
my_dest_ptr dest;
/* The destination object is made permanent so that multiple JPEG images
* can be written to the same file without re-executing jpeg_stdio_dest.
* This makes it dangerous to use this manager and a different destination
* manager serially with the same JPEG object, because their private object
* sizes may be different. Caveat programmer.
*/
if (cinfo->dest == NULL) { /* first time for this JPEG object? */
cinfo->dest = (struct jpeg_destination_mgr *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
sizeof(my_destination_mgr));
}
dest = (my_dest_ptr) cinfo->dest;
dest->pub.init_destination = JPEGInitDestination;
dest->pub.empty_output_buffer = JPEGEmptyOutputBuffer;
dest->pub.term_destination = JPEGTermDestination;
dest->outfile = outfile;
dest->size = size;
}
void roq::WriteLossless( void ) {
word direct;
uint directdw;
if (!dataStuff) {
InitRoQPatterns();
dataStuff=true;
}
direct = RoQ_QUAD_JPEG;
Write16Word( &direct, RoQFile);
/* This struct contains the JPEG compression parameters and pointers to
* working space (which is allocated as needed by the JPEG library).
* It is possible to have several such structures, representing multiple
* compression/decompression processes, in existence at once. We refer
* to any one struct (and its associated working data) as a "JPEG object".
*/
struct jpeg_compress_struct cinfo;
/* This struct represents a JPEG error handler. It is declared separately
* because applications often want to supply a specialized error handler
* (see the second half of this file for an example). But here we just
* take the easy way out and use the standard error handler, which will
* print a message on stderr and call exit() if compression fails.
* Note that this struct must live as long as the main JPEG parameter
* struct, to avoid dangling-pointer problems.
*/
struct jpeg_error_mgr jerr;
/* More stuff */
JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
int row_stride; /* physical row width in image buffer */
byte *out;
/* Step 1: allocate and initialize JPEG compression object */
/* We have to set up the error handler first, in case the initialization
* step fails. (Unlikely, but it could happen if you are out of memory.)
* This routine fills in the contents of struct jerr, and returns jerr's
* address which we place into the link field in cinfo.
*/
cinfo.err = jpeg_std_error(&jerr);
/* Now we can initialize the JPEG compression object. */
jpeg_create_compress(&cinfo);
/* Step 2: specify data destination (eg, a file) */
/* Note: steps 2 and 3 can be done in either order. */
/* Here we use the library-supplied code to send compressed data to a
* stdio stream. You can also write your own code to do something else.
* VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
* requires it in order to write binary files.
*/
out = (byte *)Mem_Alloc(image->pixelsWide()*image->pixelsHigh()*4);
JPEGDest(&cinfo, out, image->pixelsWide()*image->pixelsHigh()*4);
/* Step 3: set parameters for compression */
/* First we supply a description of the input image.
* Four fields of the cinfo struct must be filled in:
*/
cinfo.image_width = image->pixelsWide(); /* image width and height, in pixels */
cinfo.image_height = image->pixelsHigh();
cinfo.input_components = 4; /* # of color components per pixel */
cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
/* Now use the library's routine to set default compression parameters.
* (You must set at least cinfo.in_color_space before calling this,
* since the defaults depend on the source color space.)
*/
jpeg_set_defaults(&cinfo);
/* Now you can set any non-default parameters you wish to.
* Here we just illustrate the use of quality (quantization table) scaling:
*/
jpeg_set_quality(&cinfo, paramFile->JpegQuality(), true /* limit to baseline-JPEG values */);
/* Step 4: Start compressor */
/* true ensures that we will write a complete interchange-JPEG file.
* Pass true unless you are very sure of what you're doing.
*/
JPEGStartCompress(&cinfo, true);
/* Step 5: while (scan lines remain to be written) */
/* jpeg_write_scanlines(...); */
/* Here we use the library's state variable cinfo.next_scanline as the
* loop counter, so that we don't have to keep track ourselves.
* To keep things simple, we pass one scanline per call; you can pass
* more if you wish, though.
*/
row_stride = image->pixelsWide() * 4; /* JSAMPLEs per row in image_buffer */
byte *pixbuf = image->bitmapData();
while (cinfo.next_scanline < cinfo.image_height) {
/* jpeg_write_scanlines expects an array of pointers to scanlines.
* Here the array is only one element long, but you could pass
* more than one scanline at a time if that's more convenient.
*/
row_pointer[0] = &pixbuf[((cinfo.image_height-1)*row_stride)-cinfo.next_scanline * row_stride];
(void) JPEGWriteScanlines(&cinfo, row_pointer, 1);
}
/* Step 6: Finish compression */
jpeg_finish_compress(&cinfo);
/* After finish_compress, we can close the output file. */
directdw = hackSize;
common->Printf("writeLossless: writing %d bytes to RoQ_QUAD_JPEG\n", hackSize);
Write32Word( &directdw, RoQFile );
direct = 0; // flags
Write16Word( &direct, RoQFile );
RoQFile->Write( out, hackSize );
Mem_Free(out);
/* Step 7: release JPEG compression object */
/* This is an important step since it will release a good deal of memory. */
jpeg_destroy_compress(&cinfo);
/* And we're done! */
encoder->SetPreviousImage( "first frame", image );
}
void roq::InitRoQFile( const char *RoQFilename )
{
word i;
static int finit = 0;
if (!finit) {
finit++;
common->Printf("initRoQFile: %s\n", RoQFilename);
RoQFile = fileSystem->OpenFileWrite( RoQFilename );
// chmod(RoQFilename, S_IREAD|S_IWRITE|S_ISUID|S_ISGID|0070|0007 );
if ( !RoQFile ) {
common->Error("Unable to open output file %s.\n", RoQFilename);
}
i = RoQ_ID;
Write16Word( &i, RoQFile );
i = 0xffff;
Write16Word( &i, RoQFile );
Write16Word( &i, RoQFile );
// to retain exact file format write out 32 for new roq's
// on loading this will be noted and converted to 1000 / 30
// as with any new sound dump avi demos we need to playback
// at the speed the sound engine dumps the audio
i = 30; // framerate
Write16Word( &i, RoQFile );
}
roqOutfile = RoQFilename;
}
void roq::InitRoQPatterns( void )
{
uint j;
word direct;
direct = RoQ_QUAD_INFO;
Write16Word( &direct, RoQFile );
j = 8;
Write32Word( &j, RoQFile );
common->Printf("initRoQPatterns: outputting %d bytes to RoQ_INFO\n", j);
direct = image->hasAlpha();
if (ParamNoAlpha() == true) direct = 0;
Write16Word( &direct, RoQFile );
direct = image->pixelsWide();
Write16Word( &direct, RoQFile );
direct = image->pixelsHigh();
Write16Word( &direct, RoQFile );
direct = 8;
Write16Word( &direct, RoQFile );
direct = 4;
Write16Word( &direct, RoQFile );
}
void roq::CloseRoQFile( void )
{
common->Printf("closeRoQFile: closing RoQ file\n");
fileSystem->CloseFile( RoQFile );
}
void roq::WriteHangFrame( void )
{
uint j;
word direct;
common->Printf("*******************************************************************\n");
direct = RoQ_QUAD_HANG;
Write16Word( &direct, RoQFile);
j = 0;
Write32Word( &j, RoQFile);
direct = 0;
Write16Word( &direct, RoQFile);
}
void roq::WriteCodeBookToStream( byte *codebook, int csize, word cflags )
{
uint j;
word direct;
if (!csize) {
common->Printf("writeCodeBook: false VQ DATA!!!!\n");
return;
}
direct = RoQ_QUAD_CODEBOOK;
Write16Word( &direct, RoQFile);
j = csize;
Write32Word( &j, RoQFile);
common->Printf("writeCodeBook: outputting %d bytes to RoQ_QUAD_CODEBOOK\n", j);
direct = cflags;
Write16Word( &direct, RoQFile);
RoQFile->Write( codebook, j );
}
void roq::WriteCodeBook( byte *codebook )
{
memcpy( codes, codebook, 4096 );
}
void roq::WriteFrame( quadcel *pquad )
{
word action, direct;
int onCCC, onAction, i, code;
uint j;
byte *cccList;
bool *use2, *use4;
int dx,dy,dxMean,dyMean,index2[256],index4[256], dimension;
cccList = (byte *)Mem_Alloc( numQuadCels * 8); // maximum length
use2 = (bool *)Mem_Alloc(256*sizeof(bool));
use4 = (bool *)Mem_Alloc(256*sizeof(bool));
for(i=0;i<256;i++) {
use2[i] = false;
use4[i] = false;
}
action = 0;
j = onAction = 0;
onCCC = 2; // onAction going to go at zero
dxMean = encoder->MotMeanX();
dyMean = encoder->MotMeanY();
if (image->hasAlpha()) dimension = 10; else dimension = 6;
for (i=0; i<numQuadCels; i++) {
if ( pquad[i].size && pquad[i].size < 16 ) {
switch( pquad[i].status ) {
case SLD:
use4[pquad[i].patten[0]] = true;
use2[codes[dimension*256+(pquad[i].patten[0]*4)+0]] = true;
use2[codes[dimension*256+(pquad[i].patten[0]*4)+1]] = true;
use2[codes[dimension*256+(pquad[i].patten[0]*4)+2]] = true;
use2[codes[dimension*256+(pquad[i].patten[0]*4)+3]] = true;
break;
case PAT:
use4[pquad[i].patten[0]] = true;
use2[codes[dimension*256+(pquad[i].patten[0]*4)+0]] = true;
use2[codes[dimension*256+(pquad[i].patten[0]*4)+1]] = true;
use2[codes[dimension*256+(pquad[i].patten[0]*4)+2]] = true;
use2[codes[dimension*256+(pquad[i].patten[0]*4)+3]] = true;
break;
case CCC:
use2[pquad[i].patten[1]] = true;
use2[pquad[i].patten[2]] = true;
use2[pquad[i].patten[3]] = true;
use2[pquad[i].patten[4]] = true;
}
}
}
if (!dataStuff) {
dataStuff=true;
InitRoQPatterns();
if (image->hasAlpha()) i = 3584; else i = 2560;
WriteCodeBookToStream( codes, i, 0 );
for(i=0;i<256;i++) {
index2[i] = i;
index4[i] = i;
}
} else {
j = 0;
for(i=0;i<256;i++) {
if (use2[i]) {
index2[i] = j;
for(dx=0;dx<dimension;dx++) cccList[j*dimension+dx] = codes[i*dimension+dx];
j++;
}
}
code = j*dimension;
direct = j;
common->Printf("writeFrame: really used %d 2x2 cels\n", j);
j = 0;
for(i=0;i<256;i++) {
if (use4[i]) {
index4[i] = j;
for(dx=0;dx<4;dx++) cccList[j*4+code+dx] = index2[codes[i*4+(dimension*256)+dx]];
j++;
}
}
code += j*4;
direct = (direct<<8) + j;
common->Printf("writeFrame: really used %d 4x4 cels\n", j);
if (image->hasAlpha()) i = 3584; else i = 2560;
if ( code == i || j == 256) {
WriteCodeBookToStream( codes, i, 0 );
} else {
WriteCodeBookToStream( cccList, code, direct );
}
}
action = 0;
j = onAction = 0;
for (i=0; i<numQuadCels; i++) {
if ( pquad[i].size && pquad[i].size < 16 ) {
code = -1;
switch( pquad[i].status ) {
case DEP:
code = 3;
break;
case SLD:
code = 2;
cccList[onCCC++] = index4[pquad[i].patten[0]];
break;
case MOT:
code = 0;
break;
case FCC:
code = 1;
dx = ((pquad[i].domain >> 8 )) - 128 - dxMean + 8;
dy = ((pquad[i].domain & 0xff)) - 128 - dyMean + 8;
if (dx>15 || dx<0 || dy>15 || dy<0 ) {
common->Error("writeFrame: FCC error %d,%d mean %d,%d at %d,%d,%d rmse %f\n", dx,dy, dxMean, dyMean,pquad[i].xat,pquad[i].yat,pquad[i].size, pquad[i].snr[FCC] );
}
cccList[onCCC++] = (dx<<4)+dy;
break;
case PAT:
code = 2;
cccList[onCCC++] = index4[pquad[i].patten[0]];
break;
case CCC:
code = 3;
cccList[onCCC++] = index2[pquad[i].patten[1]];
cccList[onCCC++] = index2[pquad[i].patten[2]];
cccList[onCCC++] = index2[pquad[i].patten[3]];
cccList[onCCC++] = index2[pquad[i].patten[4]];
break;
case DEAD:
common->Error("dead cels in picture\n");
break;
}
if (code == -1) {
common->Error( "writeFrame: an error occurred writing the frame\n");
}
action = (action<<2)|code;
j++;
if (j == 8) {
j = 0;
cccList[onAction+0] = (action & 0xff);
cccList[onAction+1] = ((action >> 8) & 0xff);
onAction = onCCC;
onCCC += 2;
}
}
}
if (j) {
action <<= ((8-j)*2);
cccList[onAction+0] = (action & 0xff);
cccList[onAction+1] = ((action >> 8) & 0xff);
}
direct = RoQ_QUAD_VQ;
Write16Word( &direct, RoQFile);
j = onCCC;
Write32Word( &j, RoQFile);
direct = dyMean;
direct &= 0xff;
direct += (dxMean<<8); // flags
Write16Word( &direct, RoQFile);
common->Printf("writeFrame: outputting %d bytes to RoQ_QUAD_VQ\n", j);
previousSize = j;
RoQFile->Write( cccList, onCCC );
Mem_Free( cccList );
Mem_Free( use2 );
Mem_Free( use4 );
}
//
// load a frame, create a window (if neccesary) and display the frame
//
void roq::LoadAndDisplayImage( const char * filename )
{
if (image) delete image;
common->Printf("loadAndDisplayImage: %s\n", filename);
currentFile = filename;
image = new NSBitmapImageRep( filename );
numQuadCels = ((image->pixelsWide() & 0xfff0)*(image->pixelsHigh() & 0xfff0))/(MINSIZE*MINSIZE);
numQuadCels += numQuadCels/4 + numQuadCels/16;
// if (paramFile->deltaFrames] == true && cleared == false && [image isPlanar] == false) {
// cleared = true;
// imageData = [image data];
// memset( imageData, 0, image->pixelsWide()*image->pixelsHigh()*[image samplesPerPixel]);
// }
if (!quietMode) common->Printf("loadAndDisplayImage: %dx%d\n", image->pixelsWide(), image->pixelsHigh());
}
void roq::MarkQuadx( int xat, int yat, int size, float cerror, int choice ) {
}
NSBitmapImageRep* roq::CurrentImage( void )
{
return image;
}
int roq::NumberOfFrames( void ) {
return numberOfFrames;
}
void RoQFileEncode_f( const idCmdArgs &args ) {
if ( args.Argc() != 2 ) {
common->Printf( "Usage: roq <paramfile>\n" );
return;
}
theRoQ = new roq;
int startMsec = Sys_Milliseconds();
theRoQ->EncodeStream( args.Argv( 1 ) );
int stopMsec = Sys_Milliseconds();
common->Printf( "total encoding time: %i second\n", ( stopMsec - startMsec ) / 1000 );
}

View File

@@ -0,0 +1,135 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __roq_h__
#define __roq_h__
#include "gdefs.h"
#include "roqParam.h"
#include "quaddefs.h"
#define JPEG_INTERNALS
extern "C" {
#include "../../../renderer/jpeg-6/jpeglib.h"
}
#pragma once
class codec;
class roqParam;
class NSBitmapImageRep {
public:
NSBitmapImageRep( void );
NSBitmapImageRep( const char *filename );
NSBitmapImageRep( int wide, int high );
~NSBitmapImageRep();
NSBitmapImageRep & operator=( const NSBitmapImageRep &a );
int samplesPerPixel( void );
int pixelsWide( void );
int pixelsHigh( void );
byte * bitmapData( void );
bool hasAlpha( void );
bool isPlanar( void );
private:
byte * bmap;
int width;
int height;
ID_TIME_T timestamp;
};
class roq {
public:
roq();
~roq();
void WriteLossless( void );
void LoadAndDisplayImage( const char *filename );
void CloseRoQFile( bool which );
void InitRoQFile( const char *roqFilename );
void InitRoQPatterns( void );
void EncodeStream( const char *paramInputFile );
void EncodeQuietly( bool which );
bool IsQuiet( void );
bool IsLastFrame( void );
NSBitmapImageRep * CurrentImage( void );
void MarkQuadx( int xat, int yat, int size, float cerror, int choice );
void WritePuzzleFrame( quadcel *pquad );
void WriteFrame( quadcel *pquad );
void WriteCodeBook( byte *codebook );
void WwriteCodeBookToStream( byte *codes, int csize, word cflags );
int PreviousFrameSize( void );
bool MakingVideo( void );
bool ParamNoAlpha( void );
bool SearchType( void );
bool HasSound( void );
const char * CurrentFilename( void );
int NormalFrameSize( void );
int FirstFrameSize( void );
bool Scaleable( void );
void WriteHangFrame( void );
int NumberOfFrames( void );
private:
void Write16Word( word *aWord, idFile *stream );
void Write32Word( unsigned int *aWord, idFile *stream );
int SizeFile( idFile *ftosize );
void CloseRoQFile( void );
void WriteCodeBookToStream( byte *codebook, int csize, word cflags );
static void JPEGInitDestination( j_compress_ptr cinfo );
static boolean JPEGEmptyOutputBuffer( j_compress_ptr cinfo );
static void JPEGTermDestination( j_compress_ptr cinfo );
void JPEGStartCompress( j_compress_ptr cinfo, bool write_all_tables );
JDIMENSION JPEGWriteScanlines( j_compress_ptr cinfo, JSAMPARRAY scanlines, JDIMENSION num_lines );
void JPEGDest( j_compress_ptr cinfo, byte* outfile, int size );
void JPEGSave( char * filename, int quality, int image_width, int image_height, unsigned char *image_buffer );
codec * encoder;
roqParam * paramFile;
idFile * RoQFile;
NSBitmapImageRep * image;
int numQuadCels;
bool quietMode;
bool lastFrame;
idStr roqOutfile;
idStr currentFile;
int numberOfFrames;
int previousSize;
byte codes[4096];
bool dataStuff;
};
extern roq *theRoQ; // current roq
#endif /* !__roq_h__ */

View File

@@ -0,0 +1,933 @@
#import "roq.h"
#import "codec.h"
#ifdef __MACOS__
blah
#endif
@implementation roq
- init
{
cWindow = eWindow = sWindow = 0;
image = 0;
quietMode = NO;
encoder = 0;
previousSize = 0;
lastFrame = NO;
codes = malloc( 4*1024 );
dataStuff=NO;
return self;
}
- (void)dealloc
{
free( codes );
if (image) [image dealloc];
if (encoder) [encoder dealloc];
return;
}
- encodeQuietly:(BOOL)which
{
quietMode = which;
return self;
}
- (BOOL)isQuiet
{
return quietMode;
}
- (BOOL)isLastFrame
{
return lastFrame;
}
- (BOOL)scaleable
{
return [paramFileId isScaleable];
}
- (BOOL)paramNoAlpha
{
return [paramFileId noAlpha];
}
- (BOOL)makingVideo
{
return YES; //[paramFileId timecode];
}
- (BOOL)searchType
{
return [paramFileId searchType];
}
- (BOOL)hasSound
{
return [paramFileId hasSound];
}
- (int)previousFrameSize
{
return previousSize;
}
-(int)firstFrameSize
{
return [paramFileId firstFrameSize];
}
-(int)normalFrameSize
{
return [paramFileId normalFrameSize];
}
- (char *)currentFilename
{
return currentFile;
}
-encodeStream: (id)paramInputFile
{
int onFrame;
char f0[MAXPATHLEN], f1[MAXPATHLEN], f2[MAXPATHLEN];
int morestuff;
onFrame = 1;
encoder = [[codec alloc] init: self];
numberOfFrames = [paramInputFile numberOfFrames];
paramFileId = paramInputFile;
if ([paramInputFile noAlpha]==YES) printf("encodeStream: eluding alpha\n");
f0[0] = 0;
strcpy( f1, [paramInputFile getNextImageFilename]);
if (( [paramInputFile moreFrames] == YES )) strcpy( f2, [paramInputFile getNextImageFilename]);
morestuff = numberOfFrames;
while( morestuff ) {
[self loadAndDisplayImage: f1];
if (onFrame==1 && ([image hadAlpha]==NO || [paramInputFile noAlpha]==YES) && ![self makingVideo] && ![self scaleable]) {
[encoder sparseEncode: self];
// [self writeLossless];
} else {
if (!strcmp( f0, f1 ) && strcmp( f1, f2) ) {
[self writeHangFrame];
} else {
[encoder sparseEncode: self];
}
}
onFrame++;
strcpy( f0, f1 );
strcpy( f1, f2 );
if ([paramInputFile moreFrames] == YES) strcpy( f2, [paramInputFile getNextImageFilename]);
morestuff--;
}
if (numberOfFrames != 1) {
if ([image hadAlpha] && [paramInputFile noAlpha]==NO) {
lastFrame = YES;
[encoder sparseEncode: self];
} else {
[self writeLossless];
}
}
return self;
}
- write16Word:(word *)aWord to:(FILE *)stream
{
byte a, b;
a = *aWord & 0xff;
b = *aWord >> 8;
fputc( a, stream );
fputc( b, stream );
return self;
}
- write32Word:( unsigned int *)aWord to:(FILE *)stream
{
byte a, b, c, d;
a = *aWord & 0xff;
b = (*aWord >> 8) & 0xff;
c = (*aWord >> 16) & 0xff;
d = (*aWord >> 24) & 0xff;
fputc( a, stream );
fputc( b, stream );
fputc( c, stream );
fputc( d, stream );
return self;
}
-(int)sizeFile:(FILE *)ftosize;
{
long int fat, fend;
fat = ftell(ftosize);
fseek( ftosize, 0, SEEK_END );
fend = ftell(ftosize);
fseek( ftosize, fat, SEEK_SET);
return (fend);
}
- convertPlanertoPacked
{
byte *iPlane[5], *newdata, *olddata;
int x,y,index, sample, pixelsWide, pixelsHigh;
TByteBitmapImageRep *newImage;
pixelsWide = [image pixelsWide];
pixelsHigh = [image pixelsHigh];
printf("convertPlanertoPacked: converting\n");
newImage = [[TByteBitmapImageRep alloc] initWithBitmapDataPlanes: NULL
pixelsWide: pixelsWide
pixelsHigh: pixelsHigh
bitsPerSample: 8
samplesPerPixel: 4
hasAlpha: YES
isPlanar: NO
colorSpaceName: NSCalibratedRGBColorSpace
bytesPerRow: 0
bitsPerPixel: 0];
newdata = [newImage bitmapData];
index = 0;
if ([image isPlanar]) {
[image getBitmapDataPlanes: iPlane];
for(y=0;y<pixelsHigh;y++) {
for(x=0;x<pixelsWide;x++) {
newdata[index++] = iPlane[0][y*pixelsWide+x];
newdata[index++] = iPlane[1][y*pixelsWide+x];
newdata[index++] = iPlane[2][y*pixelsWide+x];
if ([image hasAlpha]) {
newdata[index++] = iPlane[3][y*pixelsWide+x];
} else {
newdata[index++] = 255;
}
}
}
} else {
sample = 0;
olddata = [image bitmapData];
for(y=0;y<pixelsHigh;y++) {
for(x=0;x<pixelsWide;x++) {
newdata[index++] = olddata[sample++];
newdata[index++] = olddata[sample++];
newdata[index++] = olddata[sample++];
if ([image hasAlpha]) {
newdata[index++] = olddata[sample++];
} else {
newdata[index++] = 255;
}
}
}
}
[image dealloc];
image = newImage;
return self;
}
- writeLossless
{
word direct;
unsigned int j;
char tempFile[MAXPATHLEN];
FILE *ftemp;
byte *buffer;
int res, mess;
[self convertPlanertoPacked];
if (!dataStuff) {
[self initRoQPatterns];
dataStuff=YES;
}
direct = RoQ_QUAD_JPEG;
[self write16Word: &direct to: RoQFile];
sprintf(tempFile, "%s.jpg",[paramFileId roqTempFilename]);
[image writeJFIF:tempFile quality: [paramFileId jpegQuality]];
ftemp = fopen(tempFile, "rb");
if (!ftemp) { fprintf(stderr, "Could not open temp file\n"); exit(1); }
j = [self sizeFile: ftemp];
printf("writeLossless: writing %d bytes to RoQ_QUAD_JPEG\n", j);
[self write32Word: &j to: RoQFile];
direct = 0; // flags
[self write16Word: &direct to: RoQFile];
buffer = malloc( 16384 );
do {
res = fread( buffer, 1, 16384, ftemp);
mess = fwrite( buffer, 1, res, RoQFile );
if (res != mess) { fprintf(stderr, "Could not write to output stream\n"); exit(1); }
} while ( res == 16384 );
free( buffer );
fclose(ftemp);
[encoder setPreviousImage: tempFile from: image parent: self];
remove( tempFile );
fflush( RoQFile );
return self;
}
- initRoQFile:(const char *)RoQFilename
{
word i;
static int finit = 0;
if (!finit) {
finit++;
printf("initRoQFile: %s\n", RoQFilename);
RoQFile = fopen( RoQFilename, "w" );
// chmod(RoQFilename, S_IREAD|S_IWRITE|S_ISUID|S_ISGID|0070|0007 );
if (!RoQFile) {
fprintf(stderr,"Unable to open output file %s.\n", RoQFilename);
exit(1);
}
i = RoQ_ID;
[self write16Word: &i to: RoQFile];
i = 0xffff;
[self write16Word: &i to: RoQFile];
[self write16Word: &i to: RoQFile];
i = 24; // framerate
[self write16Word: &i to: RoQFile];
fflush( RoQFile );
}
strcpy( roqOutfile, RoQFilename );
return self;
}
- initRoQPatterns
{
int j;
word direct;
direct = RoQ_QUAD_INFO;
[self write16Word: &direct to: RoQFile];
j = 8;
[self write32Word: &j to: RoQFile];
printf("initRoQPatterns: outputting %d bytes to RoQ_INFO\n", j);
direct = [image hadAlpha];
if ([self paramNoAlpha] == YES) direct = 0;
[self write16Word: &direct to: RoQFile];
direct = [image pixelsWide];
[self write16Word: &direct to: RoQFile];
direct = [image pixelsHigh];
[self write16Word: &direct to: RoQFile];
direct = 8;
[self write16Word: &direct to: RoQFile];
direct = 4;
[self write16Word: &direct to: RoQFile];
fflush( RoQFile );
return self;
}
- closeRoQFile
{
fflush( RoQFile );
printf("closeRoQFile: closing RoQ file\n");
fclose( RoQFile );
return self;
}
- writeHangFrame
{
int j;
word direct;
printf("*******************************************************************\n");
direct = RoQ_QUAD_HANG;
[self write16Word: &direct to: RoQFile];
j = 0;
[self write32Word: &j to: RoQFile];
direct = 0;
[self write16Word: &direct to: RoQFile];
return self;
}
- writeCodeBookToStream: (byte *)codebook size: (int)csize flags: (word)cflags
{
int j;
word direct;
if (!csize) {
printf("writeCodeBook: NO VQ DATA!!!!\n");
return self;
}
direct = RoQ_QUAD_CODEBOOK;
[self write16Word: &direct to: RoQFile];
j = csize;
[self write32Word: &j to: RoQFile];
printf("writeCodeBook: outputting %d bytes to RoQ_QUAD_CODEBOOK\n", j);
direct = cflags;
[self write16Word: &direct to: RoQFile];
fwrite( codebook, j, 1, RoQFile);
fflush( RoQFile );
return self;
}
- writeCodeBook: (byte *)codebook
{
memcpy( codes, codebook, 4096 );
return self;
}
- writeFrame:(quadcel *)pquad
{
word action, direct;
int onCCC, onAction, i, j, code;
byte *cccList;
BOOL *use2, *use4;
int dx,dy,dxMean,dyMean,index2[256],index4[256], dimension;
cccList = malloc( numQuadCels * 8); // maximum length
use2 = malloc(256*sizeof(BOOL));
use4 = malloc(256*sizeof(BOOL));
for(i=0;i<256;i++) {
use2[i] = NO;
use4[i] = NO;
}
action = 0;
j = onAction = 0;
onCCC = 2; // onAction going to go at zero
dxMean = [encoder motMeanX];
dyMean = [encoder motMeanY];
if ([image hadAlpha]) dimension = 10; else dimension = 6;
for (i=0; i<numQuadCels; i++) {
if ( pquad[i].size && pquad[i].size < 16 ) {
switch( pquad[i].status ) {
case SLD:
use4[pquad[i].patten[0]] = YES;
use2[codes[dimension*256+(pquad[i].patten[0]*4)+0]] = YES;
use2[codes[dimension*256+(pquad[i].patten[0]*4)+1]] = YES;
use2[codes[dimension*256+(pquad[i].patten[0]*4)+2]] = YES;
use2[codes[dimension*256+(pquad[i].patten[0]*4)+3]] = YES;
break;
case PAT:
use4[pquad[i].patten[0]] = YES;
use2[codes[dimension*256+(pquad[i].patten[0]*4)+0]] = YES;
use2[codes[dimension*256+(pquad[i].patten[0]*4)+1]] = YES;
use2[codes[dimension*256+(pquad[i].patten[0]*4)+2]] = YES;
use2[codes[dimension*256+(pquad[i].patten[0]*4)+3]] = YES;
break;
case CCC:
use2[pquad[i].patten[1]] = YES;
use2[pquad[i].patten[2]] = YES;
use2[pquad[i].patten[3]] = YES;
use2[pquad[i].patten[4]] = YES;
}
}
}
if (!dataStuff) {
dataStuff=YES;
[self initRoQPatterns];
if ([image hadAlpha]) i = 3584; else i = 2560;
[self writeCodeBookToStream: codes size: i flags: 0];
for(i=0;i<256;i++) {
index2[i] = i;
index4[i] = i;
}
} else {
j = 0;
for(i=0;i<256;i++) {
if (use2[i]) {
index2[i] = j;
for(dx=0;dx<dimension;dx++) cccList[j*dimension+dx] = codes[i*dimension+dx];
j++;
}
}
code = j*dimension;
direct = j;
printf("writeFrame: really used %d 2x2 cels\n", j);
j = 0;
for(i=0;i<256;i++) {
if (use4[i]) {
index4[i] = j;
for(dx=0;dx<4;dx++) cccList[j*4+code+dx] = index2[codes[i*4+(dimension*256)+dx]];
j++;
}
}
code += j*4;
direct = (direct<<8) + j;
printf("writeFrame: really used %d 4x4 cels\n", j);
if ([image hadAlpha]) i = 3584; else i = 2560;
if ( code == i || j == 256) {
[self writeCodeBookToStream: codes size: i flags: 0];
} else {
[self writeCodeBookToStream: cccList size: code flags: direct];
}
}
action = 0;
j = onAction = 0;
for (i=0; i<numQuadCels; i++) {
if ( pquad[i].size && pquad[i].size < 16 ) {
code = -1;
switch( pquad[i].status ) {
case DEP:
code = 3;
break;
case SLD:
code = 2;
cccList[onCCC++] = index4[pquad[i].patten[0]];
break;
case MOT:
code = 0;
break;
case FCC:
code = 1;
dx = ((pquad[i].domain >> 8 )) - 128 - dxMean + 8;
dy = ((pquad[i].domain & 0xff)) - 128 - dyMean + 8;
if (dx>15 || dx<0 || dy>15 || dy<0 ) {
printf("writeFrame: FCC error %d,%d mean %d,%d at %d,%d,%d rmse %f\n", dx,dy, dxMean, dyMean,pquad[i].xat,pquad[i].yat,pquad[i].size, pquad[i].snr[FCC] );
exit(1);
}
cccList[onCCC++] = (dx<<4)+dy;
break;
case PAT:
code = 2;
cccList[onCCC++] = index4[pquad[i].patten[0]];
break;
case CCC:
code = 3;
cccList[onCCC++] = index2[pquad[i].patten[1]];
cccList[onCCC++] = index2[pquad[i].patten[2]];
cccList[onCCC++] = index2[pquad[i].patten[3]];
cccList[onCCC++] = index2[pquad[i].patten[4]];
break;
case DEAD:
fprintf(stderr,"dead cels in picture\n");
break;
}
if (code == -1) {
fprintf(stderr, "writeFrame: an error occurred writing the frame\n");
exit(2);
}
action = (action<<2)|code;
j++;
if (j == 8) {
j = 0;
cccList[onAction+0] = (action & 0xff);
cccList[onAction+1] = ((action >> 8) & 0xff);
onAction = onCCC;
onCCC += 2;
}
}
}
if (j) {
action <<= ((8-j)*2);
cccList[onAction+0] = (action & 0xff);
cccList[onAction+1] = ((action >> 8) & 0xff);
}
direct = RoQ_QUAD_VQ;
[self write16Word: &direct to: RoQFile];
j = onCCC;
[self write32Word: &j to: RoQFile];
direct = dyMean;
direct &= 0xff;
direct += (dxMean<<8); // flags
[self write16Word: &direct to: RoQFile];
printf("writeFrame: outputting %d bytes to RoQ_QUAD_VQ\n", j);
previousSize = j;
fwrite( cccList, onCCC, 1, RoQFile );
fflush( RoQFile );
free( cccList );
free( use2 );
free( use4 );
return self;
}
- writePuzzleFrame:(quadcel *)pquad
{
return self;
}
- (TByteBitmapImageRep *)scaleImage: (TByteBitmapImageRep *)toscale
{
int newx, newy,x,y,s,linesize;
TByteBitmapImageRep *newImage;
unsigned char *i0, *i1;
int newv;
newx = 288;
if ([toscale pixelsHigh] == 160) {
newy = 320;
} else {
newy = [toscale pixelsHigh];
}
newImage = [[TByteBitmapImageRep alloc] initWithBitmapDataPlanes: NULL
pixelsWide: newx
pixelsHigh: newy
bitsPerSample: 8
samplesPerPixel: 4
hasAlpha: YES
isPlanar: NO
colorSpaceName: NSCalibratedRGBColorSpace
bytesPerRow: 0
bitsPerPixel: 0];
i0 = [toscale bitmapData];
i1 = [newImage bitmapData];
linesize = [toscale pixelsWide]*4;
for(y=0; y<newy; y++) {
for(x=0; x<320; x++) {
if (x>=16 && x<304) {
for(s=0;s<4;s++) {
if ([toscale pixelsHigh] == 160) {
newv = i0[(x*2+0)*4+(y>>1)*linesize+s];
newv += i0[(x*2+1)*4+(y>>1)*linesize+s];
newv += i0[(x*2+0)*4+((y>>1)+1)*linesize+s];
newv += i0[(x*2+1)*4+((y>>1)+1)*linesize+s];
newv = newv/4;
} else {
newv = i0[(x*2+0)*4+y*linesize+s];
newv += i0[(x*2+1)*4+y*linesize+s];
newv = newv/2;
}
i1[(x-16)*4+y*(288*4)+s] = newv;
}
}
}
}
return (newImage);
}
//
// load a frame, create a window (if neccesary) and display the frame
//
- loadAndDisplayImage: (const char *) filename
{
NSRect cRect;
char *secondFilename,firstFilename[MAXPATHLEN+1];
id image1;
NSSize newSize;
// unsigned char *imageData;
// static BOOL cleared = NO;
if (image) [image dealloc];
printf("loadAndDisplayImage: %s\n", filename);
strcpy( currentFile, filename );
image = [TByteBitmapImageRep alloc];
if (!(secondFilename= strchr(filename,'\n'))) { //one filename, no compositing
[image initFromFile: filename ];
}
else {
strncpy(firstFilename,filename,secondFilename-filename);
firstFilename[secondFilename-filename]='\0';
secondFilename++;//point past the \n
image1 = [[TByteBitmapImageRep alloc] initFromFile:firstFilename];
[image initFromFile: secondFilename ];//result will be in here
//image is the composite of those two...
[self composite:image1 to:image];
}
//
// wolf stuff
//
newSize.width = 256;
newSize.height = 256;
[image setSize: newSize];
if ([paramFileId output3DO] == YES) {
image1 = [self scaleImage: image];
[image dealloc];
image = image1;
}
numQuadCels = (([image pixelsWide] & 0xfff0)*([image pixelsHigh] & 0xfff0))/(MINSIZE*MINSIZE);
numQuadCels += numQuadCels/4 + numQuadCels/16;
// if ([paramFileId deltaFrames] == YES && cleared == NO && [image isPlanar] == NO) {
// cleared = YES;
// imageData = [image data];
// memset( imageData, 0, [image pixelsWide]*[image pixelsHigh]*[image samplesPerPixel]);
// }
if (!quietMode) printf("loadAndDisplayImage: %dx%d\n", [image pixelsWide], [image pixelsHigh]);
if (!quietMode) {
if (!cWindow) {
cRect.origin.x = 8.0 * 48.0;
cRect.origin.y = ([image pixelsHigh]+80);
cRect.size.width = [image pixelsWide];
cRect.size.height = [image pixelsHigh];
cWindow = [[NSWindow alloc] initWithContentRect:cRect styleMask:NSTitledWindowMask
backing:NSBackingStoreBuffered defer:NO];
cRect.origin.x = cRect.origin.y = 0.0;
// [[cWindow contentView] setClipping:NO];
[cWindow setTitle: @"current frame"];
[cWindow makeKeyAndOrderFront: [cWindow contentView]];
[cWindow display];
}
cRect = [[cWindow contentView] bounds];
[[cWindow contentView] lockFocus];
[image drawInRect: cRect];
[[cWindow contentView] unlockFocus];
[cWindow flushWindow];
if (!eWindow) {
cRect.origin.x = 8.0 * 48.0 - ([image pixelsWide]>>1) - 4;
cRect.origin.y = ([image pixelsHigh]+80);
cRect.size.width = [image pixelsWide] >> 1;
cRect.size.height = [image pixelsHigh] >> 1;
eWindow = [[NSWindow alloc] initWithContentRect:cRect styleMask:NSTitledWindowMask
backing:NSBackingStoreBuffered defer:NO];
cRect.origin.x = cRect.origin.y = 0.0;
// [[eWindow contentView] setClipping:NO];
[eWindow setTitle: @"cel error"];
[eWindow makeKeyAndOrderFront: [eWindow contentView]];
[eWindow display];
}
if (!sWindow) {
cRect.origin.x = 8.0 * 48.0 - ([image pixelsWide]>>1) - 4;
cRect.origin.y = ([image pixelsHigh]+80) + (([image pixelsHigh]+48)>>1);
cRect.size.width = [image pixelsWide] >> 1;
cRect.size.height = [image pixelsHigh] >> 1;
sWindow = [[NSWindow alloc] initWithContentRect: cRect styleMask:NSTitledWindowMask
backing:NSBackingStoreBuffered defer:NO];
cRect.origin.x = cRect.origin.y = 0.0;
// [[eWindow contentView] setClipping:NO];
[sWindow setTitle: @"quadtree map"];
[sWindow makeKeyAndOrderFront: [sWindow contentView]];
[sWindow display];
}
cRect = [[sWindow contentView] bounds];
[[sWindow contentView] lockFocus];
[image drawInRect: cRect];
[[sWindow contentView] unlockFocus];
[sWindow flushWindow];
cRect = [[eWindow contentView] bounds];
[[eWindow contentView] lockFocus];
[image drawInRect: cRect];
[[eWindow contentView] unlockFocus];
[eWindow flushWindow];
if (!errImage) {
errImage = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes: NULL
pixelsWide: 1
pixelsHigh: 1
bitsPerSample: 8
samplesPerPixel: 3
hasAlpha: NO
isPlanar: NO
colorSpaceName: NSCalibratedRGBColorSpace
bytesPerRow: 0
bitsPerPixel: 0];
}
// NSPing();
}
return self;
}
- markQuadx: (int)xat quady: (int)yat quads: (int)size error: (float)cerror type: (int)choice
{
NSRect cRect;
byte *err;
static int ywasat = -1;
if (!quietMode) {
cRect.origin.x = (xat)>>1;
cRect.origin.y = ([image pixelsHigh] - yat - size)>>1;
cRect.size.width = cRect.size.height = (size)>>1;
if (size < 1) {
[[sWindow contentView] lockFocus];
if (size == 8 && choice == 1) {
PSsetgray(NSWhite);
} else if (size == 8 && choice == 3) {
PSsetgray(NSLightGray);
} else if (size == 4) {
PSsetgray(NSDarkGray);
} else if (size == 2) {
PSsetgray(NSBlack);
}
NSFrameRectWithWidth(cRect,0.0);
[[sWindow contentView] unlockFocus];
if (!(ywasat & 31)) {
[sWindow flushWindow];
}
}
err = [errImage bitmapData];
err[0] = err[1] = err[2] = 0;
if ( cerror > 31 ) cerror = 31;
if (choice & 1) err[0] = (int)cerror*8;
if (choice & 2) err[1] = (int)cerror*8;
if (choice & 4) err[2] = (int)cerror*8;
[[eWindow contentView] lockFocus];
[errImage drawInRect: cRect];
[[eWindow contentView] unlockFocus];
if (!(ywasat & 31)) {
[eWindow flushWindow];
}
ywasat++;
}
return self;
}
- (NSBitmapImageRep*)currentImage
{
return image;
}
- (id)errorWindow
{
return eWindow;
}
- (id)scaleWindow
{
return sWindow;
}
- (int)numberOfFrames {
return numberOfFrames;
}
- composite:(NSBitmapImageRep *)source to: (NSBitmapImageRep *)destination
{
unsigned short value;
int x,y,bpp,inc,pixelsWide,pixelsHigh,yoff,pixel;
byte *iPlane[5], *dPlane[5];
bpp = [source samplesPerPixel];
pixelsWide = [source pixelsWide];
pixelsHigh = [source pixelsHigh];
if ([source isPlanar]) {
[source getBitmapDataPlanes: iPlane];
[destination getBitmapDataPlanes: dPlane];
for(y=0;y<pixelsHigh;y++) {
yoff = y*pixelsWide;
for(x=0;x<pixelsWide;x++) {
if ([destination hasAlpha]) {
value = dPlane[3][yoff+x];
} else {
value = 255;
}
if (value == 0) {
dPlane[0][yoff+x] = iPlane[0][yoff+x];
dPlane[1][yoff+x] = iPlane[1][yoff+x];
dPlane[2][yoff+x] = iPlane[2][yoff+x];
dPlane[3][yoff+x] = iPlane[3][yoff+x];
} else if (value != 255) {
pixel = ((iPlane[0][yoff+x]*(255-value))/255) + ((dPlane[0][yoff+x]*value)/255);
dPlane[0][yoff+x] = pixel;
pixel = ((iPlane[1][yoff+x]*(255-value))/255) + ((dPlane[1][yoff+x]*value)/255);
dPlane[1][yoff+x] = pixel;
pixel = ((iPlane[2][yoff+x]*(255-value))/255) + ((dPlane[2][yoff+x]*value)/255);
dPlane[2][yoff+x] = pixel;
if ([destination hasAlpha]) {
if (iPlane[3][yoff+x]>dPlane[3][yoff+x]) dPlane[3][yoff+x] = iPlane[3][yoff+x];
}
}
}
}
} else {
iPlane[0] = [source bitmapData];
dPlane[0] = [destination bitmapData];
for(y=0;y<pixelsHigh;y++) {
yoff = y*pixelsWide*bpp;
for(x=0;x<pixelsWide;x++) {
inc = x*bpp;
if ([destination hasAlpha]) {
value = dPlane[0][yoff+inc+3];
} else {
value = 255;
}
if (value == 0) {
dPlane[0][yoff+inc+0] = iPlane[0][yoff+inc+0];
dPlane[0][yoff+inc+1] = iPlane[0][yoff+inc+1];
dPlane[0][yoff+inc+2] = iPlane[0][yoff+inc+2];
dPlane[0][yoff+inc+3] = iPlane[0][yoff+inc+3];
} else if (value != 255) {
pixel = ((iPlane[0][yoff+inc+0]*(255-value))/255) + ((dPlane[0][yoff+inc+0]*value)/255);
dPlane[0][yoff+inc+0] = pixel;
pixel = ((iPlane[0][yoff+inc+1]*(255-value))/255) + ((dPlane[0][yoff+inc+1]*value)/255);
dPlane[0][yoff+inc+1] = pixel;
pixel = ((iPlane[0][yoff+inc+2]*(255-value))/255) + ((dPlane[0][yoff+inc+2]*value)/255);
dPlane[0][yoff+inc+2] = pixel;
if ([destination hasAlpha]) {
if (iPlane[0][yoff+inc+3]>dPlane[0][yoff+inc+3]) dPlane[0][yoff+inc+3] = iPlane[0][yoff+inc+3];
}
}
}
}
}
return self;
}
@end

View File

@@ -0,0 +1,635 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "../../../idlib/precompiled.h"
#pragma hdrstop
#include "roqParam.h"
//
// read a parameter file in (true I bloddy well had to do this again) (and yet again to c++)
//
int parseRange(const char *rangeStr,int field, int skipnum[], int startnum[], int endnum[],int numfiles[],bool padding[],int numpadding[] );
int parseTimecodeRange(const char *rangeStr,int field, int skipnum[], int startnum[], int endnum[],int numfiles[],bool padding[],int numpadding[] );
void roqParam::InitFromFile( const char *fileName )
{
idParser *src;
idToken token;
int i, readarg;
src = new idParser( fileName, LEXFL_NOSTRINGCONCAT | LEXFL_NOSTRINGESCAPECHARS | LEXFL_ALLOWPATHNAMES );
if ( !src->IsLoaded() ) {
delete src;
common->Printf("Error: can't open param file %s\n", fileName);
return;
}
common->Printf("initFromFile: %s\n", fileName);
fullSearch = false;
scaleDown = false;
encodeVideo = false;
addPath = false;
screenShots = false;
startPalette = false;
endPalette = false;
fixedPalette = false;
keyColor = false;
justDelta = false;
useTimecodeForRange = false;
onFrame = 0;
numInputFiles = 0;
currentPath[0] = '\0';
make3DO = false;
makeVectors = false;
justDeltaFlag = false;
noAlphaAtAll = false;
twentyFourToThirty = false;
hasSound = false;
isScaleable = false;
firstframesize = 56*1024;
normalframesize = 20000;
jpegDefault = 85;
realnum = 0;
while( 1 ) {
if ( !src->ReadToken( &token ) ) {
break;
}
readarg = 0;
// input dir
if (token.Icmp( "input_dir") == 0) {
src->ReadToken( &token );
addPath = true;
currentPath = token;
// common->Printf(" + input directory is %s\n", currentPath );
readarg++;
continue;
}
// input dir
if (token.Icmp( "scale_down") == 0) {
scaleDown = true;
// common->Printf(" + scaling down input\n" );
readarg++;
continue;
}
// full search
if (token.Icmp( "fullsearch") == 0) {
normalframesize += normalframesize/2;
fullSearch = true;
readarg++;
continue;
}
// scaleable
if (token.Icmp( "scaleable") == 0) {
isScaleable = true;
readarg++;
continue;
}
// input dir
if (token.Icmp( "no_alpha") == 0) {
noAlphaAtAll = true;
// common->Printf(" + scaling down input\n" );
readarg++;
continue;
}
if (token.Icmp( "24_fps_in_30_fps_out") == 0) {
twentyFourToThirty = true;
readarg++;
continue;
}
// video in
if (token.Icmp( "video_in") == 0) {
encodeVideo = true;
// common->Printf(" + Using the video port as input\n");
continue;
}
//timecode range
if (token.Icmp( "timecode") == 0) {
useTimecodeForRange = true;
firstframesize = 12*1024;
normalframesize = 4500;
// common->Printf(" + Using timecode as range\n");
continue;
}
// soundfile for making a .RnR
if (token.Icmp( "sound") == 0) {
src->ReadToken( &token );
soundfile = token;
hasSound = true;
// common->Printf(" + Using timecode as range\n");
continue;
}
// soundfile for making a .RnR
if (token.Icmp( "has_sound") == 0) {
hasSound = true;
continue;
}
// outfile
if (token.Icmp( "filename") == 0) {
src->ReadToken( &token );
outputFilename = token;
i = strlen(outputFilename);
// common->Printf(" + output file is %s\n", outputFilename );
readarg++;
continue;
}
// starting palette
if (token.Icmp( "start_palette") == 0) {
src->ReadToken( &token );
sprintf(startPal, "/LocalLibrary/vdxPalettes/%s", token.c_str());
// common->Error(" + starting palette is %s\n", startPal );
startPalette = true;
readarg++;
continue;
}
// ending palette
if (token.Icmp( "end_palette") == 0) {
src->ReadToken( &token );
sprintf(endPal, "/LocalLibrary/vdxPalettes/%s", token.c_str());
// common->Printf(" + ending palette is %s\n", endPal );
endPalette = true;
readarg++;
continue;
}
// fixed palette
if (token.Icmp( "fixed_palette") == 0) {
src->ReadToken( &token );
sprintf(startPal, "/LocalLibrary/vdxPalettes/%s", token.c_str());
// common->Printf(" + fixed palette is %s\n", startPal );
fixedPalette = true;
readarg++;
continue;
}
// these are screen shots
if (token.Icmp( "screenshot") == 0) {
// common->Printf(" + shooting screen shots\n" );
screenShots = true;
readarg++;
continue;
}
// key_color r g b
if (token.Icmp( "key_color") == 0) {
keyR = src->ParseInt();
keyG = src->ParseInt();
keyB = src->ParseInt();
keyColor = true;
// common->Printf(" + key color is %03d %03d %03d\n", keyR, keyG, keyB );
readarg++;
continue;
}
// only want deltas
if (token.Icmp( "just_delta") == 0) {
// common->Printf(" + outputting deltas in the night\n" );
// justDelta = true;
// justDeltaFlag = true;
readarg++;
continue;
}
// doing 3DO
if (token.Icmp( "3DO") == 0) {
make3DO = true;
readarg++;
continue;
}
// makes codebook vector tables
if (token.Icmp( "codebook") == 0) {
makeVectors = true;
readarg++;
continue;
}
// set first frame size
if (token.Icmp( "firstframesize") == 0) {
firstframesize = src->ParseInt();
readarg++;
continue;
}
// set normal frame size
if (token.Icmp( "normalframesize") == 0) {
normalframesize = src->ParseInt();
readarg++;
continue;
}
// set normal frame size
if (token.Icmp( "stillframequality") == 0) {
jpegDefault = src->ParseInt();
readarg++;
continue;
}
if (token.Icmp( "input") == 0) {
int num_files = 255;
range = (int *)Mem_ClearedAlloc( num_files * sizeof(int) );
padding = (bool *)Mem_ClearedAlloc( num_files * sizeof(bool) );
padding2 = (bool *)Mem_ClearedAlloc( num_files * sizeof(bool) );
skipnum = (int *)Mem_ClearedAlloc( num_files * sizeof(int) );
skipnum2 = (int *)Mem_ClearedAlloc( num_files * sizeof(int) );
startnum = (int *)Mem_ClearedAlloc( num_files * sizeof(int) );
startnum2 = (int *)Mem_ClearedAlloc( num_files * sizeof(int) );
endnum = (int *)Mem_ClearedAlloc( num_files * sizeof(int) );
endnum2 = (int *)Mem_ClearedAlloc( num_files * sizeof(int) );
numpadding = (int *)Mem_ClearedAlloc( num_files * sizeof(int) );
numpadding2 = (int *)Mem_ClearedAlloc( num_files * sizeof(int) );
numfiles = (int *)Mem_ClearedAlloc( num_files * sizeof(int) );
idStr empty;
file.AssureSize( num_files, empty );
file.AssureSize( num_files, empty );
field = 0;
realnum = 0;
do {
src->ReadToken(&token);
if ( token.Icmp( "end_input") != 0 ) {
idStr arg1, arg2, arg3;
file[field] = token;
while (src->ReadTokenOnLine( &token ) && token.Icmp( "[" ) ) {
file[field].Append( token );
}
arg1 = token;
while (src->ReadTokenOnLine( &token ) && token.Icmp( "[" ) ) {
arg1 += token;
}
arg2 = token;
while (src->ReadTokenOnLine( &token ) && token.Icmp( "[" ) ) {
arg2 += token;
}
arg3 = token;
while (src->ReadTokenOnLine( &token ) && token.Icmp( "[" ) ) {
arg3 += token;
}
if ( arg1[0] != '[' ) {
// common->Printf(" + reading %s\n", file[field] );
range[field] = 0;
numfiles[field] = 1;
realnum++;
}
else {
if ( arg1[0] == '[' )
{
range[field] = 1;
if (useTimecodeForRange) {
realnum += parseTimecodeRange( arg1, field, skipnum, startnum, endnum, numfiles, padding, numpadding);
// common->Printf(" + reading %s from %d to %d\n", file[field], startnum[field], endnum[field]);
}
else {
realnum += parseRange( arg1, field, skipnum, startnum, endnum, numfiles, padding, numpadding);
// common->Printf(" + reading %s from %d to %d\n", file[field], startnum[field], endnum[field]);
}
}
else if (( arg1[0] != '[' ) && ( arg2[0] == '[') && ( arg3[0] =='[')) { //a double ranger...
int files1,files2;
file2[field] = arg1;
range[field] = 2;
files1 = parseRange(arg2, field, skipnum, startnum, endnum, numfiles, padding, numpadding);
// common->Printf(" + reading %s from %d to %d\n", file[field], startnum[field], endnum[field]);
files2 = parseRange(arg3, field, skipnum2, startnum2, endnum2, numfiles, padding2, numpadding2);
// common->Printf(" + reading %s from %d to %d\n", file2[field], startnum2[field], endnum2[field]);
if (files1 != files2) {
common->Error( "You had %d files for %s and %d for %s!", files1, arg1.c_str(), files2, arg2.c_str() );
}
else {
realnum += files1;//not both, they are parallel
}
}
else {
common->Error("Error: invalid range on open (%s %s %s)\n", arg1.c_str(), arg2.c_str(), arg3.c_str() );
}
}
field++;
}
} while (token.Icmp( "end_input"));
}
}
if (TwentyFourToThirty()) realnum = realnum+(realnum>>2);
numInputFiles = realnum;
common->Printf(" + reading a total of %d frames in %s\n", numInputFiles, currentPath.c_str() );
delete src;
}
void roqParam::GetNthInputFileName( idStr &fileName, int n ) {
int i, myfield, index,hrs,mins,secs,frs;
char tempfile[33], left[256], right[256], *strp;
if ( n > realnum ) n = realnum;
// overcome starting at zero by ++ing and then --ing.
if (TwentyFourToThirty()) { n++; n = (n/5) * 4 + (n % 5); n--; }
i = 0;
myfield = 0;
while (i <= n) {
i += numfiles[myfield++];
}
myfield--;
i -= numfiles[myfield];
if ( range[myfield] == 1 ) {
strcpy( left, file[myfield] );
strp = strstr( left, "*" );
*strp++ = 0;
sprintf(right, "%s", strp);
if ( startnum[myfield] <= endnum[myfield] ) {
index = startnum[myfield] + ((n-i)*skipnum[myfield]);
} else {
index = startnum[myfield] - ((n-i)*skipnum[myfield]);
}
if ( padding[myfield] == true ) {
if (useTimecodeForRange) {
hrs = index/(30*60*60) ;
mins = (index/(30*60)) %60;
secs = (index/(30)) % 60;
frs = index % 30;
sprintf(fileName,"%s%.02d%.02d/%.02d%.02d%.02d%.02d%s",left,hrs,mins,hrs,mins,secs,frs,right);
}
else {
sprintf(tempfile, "%032d", index );
sprintf(fileName, "%s%s%s", left, &tempfile[ 32-numpadding[myfield] ], right );
}
} else {
if (useTimecodeForRange) {
hrs = index/(30*60*60) ;
mins = (index/(30*60)) %60;
secs = (index/(30)) % 60;
frs = index % 30;
sprintf(fileName,"%s%.02d%.02d/%.02d%.02d%.02d%.02d%s",left,hrs,mins,hrs,mins,secs,frs,right);
}
else {
sprintf(fileName, "%s%d%s", left, index, right );
}
}
} else if ( range[myfield] == 2 ) {
strcpy( left, file[myfield] );
strp = strstr( left, "*" );
*strp++ = 0;
sprintf(right, "%s", strp);
if ( startnum[myfield] <= endnum[myfield] ) {
index = startnum[myfield] + ((n-i)*skipnum[myfield]);
} else {
index = startnum[myfield] - ((n-i)*skipnum[myfield]);
}
if ( padding[myfield] == true ) {
sprintf(tempfile, "%032d", index );
sprintf(fileName, "%s%s%s", left, &tempfile[ 32-numpadding[myfield] ], right );
} else {
sprintf(fileName, "%s%d%s", left, index, right );
}
strcpy( left, file2[myfield] );
strp = strstr( left, "*" );
*strp++ = 0;
sprintf(right, "%s", strp);
if ( startnum2[myfield] <= endnum2[myfield] ) {
index = startnum2[myfield] + ((n-i)*skipnum2[myfield]);
} else {
index = startnum2[myfield] - ((n-i)*skipnum2[myfield]);
}
if ( padding2[myfield] == true ) {
sprintf(tempfile, "%032d", index );
fileName += va( "\n%s%s%s", left, &tempfile[ 32-numpadding2[myfield] ], right );
} else {
fileName += va( "\n%s%d%s", left, index, right );
}
} else {
fileName = file[myfield];
}
}
const char* roqParam::GetNextImageFilename( void ) {
idStr tempBuffer;
int i;
int len;
GetNthInputFileName( tempBuffer, onFrame++);
if ( justDeltaFlag == true ) {
onFrame--;
justDeltaFlag = false;
}
if ( addPath == true ) {
currentFile = currentPath + "/" + tempBuffer;
} else {
currentFile = tempBuffer;
}
len = currentFile.Length();
for(i=0;i<len;i++) {
if (currentFile[i] == '^') {
currentFile[i] = ' ';
}
}
return currentFile.c_str();
}
const char* roqParam::RoqFilename( void ) {
return outputFilename.c_str();
}
const char* roqParam::SoundFilename( void ) {
return soundfile.c_str();
}
const char* roqParam::RoqTempFilename( void ) {
int i, j, len;
j = 0;
len = outputFilename.Length();
for(i=0; i<len; i++ )
if ( outputFilename[i] == '/' ) j = i;
sprintf(tempFilename, "/%s.temp", &outputFilename[j+1] );
return tempFilename.c_str();
}
bool roqParam::Timecode( void ) {
return useTimecodeForRange;
}
bool roqParam::OutputVectors( void ) {
return makeVectors;
}
bool roqParam::HasSound( void ) {
return hasSound;
}
bool roqParam::DeltaFrames( void ) {
return justDelta;
}
bool roqParam::NoAlpha( void ) {
return noAlphaAtAll;
}
bool roqParam::SearchType( void ) {
return fullSearch;
}
bool roqParam::MoreFrames( void ) {
if (onFrame < numInputFiles) {
return true;
} else {
return false;
}
}
bool roqParam::TwentyFourToThirty( void ) {
return twentyFourToThirty;
}
int roqParam::NumberOfFrames( void ) {
return numInputFiles;
}
int roqParam::FirstFrameSize( void ) {
return firstframesize;
}
int roqParam::NormalFrameSize( void ) {
return normalframesize;
}
bool roqParam::IsScaleable( void ) {
return isScaleable;
}
int roqParam::JpegQuality( void ) {
return jpegDefault;
}
int parseRange(const char *rangeStr,int field, int skipnum[], int startnum[], int endnum[],int numfiles[],bool padding[],int numpadding[] ) {
char start[64], end[64], skip[64];
char *stptr, *enptr, *skptr;
int i,realnum;
i = 1;
realnum = 0;
stptr = start;
enptr = end;
skptr = skip;
do {
*stptr++ = rangeStr[i++];
} while ( rangeStr[i] >= '0' && rangeStr[i] <= '9' );
*stptr = '\0';
if ( rangeStr[i++] != '-' ) {
common->Error("Error: invalid range on middle \n");
}
do {
*enptr++ = rangeStr[i++];
} while ( rangeStr[i] >= '0' && rangeStr[i] <= '9' );
*enptr = '\0';
if ( rangeStr[i] != ']' ) {
if ( rangeStr[i++] != '+' ) {
common->Error("Error: invalid range on close\n");
}
do {
*skptr++ = rangeStr[i++];
} while ( rangeStr[i] >= '0' && rangeStr[i] <= '9' );
*skptr = '\0';
skipnum[field] = atoi( skip );
} else {
skipnum[field] = 1;
}
startnum[field] = atoi( start );
endnum[field] = atoi( end );
numfiles[field] = (abs( startnum[field] - endnum[field] ) / skipnum[field]) + 1;
realnum += numfiles[field];
if ( start[0] == '0' && start[1] != '\0' ) {
padding[field] = true;
numpadding[field] = strlen( start );
} else {
padding[field] = false;
}
return realnum;
}
int parseTimecodeRange(const char *rangeStr,int field, int skipnum[], int startnum[], int endnum[],int numfiles[],bool padding[],int numpadding[] )
{
char start[64], end[64], skip[64];
char *stptr, *enptr, *skptr;
int i,realnum,hrs,mins,secs,frs;
i = 1;//skip the '['
realnum = 0;
stptr = start;
enptr = end;
skptr = skip;
do {
*stptr++ = rangeStr[i++];
} while ( rangeStr[i] >= '0' && rangeStr[i] <= '9' );
*stptr = '\0';
if ( rangeStr[i++] != '-' ) {
common->Error("Error: invalid range on middle \n");
}
do {
*enptr++ = rangeStr[i++];
} while ( rangeStr[i] >= '0' && rangeStr[i] <= '9' );
*enptr = '\0';
if ( rangeStr[i] != ']' ) {
if ( rangeStr[i++] != '+' ) {
common->Error("Error: invalid range on close\n");
}
do {
*skptr++ = rangeStr[i++];
} while ( rangeStr[i] >= '0' && rangeStr[i] <= '9' );
*skptr = '\0';
skipnum[field] = atoi( skip );
} else {
skipnum[field] = 1;
}
sscanf(start,"%2d%2d%2d%2d",&hrs,&mins,&secs,&frs);
startnum[field] = hrs*30*60*60 + mins *60*30 + secs*30 +frs;
sscanf(end,"%2d%2d%2d%2d",&hrs,&mins,&secs,&frs);
endnum[field] = hrs*30*60*60 + mins *60*30 + secs*30 +frs;
numfiles[field] = (abs( startnum[field] - endnum[field] ) / skipnum[field]) + 1;
realnum += numfiles[field];
if ( start[0] == '0' && start[1] != '\0' ) {
padding[field] = true;
numpadding[field] = strlen( start );
} else {
padding[field] = false;
}
return realnum;
}

View File

@@ -0,0 +1,105 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __roqParam_h__
#define __roqParam_h__
#include "gdefs.h"
#pragma once
class roqParam
{
public:
const char* RoqFilename( void );
const char* RoqTempFilename( void );
const char* GetNextImageFilename( void );
const char* SoundFilename( void );
void InitFromFile( const char *fileName );
void GetNthInputFileName( idStr &fileName, int n);
bool MoreFrames( void );
bool OutputVectors( void );
bool Timecode( void );
bool DeltaFrames( void );
bool NoAlpha( void );
bool SearchType( void );
bool TwentyFourToThirty( void );
bool HasSound( void );
int NumberOfFrames( void );
int NormalFrameSize( void );
int FirstFrameSize( void );
int JpegQuality( void );
bool IsScaleable( void );
idStr outputFilename;
int numInputFiles;
private:
int *range;
bool *padding, *padding2;
idStrList file;
idStrList file2;
idStr soundfile;
idStr currentPath;
idStr tempFilename;
idStr startPal;
idStr endPal;
idStr currentFile;
int *skipnum, *skipnum2;
int *startnum, *startnum2;
int *endnum, *endnum2;
int *numpadding, *numpadding2;
int *numfiles;
byte keyR, keyG, keyB;
int field;
int realnum;
int onFrame;
int firstframesize;
int normalframesize;
int jpegDefault;
bool scaleDown;
bool twentyFourToThirty;
bool encodeVideo;
bool useTimecodeForRange;
bool addPath;
bool screenShots;
bool startPalette;
bool endPalette;
bool fixedPalette;
bool keyColor;
bool justDelta;
bool make3DO;
bool makeVectors;
bool justDeltaFlag;
bool noAlphaAtAll;
bool fullSearch;
bool hasSound;
bool isScaleable;
};
#endif // roqParam