mirror of
https://github.com/jmarshall23/DoomRTX.git
synced 2026-08-17 19:23:51 +02:00
Filesystem update.
This commit is contained in:
@@ -0,0 +1,826 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
IceTech GPL Source Code
|
||||
Copyright (C) 2026 Justin Marshall
|
||||
|
||||
This file is part of the IceTech GPL Source Code (?IceTech Source Code?).
|
||||
|
||||
IceTech 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.
|
||||
|
||||
IceTech 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 IceTech Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the IceTech 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 IceTech 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 Justin Marshall, justinmarshall20@gmail.com
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "roq.h"
|
||||
#include "codec.h"
|
||||
|
||||
/*
|
||||
=========================================================
|
||||
|
||||
JPEG writing now uses stb_image_write.h instead of libjpeg.
|
||||
|
||||
Put stb_image_write.h somewhere this project can include it.
|
||||
|
||||
IMPORTANT:
|
||||
Only define STB_IMAGE_WRITE_IMPLEMENTATION in ONE cpp file.
|
||||
If you already define it somewhere else, remove the define below.
|
||||
|
||||
=========================================================
|
||||
*/
|
||||
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#define STBI_WRITE_NO_STDIO
|
||||
#include "stb_image_write.h"
|
||||
|
||||
roq* theRoQ; // current roq file
|
||||
|
||||
/*
|
||||
================
|
||||
roqJpegMemoryBuffer
|
||||
|
||||
Small dynamic output buffer used by stbi_write_jpg_to_func().
|
||||
================
|
||||
*/
|
||||
struct roqJpegMemoryBuffer {
|
||||
byte* data;
|
||||
int size;
|
||||
int capacity;
|
||||
};
|
||||
|
||||
/*
|
||||
================
|
||||
RoQJpegGrowBuffer
|
||||
================
|
||||
*/
|
||||
static void RoQJpegGrowBuffer(roqJpegMemoryBuffer* buffer, int neededSize) {
|
||||
byte* newData;
|
||||
int newCapacity;
|
||||
|
||||
if (neededSize <= buffer->capacity) {
|
||||
return;
|
||||
}
|
||||
|
||||
newCapacity = buffer->capacity;
|
||||
|
||||
if (newCapacity <= 0) {
|
||||
newCapacity = 64 * 1024;
|
||||
}
|
||||
|
||||
while (newCapacity < neededSize) {
|
||||
newCapacity *= 2;
|
||||
}
|
||||
|
||||
newData = (byte*)Mem_Alloc(newCapacity);
|
||||
|
||||
if (buffer->data && buffer->size > 0) {
|
||||
memcpy(newData, buffer->data, buffer->size);
|
||||
}
|
||||
|
||||
if (buffer->data) {
|
||||
Mem_Free(buffer->data);
|
||||
}
|
||||
|
||||
buffer->data = newData;
|
||||
buffer->capacity = newCapacity;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
RoQJpegWriteCallback
|
||||
|
||||
stb_image_write calls this with chunks of encoded JPEG data.
|
||||
================
|
||||
*/
|
||||
static void RoQJpegWriteCallback(void* context, void* data, int size) {
|
||||
roqJpegMemoryBuffer* buffer;
|
||||
|
||||
if (!context || !data || size <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
buffer = (roqJpegMemoryBuffer*)context;
|
||||
|
||||
RoQJpegGrowBuffer(buffer, buffer->size + size);
|
||||
|
||||
memcpy(buffer->data + buffer->size, data, size);
|
||||
|
||||
buffer->size += size;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
roq::WriteLossless
|
||||
|
||||
Writes the first/lossless RoQ JPEG frame.
|
||||
|
||||
Old code used libjpeg directly.
|
||||
This version uses stb_image_write.h and writes the JPEG into memory,
|
||||
then writes that memory into the RoQ_QUAD_JPEG chunk.
|
||||
|
||||
The source image is assumed to be RGBA.
|
||||
JPEG has no alpha, so this writes RGB.
|
||||
================
|
||||
*/
|
||||
void roq::WriteLossless(void) {
|
||||
word direct;
|
||||
uint directdw;
|
||||
int imageWidth;
|
||||
int imageHeight;
|
||||
int srcStride;
|
||||
int dstStride;
|
||||
int quality;
|
||||
byte* srcPixels;
|
||||
byte* rgbPixels;
|
||||
int x;
|
||||
int y;
|
||||
roqJpegMemoryBuffer jpegBuffer;
|
||||
|
||||
if (!dataStuff) {
|
||||
InitRoQPatterns();
|
||||
dataStuff = true;
|
||||
}
|
||||
|
||||
if (!image || !image->bitmapData()) {
|
||||
common->Error("WriteLossless: no image loaded\n");
|
||||
return;
|
||||
}
|
||||
|
||||
imageWidth = image->pixelsWide();
|
||||
imageHeight = image->pixelsHigh();
|
||||
|
||||
if (imageWidth <= 0 || imageHeight <= 0) {
|
||||
common->Error("WriteLossless: bad image size %d x %d\n", imageWidth, imageHeight);
|
||||
return;
|
||||
}
|
||||
|
||||
direct = RoQ_QUAD_JPEG;
|
||||
Write16Word(&direct, RoQFile);
|
||||
|
||||
quality = paramFile->JpegQuality();
|
||||
|
||||
if (quality < 1) {
|
||||
quality = 1;
|
||||
}
|
||||
|
||||
if (quality > 100) {
|
||||
quality = 100;
|
||||
}
|
||||
|
||||
srcStride = imageWidth * 4;
|
||||
dstStride = imageWidth * 3;
|
||||
|
||||
srcPixels = image->bitmapData();
|
||||
|
||||
/*
|
||||
====================
|
||||
Convert RGBA to RGB and vertically flip.
|
||||
|
||||
The old libjpeg path fed rows from bottom to top:
|
||||
row_pointer[0] = bottom row - next_scanline.
|
||||
|
||||
Keep that behavior here so the encoded first frame matches the old orientation.
|
||||
====================
|
||||
*/
|
||||
rgbPixels = (byte*)Mem_Alloc(imageWidth * imageHeight * 3);
|
||||
|
||||
for (y = 0; y < imageHeight; y++) {
|
||||
const byte* srcRow;
|
||||
byte* dstRow;
|
||||
|
||||
srcRow = srcPixels + (imageHeight - 1 - y) * srcStride;
|
||||
dstRow = rgbPixels + y * dstStride;
|
||||
|
||||
for (x = 0; x < imageWidth; x++) {
|
||||
dstRow[x * 3 + 0] = srcRow[x * 4 + 0];
|
||||
dstRow[x * 3 + 1] = srcRow[x * 4 + 1];
|
||||
dstRow[x * 3 + 2] = srcRow[x * 4 + 2];
|
||||
}
|
||||
}
|
||||
|
||||
jpegBuffer.data = NULL;
|
||||
jpegBuffer.size = 0;
|
||||
jpegBuffer.capacity = 0;
|
||||
|
||||
if (!stbi_write_jpg_to_func(
|
||||
RoQJpegWriteCallback,
|
||||
&jpegBuffer,
|
||||
imageWidth,
|
||||
imageHeight,
|
||||
3,
|
||||
rgbPixels,
|
||||
quality)) {
|
||||
Mem_Free(rgbPixels);
|
||||
|
||||
if (jpegBuffer.data) {
|
||||
Mem_Free(jpegBuffer.data);
|
||||
}
|
||||
|
||||
common->Error("WriteLossless: stbi_write_jpg_to_func failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
Mem_Free(rgbPixels);
|
||||
|
||||
if (!jpegBuffer.data || jpegBuffer.size <= 0) {
|
||||
if (jpegBuffer.data) {
|
||||
Mem_Free(jpegBuffer.data);
|
||||
}
|
||||
|
||||
common->Error("WriteLossless: JPEG encoder produced no data\n");
|
||||
return;
|
||||
}
|
||||
|
||||
directdw = jpegBuffer.size;
|
||||
|
||||
common->Printf("writeLossless: writing %d bytes to RoQ_QUAD_JPEG\n", jpegBuffer.size);
|
||||
|
||||
Write32Word(&directdw, RoQFile);
|
||||
|
||||
direct = 0; // flags
|
||||
Write16Word(&direct, RoQFile);
|
||||
|
||||
RoQFile->Write(jpegBuffer.data, jpegBuffer.size);
|
||||
|
||||
Mem_Free(jpegBuffer.data);
|
||||
|
||||
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);
|
||||
|
||||
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 30 for new RoQs.
|
||||
i = 30;
|
||||
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);
|
||||
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;
|
||||
|
||||
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;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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 (!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);
|
||||
}
|
||||
Reference in New Issue
Block a user