mirror of
https://github.com/ondra-novak/gates_of_skeldal.git
synced 2025-07-12 17:32:30 -04:00
892 lines
21 KiB
C
892 lines
21 KiB
C
// MOTION GIF - LZW komprimovana animace v rozliseni 320x180 256 barev avsak
|
||
// upravena pro prehravani v HICOLOR pro konkretni rezim (32768 barev)
|
||
|
||
|
||
// Format
|
||
/*
|
||
|
||
[ FRAME ] <pocet_chunku 1b><delka frame 3b>
|
||
[CHUNK] <cislo_akce 1b><delka_chunku 3b> !pozor delka je 3 bajtova (tj 16MB)
|
||
0 - PRADNY CHUNK
|
||
1 - LZW FULL SCREEN
|
||
2 - MGIF DELTA
|
||
3 - HICOLOR PALETE
|
||
4 - SOUND TRACK
|
||
5 - TEXT TRACK
|
||
6 - MGIF COPY
|
||
7 - SOUND INIT
|
||
|
||
Popis Chunku:
|
||
PRAZDNY_CHUNK - muze obsahovat soukrome informace
|
||
|
||
LZW_FULL_SCREEN
|
||
- ihned za hlavickou nasleduje LZW komprimovany obrazek
|
||
v rozliseni 320x180 256 barev
|
||
|
||
MGIF_DELTA
|
||
- cely blok je LZW komprimovany. Po dekomprimace blok obsahuje
|
||
dva druhy informaci. Prvni DWORD je ofset od pocatku dat
|
||
ktery ukazuje na zacatek graficke informace. Po tomto
|
||
DWORDU jsou ulozeny data o umisteni grafickych bodu v obrazu
|
||
Prvni byte znaci, kolik je nutne preskocit slov. (tj *2 byte)
|
||
Dalsi byte znaci, kolik je nutne zapsat slov (tj *2 byte)
|
||
Po tomto bytu je nutne prenest presne tolik slov z
|
||
grafickeho bloku na obrazovku. Dvojice bajtu se opakuji
|
||
dokud ani jeden z nich nema nejvyssi 2 bity nastavene.
|
||
Pak tento byte znaci ze uz na radce nic vic neni. Dolni cast
|
||
byte (tj 6 bitu) pak udava pocet radku, ktere je treba pre-
|
||
skocit. (nula=zadny).
|
||
|
||
HICOLOR PALETTE
|
||
- Prvni byte znamena pocet aktivnich barev. Pak nasleduje
|
||
paleta ve formatu xRRRRRGGGGGBBBBB. Rozdil oproti vsem
|
||
beznym paletam je v tom ze neni treba v palete udrzovat
|
||
barvy, ktere uz na obrazovce jsou, protoze zmena palety
|
||
se neprojevi na jiz zobrazenem obrazku.
|
||
|
||
SOUND_TRACK
|
||
- Kazdy frame obsahuje zvukovou stopu. Je to RAW format.
|
||
Pro verzi MGIF97 zde je zvukova informace ulozena ve
|
||
zvukove kvalite 16-bit stereo 22000Khz, ovsem komprimovana
|
||
na 50% jako MUS.
|
||
TEXT_TRACK
|
||
- Navic je ve mozne ve frame umistit textovou zpravu (titulek)
|
||
Prvni WORD udava dobu zobrazeni (pocet frame).
|
||
Pote nasleduje text zakoncen znakem 0;
|
||
|
||
MGIF_COPY - Za timto CHUNKEM je ulozen blok dat v nezakomprimovanem
|
||
tvaru(tj 57600byte);
|
||
|
||
|
||
|
||
*/
|
||
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <types.h>
|
||
#include <bgraph.h>
|
||
#include <memman.h>
|
||
#include <mem.h>
|
||
#include <pcx.h>
|
||
#include "lzw.h"
|
||
#include <math.h>
|
||
#include <conio.h>
|
||
#include "jpegmgif.h"
|
||
|
||
#define MGIF "MGIF"
|
||
#define MGIF_Y "97"
|
||
#define VER 0x100
|
||
|
||
#define MGIF_EMPTY 0
|
||
#define MGIF_LZW 1
|
||
#define MGIF_DELTA 2
|
||
#define MGIF_PAL 3
|
||
#define MGIF_SOUND 4
|
||
#define MGIF_TEXT 5
|
||
#define MGIF_COPY 6
|
||
#define MGIF_SINIT 7
|
||
|
||
#define FRAME_X 320
|
||
#define FRAME_Y 180
|
||
#define FRAME_LEN (FRAME_X*FRAME_Y)
|
||
#define DELTA_LEN (3*FRAME_LEN)
|
||
#define LZW_LEN (2*FRAME_LEN)
|
||
|
||
#define SOUND_SPEED 44100
|
||
#define PRE_SOUND ((256*1024)/2)
|
||
|
||
#define ZTRATA lowq
|
||
#define BZTRATA colorq
|
||
#define MAX_FRAME max_fr
|
||
#define MIN_FRAME min_fr
|
||
|
||
#define BOXES_X 80
|
||
#define BOXES_Y 45
|
||
#define BOXES_ALL (BOXES_X*BOXES_Y)
|
||
|
||
#define SND_NAME ".SNF"
|
||
|
||
short mult_table[64];
|
||
short square_table[4096];
|
||
int statpic=0;
|
||
|
||
typedef struct mgif_header
|
||
{
|
||
char sign[4];
|
||
char year[2];
|
||
char eof;
|
||
word ver;
|
||
long frames;
|
||
word snd_chans;
|
||
int snd_freq;
|
||
short ampl_table[256];
|
||
short reserved[32];
|
||
};
|
||
|
||
word last_frame[FRAME_Y][FRAME_X];
|
||
char frame_delta[FRAME_LEN];
|
||
char delta_data[DELTA_LEN];
|
||
char frame_buffer[FRAME_LEN];
|
||
word color_state[32*32+32*32+32*32];
|
||
char calc_data[FRAME_LEN];
|
||
char flc_paleta[256][3];
|
||
int delta_data_size;
|
||
int frame_delta_size;
|
||
int speed=0;
|
||
int global_frame_counter=0;
|
||
int last_frame_size;
|
||
int total_frames;
|
||
|
||
int lowq=0;
|
||
int colorq=0;
|
||
int max_fr=99999;
|
||
int min_fr=0;
|
||
|
||
int hranice;
|
||
int hdiff=0;
|
||
int difdif=0;
|
||
|
||
TBOX *iib;
|
||
TBOX *rbb;
|
||
TBOX *gbb;
|
||
char *rgb_mem;
|
||
char frame_step=1;
|
||
|
||
struct mgif_header gh;
|
||
|
||
char lzw_buffer[LZW_LEN];
|
||
|
||
char pal_use[256],color_map[256];
|
||
word hipal[256],max_colors;
|
||
|
||
|
||
FILE *mgf;
|
||
|
||
long of_pos;
|
||
int of_chunks;
|
||
|
||
void open_frame()
|
||
{
|
||
of_chunks=0;
|
||
of_pos=ftell(mgf);
|
||
fwrite(&of_pos,1,4,mgf);
|
||
}
|
||
|
||
void close_frame()
|
||
{
|
||
long fsize,p;
|
||
|
||
last_frame_size=fsize=(p=ftell(mgf))-of_pos-4;
|
||
fseek(mgf,of_pos,SEEK_SET);
|
||
fwrite(&of_chunks,1,1,mgf);
|
||
fwrite(&fsize,1,3,mgf);
|
||
fseek(mgf,p,SEEK_SET);
|
||
total_frames++;
|
||
}
|
||
|
||
|
||
void write_chunk(char action,long size,void *data)
|
||
{
|
||
fwrite(&action,1,1,mgf);
|
||
fwrite(&size,1,3,mgf);
|
||
fwrite(data,1,size,mgf);
|
||
of_chunks++;
|
||
}
|
||
|
||
/*
|
||
void conv_2_hicolor()
|
||
{
|
||
int i,r,g,b;
|
||
for(i=0;i<256;i++)
|
||
{
|
||
r=(flc_paleta[i][0]>>3);
|
||
g=(flc_paleta[i][1]>>3);
|
||
b=(flc_paleta[i][2]>>3);
|
||
hipal[i]=((r<<10)+(g<<5)+b);
|
||
}
|
||
}
|
||
*/
|
||
|
||
void conv_2_rgb()
|
||
{
|
||
int i;
|
||
for(i=0;i<256;i++)
|
||
{
|
||
flc_paleta[i][0]=(hipal[i]>>10) & 0x1f;
|
||
flc_paleta[i][1]=(hipal[i]>>5)& 0x1f;
|
||
flc_paleta[i][2]=hipal[i]& 0x1f;
|
||
}
|
||
}
|
||
|
||
char find_color(word c); //najde barvu v palete a vraci byte
|
||
#pragma aux find_color parm [eax]=\
|
||
"mov edi,offset hipal"\
|
||
"mov ecx,256"\
|
||
"repne scasw"\
|
||
"mov eax,edi"\
|
||
"sub eax,offset hipal"\
|
||
"shr eax,1"\
|
||
"dec eax"\
|
||
value [al] modify[edi ecx];
|
||
|
||
|
||
void init_palmap()
|
||
{
|
||
int i;
|
||
memset(pal_use,0,sizeof(pal_use)); // nuluj pristupy k barvam
|
||
for(i=0;i<256;i++) color_map[i]=find_color(hipal[i]); //redukuj paletu;
|
||
max_colors=256; // pocet barev zatim 256;
|
||
}
|
||
|
||
int test_transp(char c,word w)
|
||
{
|
||
int r1,g1,b1;
|
||
int r2,g2,b2;
|
||
int diff;
|
||
|
||
r1=flc_paleta[c][0]>>3;
|
||
g1=flc_paleta[c][1]>>3;
|
||
b1=flc_paleta[c][2]>>3;
|
||
w&=0x7fff;
|
||
b2=w;g2=b2>>5;r2=g2>>5;b2&=0x1f;g2&=0x1f;
|
||
r1-=r2;g1-=g2;b1-=b2;
|
||
diff=r1*r1+g1*g1+b1*b1;
|
||
return diff<=hranice?diff:-1;
|
||
}
|
||
|
||
int change_color(char c1,char c2,int diff1)
|
||
{
|
||
int r1,g1,b1;
|
||
int r3,g3,b3;
|
||
int r4,g4,b4;
|
||
int diff2;
|
||
|
||
if (!diff1) return -1;
|
||
r1=flc_paleta[c1][0]>>3;
|
||
g1=flc_paleta[c1][1]>>3;
|
||
b1=flc_paleta[c1][2]>>3;
|
||
r3=flc_paleta[c2][0]>>3;
|
||
g3=flc_paleta[c2][1]>>3;
|
||
b3=flc_paleta[c2][2]>>3;
|
||
r4=r3-r1;g4=g3-g1;b4=b3-b1;
|
||
diff2=r4*r4+g4*g4+b4*b4;
|
||
if (diff2*2<diff1) return c2;else return -1;
|
||
}
|
||
|
||
void create_delta(char *frame_buffer)
|
||
{
|
||
char *delta;
|
||
char *data;
|
||
long colors2;
|
||
int x,y,i;
|
||
word *p;
|
||
char skip,skc,cpc;
|
||
char c1,c2,*a,d,c2old;
|
||
int d2;
|
||
|
||
delta=delta_data;
|
||
data=frame_delta;
|
||
a=frame_buffer;
|
||
c2old=color_map[*a];
|
||
for(y=0;y<180;y++)
|
||
{
|
||
p=&last_frame[y];
|
||
skip=1;
|
||
skc=0;
|
||
cpc=0;
|
||
for(x=0;x<160;x++)
|
||
{
|
||
c1=*a++;c2=*a++;
|
||
c1=color_map[c1];
|
||
c2=color_map[c2];i=0;
|
||
if ((d2=test_transp(c1,p[0]))>=0)
|
||
{/*if ((i=change_color(c1,c2old,d2))>=0) c1=i,d=0;else */d=1;}
|
||
else d=0;
|
||
c2old=c1;
|
||
if (d && (d2=test_transp(c2,p[1]))>=0)
|
||
{/*if (!d && (i=change_color(c2,c2old,d2))>=0) c2=i,d=0;else */d=1;}
|
||
else d=0;
|
||
c2old=c2;
|
||
if (d!=skip)
|
||
{
|
||
if (skip) *delta++=skc;else *delta++=cpc;
|
||
skip=!skip;skc=0;cpc=0;
|
||
}
|
||
if (!skip)
|
||
{
|
||
*data++=c1;
|
||
*data++=c2;
|
||
colors2=hipal[c1]+(hipal[c2]<<16);
|
||
*(long *)p=colors2;
|
||
cpc++;
|
||
}
|
||
else skc++;
|
||
p+=2;
|
||
pal_use[c1]=1;
|
||
pal_use[c2]=1;
|
||
}
|
||
if (!skip) *delta++=cpc;
|
||
if (skc==160 && *(delta-1)!=0xff && delta!=delta_data) delta[-1]++; //preskoc n radek
|
||
else *delta++=0xc0; //oznac konec radky
|
||
}
|
||
delta_data_size=delta-delta_data;
|
||
frame_delta_size=data-frame_delta;
|
||
}
|
||
|
||
|
||
void reduce_palette() //redukuje paletu na nejmensi nutny pocet barev
|
||
{
|
||
int i,j;
|
||
|
||
if (!speed) pal_use[0]=1;
|
||
for(i=0,j=0;i<256;i++)
|
||
{
|
||
if (pal_use[i])
|
||
{
|
||
hipal[j]=hipal[i];
|
||
color_map[i]=j++;
|
||
}
|
||
}
|
||
max_colors=j;
|
||
}
|
||
|
||
void filter_colors(void *block,int size,void *colormap); //prefiltruje blok dat podle color_map
|
||
#pragma aux filter_colors parm [edi][ecx][ebx]=\
|
||
"lp1: mov al,[edi]"\
|
||
" xlatb"\
|
||
" stosb"\
|
||
" loop lp1"\
|
||
modify [eax];
|
||
|
||
|
||
void *join_two_blocks(void *d1,void *d2,int siz1,int siz2,long *celk)
|
||
{
|
||
long siz;
|
||
char *d;
|
||
void *x;
|
||
|
||
siz=siz1+siz2+4;
|
||
d=(char *)getmem(siz);
|
||
x=d;
|
||
memcpy(d,&siz1,4);d+=4;
|
||
memcpy(d,d1,siz1);d+=siz1;
|
||
memcpy(d,d2,siz2);
|
||
*celk=siz;
|
||
return x;
|
||
}
|
||
|
||
void create_last_frame(void *source,void *target,void *pal,int size);
|
||
#pragma aux create_last_frame parm [esi][edi][ebx][ecx]=\
|
||
"lp1: lodsb"\
|
||
" movzx eax,al"\
|
||
" mov eax,[eax*2+ebx]"\
|
||
" stosw"\
|
||
" loop lp1"\
|
||
modify[eax]
|
||
|
||
|
||
void create_mgif_pal()
|
||
{
|
||
write_chunk(MGIF_PAL,max_colors*2,hipal);
|
||
}
|
||
|
||
|
||
void create_mgif_lzw()
|
||
{
|
||
int siz;
|
||
|
||
//conv_2_rgb();
|
||
init_palmap();
|
||
create_mgif_pal();
|
||
filter_colors(frame_buffer,FRAME_LEN,color_map);
|
||
create_last_frame(frame_buffer,last_frame,hipal,FRAME_LEN);
|
||
init_lzw_compressor(8);
|
||
memset(lzw_buffer,0,sizeof(lzw_buffer));
|
||
siz=lzw_encode(frame_buffer,lzw_buffer,FRAME_LEN);
|
||
if (siz>FRAME_LEN) write_chunk(MGIF_COPY,FRAME_LEN,frame_buffer);
|
||
else write_chunk(MGIF_LZW,siz,lzw_buffer);
|
||
done_lzw_compressor(8);
|
||
}
|
||
|
||
|
||
void create_color_state()
|
||
{
|
||
int i;
|
||
int r1,g1,b1;
|
||
int r2,g2,b2;
|
||
int diff;
|
||
char *c;
|
||
word *w;
|
||
|
||
memset(color_state,0,sizeof(color_state));
|
||
c=frame_buffer;
|
||
w=last_frame;
|
||
for(i=0;i<FRAME_LEN;i++)
|
||
{
|
||
r1=flc_paleta[*c][0]>>3;
|
||
g1=flc_paleta[*c][1]>>3;
|
||
b1=flc_paleta[*c][2]>>3;
|
||
b2=*w;g2=b2>>5;r2=g2>>5;b2&=0x1f;g2&=0x1f;
|
||
r1-=r2;g1-=g2;b1-=b2;
|
||
diff=abs(r1)+abs(g1<<1)+abs(b1);
|
||
color_state[diff]++;
|
||
c++;w++;
|
||
}
|
||
}
|
||
|
||
void set_max_color_change(int cchange)
|
||
{
|
||
int i,s;
|
||
|
||
s=0;cchange=57600-cchange;
|
||
for(i=sizeof(color_state)/sizeof(word)-1;s<cchange && i>0;i--) s+=color_state[i];
|
||
if (s>=cchange) i++;
|
||
hranice=i+hdiff;if (hranice<0) hranice=0;
|
||
}
|
||
|
||
int rozptyl(int v1,int v2)
|
||
{
|
||
int c1,c2,x,s;
|
||
x=v1+v2>>1;
|
||
c1=(x-v1);
|
||
c2=(x-v2);
|
||
s=c1*c1+c2*c2;
|
||
return s;
|
||
}
|
||
|
||
void create_low_quality()
|
||
{
|
||
void *snd;int l;
|
||
char *sn,*sr,c1,c2;
|
||
int rs,bs,gs;
|
||
|
||
l=FRAME_LEN;
|
||
sr=frame_buffer;
|
||
snd=calc_data;
|
||
sn=(char *)snd;
|
||
l--;
|
||
while (l--)
|
||
{
|
||
c1=*sr++;
|
||
c2=*sr;
|
||
rs=rozptyl(flc_paleta[c1][0],flc_paleta[c2][0]);
|
||
gs=rozptyl(flc_paleta[c1][1],flc_paleta[c2][1]);
|
||
bs=rozptyl(flc_paleta[c1][2],flc_paleta[c2][2]);
|
||
if (rs+gs+bs<ZTRATA)
|
||
{
|
||
*sn++=c1;
|
||
*sn++=c1;
|
||
sr++;if(!l--) break;
|
||
}
|
||
else
|
||
{
|
||
*sn++=c1;
|
||
*sn++=c2;
|
||
sr++;
|
||
if(!l--) break;
|
||
}
|
||
}
|
||
create_delta(snd);
|
||
}
|
||
|
||
void create_mgif_delta()
|
||
{
|
||
void *d;
|
||
long siz;
|
||
|
||
//conv_2_rgb();
|
||
init_palmap();
|
||
if (BZTRATA) create_color_state();
|
||
set_max_color_change(BZTRATA);
|
||
create_low_quality();
|
||
if (delta_data_size+frame_delta_size>FRAME_LEN)
|
||
{
|
||
create_mgif_lzw();
|
||
return;
|
||
}
|
||
if (!frame_delta_size) return;
|
||
reduce_palette();
|
||
filter_colors(frame_delta,frame_delta_size,color_map);
|
||
d=join_two_blocks(delta_data,frame_delta,delta_data_size,frame_delta_size,&siz);
|
||
init_lzw_compressor(8);
|
||
memset(lzw_buffer,0,sizeof(lzw_buffer));
|
||
siz=lzw_encode(d,lzw_buffer,siz);
|
||
done_lzw_compressor();
|
||
free(d);
|
||
if (siz>FRAME_LEN)
|
||
{
|
||
create_mgif_lzw();
|
||
return;
|
||
}
|
||
write_chunk(MGIF_DELTA,siz,lzw_buffer);
|
||
create_mgif_pal();
|
||
}
|
||
|
||
void prepare_for_mjpg()
|
||
{
|
||
iib=getmem(sizeof(TBOX)*BOXES_ALL);
|
||
rbb=getmem(sizeof(TBOX)*BOXES_ALL);
|
||
gbb=getmem(sizeof(TBOX)*BOXES_ALL);
|
||
memset(iib,0,sizeof(TBOX)*BOXES_ALL);
|
||
memset(rbb,0,sizeof(TBOX)*BOXES_ALL);
|
||
memset(gbb,0,sizeof(TBOX)*BOXES_ALL);
|
||
ibox=iib;
|
||
rbbox=rbb;
|
||
gbbox=gbb;
|
||
rgb_mem=getmem(FRAME_LEN*3);
|
||
create_cos_tab();
|
||
}
|
||
|
||
void create_jpg_frame()
|
||
{
|
||
int i,x,y,a;
|
||
char *dl=delta_data;
|
||
char *r=rgb_mem;
|
||
char *p=frame_buffer;
|
||
|
||
conv_2_rgb();
|
||
for(i=0;i<FRAME_LEN;i++)
|
||
{
|
||
*r++=flc_paleta[*p][0];
|
||
*r++=flc_paleta[*p][1];
|
||
*r++=flc_paleta[*p][2];
|
||
p++;
|
||
}
|
||
a=0;
|
||
for(y=0;y<BOXES_Y;y++)
|
||
for(x=0;x<BOXES_X;x++,a++)
|
||
{
|
||
int siz;
|
||
siz=transformace(rgb_mem+(y*4*12*BOXES_X+x*12),dl,320,a);
|
||
dl+=siz;
|
||
}
|
||
dl=delta_data;
|
||
a=0;
|
||
memset(iib,0,sizeof(TBOX)*BOXES_ALL);
|
||
memset(rbb,0,sizeof(TBOX)*BOXES_ALL);
|
||
memset(gbb,0,sizeof(TBOX)*BOXES_ALL);
|
||
for(y=0;y<BOXES_Y;y++)
|
||
for(x=0;x<BOXES_X;x++,a++)
|
||
{
|
||
zpetna_transformace(&dl,lbuffer+(y*8*BOXES_X+x)*8,a);
|
||
}
|
||
getchar();
|
||
}
|
||
|
||
void create_sound_track(int size)
|
||
{
|
||
void *p;
|
||
|
||
p=getmem(size);
|
||
memset(p,0,size);
|
||
write_chunk(MGIF_SOUND,size,p);
|
||
free(p);
|
||
}
|
||
|
||
void reserve_track()
|
||
{
|
||
int size;
|
||
|
||
if (!speed) return;
|
||
size=SOUND_SPEED/speed;
|
||
size&=~1;
|
||
create_sound_track(size);
|
||
}
|
||
|
||
void prereserve_tracks()
|
||
{
|
||
int size;
|
||
int celk;
|
||
|
||
if (!speed) return;
|
||
size=SOUND_SPEED/speed;
|
||
size&=~1;
|
||
celk=PRE_SOUND;
|
||
while (celk-size>0)
|
||
{
|
||
open_frame();
|
||
create_sound_track(size);
|
||
close_frame();
|
||
celk-=size;
|
||
}
|
||
if (celk)
|
||
{
|
||
open_frame();
|
||
create_sound_track(celk);
|
||
close_frame();
|
||
}
|
||
}
|
||
|
||
void fill_header(int frames)
|
||
{
|
||
memset(&gh,0,sizeof(gh));
|
||
strncpy(gh.sign,MGIF,4);
|
||
strncpy(gh.year,MGIF_Y,2);
|
||
gh.eof=26;
|
||
gh.ver=VER;
|
||
gh.frames=frames;
|
||
}
|
||
|
||
|
||
|
||
void show_screen()
|
||
{
|
||
word *c;
|
||
int i,j;
|
||
word *w;
|
||
|
||
c=last_frame;
|
||
w=screen;
|
||
for(i=0;i<180;i++)
|
||
{
|
||
for(j=0;j<320;j++)
|
||
{
|
||
*w++=*c;
|
||
*w++=*c;
|
||
c++;
|
||
}
|
||
w+=640;
|
||
}
|
||
showview(0,0,640,360);
|
||
showview(0,400,639,30);
|
||
}
|
||
|
||
|
||
void write_frame_size(int i,int col)
|
||
{
|
||
char s[200];
|
||
sprintf(s,"SIZE: %05d COLORS: %03d COMP.LEVEL %03d",i,col,hranice);position(0,400);outtext(s);
|
||
}
|
||
|
||
char *get_pcx_name(char *name,int x)
|
||
{
|
||
static char s[256];
|
||
char c[10],e[20],*z;
|
||
int d;
|
||
|
||
z=strchr(name,'#');
|
||
if (z==NULL)
|
||
{
|
||
memset(s,0,sizeof(s));
|
||
strncpy(s,name,240);
|
||
d=strlen(s);
|
||
if (x>9999)
|
||
{
|
||
s[d-1]=0;
|
||
sprintf(s,"%s%05d.pcx",s,x);
|
||
}
|
||
else sprintf(s,"%s%04d.pcx",s,x);
|
||
strupr(s);
|
||
}
|
||
else
|
||
{
|
||
int pocet,i;
|
||
pocet=0;
|
||
while(*z) if (*z++=='#') pocet++;
|
||
sprintf(c,"%%0%dd",pocet);
|
||
sprintf(e,c,x);
|
||
strcpy(s,name);
|
||
z=strchr(s,'#');
|
||
for(i=0;i<pocet;z++) if (*z=='#') *z=e[i],i++;
|
||
}
|
||
return s;
|
||
}
|
||
|
||
void write_frame_name(char *name,int x)
|
||
{
|
||
char s[256];
|
||
curcolor=0;bar(0,400,639,420);
|
||
sprintf(s,"FRAME: %d FILE: %s",x,get_pcx_name(name,x));position(0,410);outtext(s);
|
||
}
|
||
|
||
|
||
char get_pcx_frame(char *name,int x)
|
||
{
|
||
char *buf;
|
||
|
||
if (open_pcx(get_pcx_name(name,x),A_8BIT,&buf)) return 0;
|
||
memcpy(frame_buffer,buf+6+512,FRAME_LEN);
|
||
memcpy(hipal,buf+6,512);
|
||
free(buf);
|
||
return 1;
|
||
}
|
||
|
||
compress_pcx(char *name)
|
||
{
|
||
int x=0;
|
||
|
||
get_palette_ptr=flc_paleta;
|
||
curcolor=0;bar(0,0,639,479);
|
||
//prepare_for_mjpg();
|
||
while (get_pcx_frame(name,x))
|
||
{
|
||
open_frame();
|
||
if (x) create_mgif_delta();else create_mgif_lzw();
|
||
reserve_track();
|
||
//create_jpg_frame();
|
||
close_frame();
|
||
curcolor=0;bar(0,400,639,430);
|
||
write_frame_name(name,x);
|
||
write_frame_size(last_frame_size,max_colors);
|
||
if (last_frame_size>MAX_FRAME) {difdif=difdif<=0?1:difdif+1;hdiff+=difdif;}
|
||
else if (last_frame_size<MIN_FRAME && hranice>0) {difdif=difdif>=0?-1:difdif-1;hdiff+=difdif;}
|
||
else if (hdiff>0) {difdif=difdif>=0?-1:difdif-1;hdiff+=difdif;}else if(hdiff<0) hdiff=0;
|
||
show_screen ();
|
||
if (statpic) statpic--;else x+=frame_step;
|
||
global_frame_counter++;
|
||
}
|
||
}
|
||
|
||
|
||
void create_mgf_file(char *name)
|
||
{
|
||
mgf=fopen(name,"wb+");
|
||
fwrite(&gh,1,sizeof(gh),mgf);
|
||
total_frames=0;
|
||
prereserve_tracks();
|
||
}
|
||
|
||
|
||
void close_mgf_file()
|
||
{
|
||
fseek(mgf,0,SEEK_SET);
|
||
fill_header(total_frames);
|
||
fwrite(&gh,1,sizeof(gh),mgf);
|
||
fclose(mgf);
|
||
}
|
||
|
||
|
||
void create_mult_and_square()
|
||
{
|
||
int i;
|
||
|
||
puts("Creating tables...");
|
||
for(i=0;i<64;i++) mult_table[i]=(short)((i-32)*(i-32));
|
||
for(i=0;i<4096;i++) square_table[i]=(short)sqrt(i);
|
||
}
|
||
|
||
extern int boldcz;
|
||
|
||
|
||
void script_compress(char *script_name)
|
||
{
|
||
FILE *scr,*snf;
|
||
char s[256],name[256];
|
||
char snd_name[256],*c;
|
||
int i;
|
||
|
||
scr=fopen(script_name,"r");
|
||
strcpy(snd_name,script_name);
|
||
c=strrchr(snd_name,'.');
|
||
if (c==NULL) strcat(snd_name,SND_NAME);
|
||
else strcpy(c,SND_NAME);
|
||
if (scr==NULL)
|
||
{
|
||
printf("Nemohu otev<65><76>t script: %s\n",script_name);
|
||
exit(1);
|
||
}
|
||
snf=fopen(snd_name,"w");
|
||
i=fscanf(scr,"%255s",name);
|
||
if (i!=1)
|
||
{
|
||
printf("Chyba ve script souboru: %s. Prvni mus<75> b<>t jm<6A>no c<>lov<6F>ho souboru.\n",scr);
|
||
exit(1);
|
||
}
|
||
i=fscanf(scr,"%d",&speed);
|
||
create_mgf_file(name);
|
||
while ((i=fgetc(scr))!=EOF && i!='\n');
|
||
i=fgetc(scr);
|
||
initmode32();
|
||
while (i!=EOF)
|
||
{
|
||
while (i<33 && i!=EOF) i=fgetc(scr);
|
||
if (i!='#')
|
||
{
|
||
int j=lowq;
|
||
ungetc(i,scr);
|
||
i=fscanf(scr,"%s %d %d %d %d",s,&j,&min_fr,&max_fr,&colorq);
|
||
strupr(s);
|
||
if (!strcmp(s,"FRAMESTEP")) frame_step=j;
|
||
else
|
||
if (!strcmp(s,"STATIC")) statpic=j;
|
||
else
|
||
if (i>=1)
|
||
{
|
||
lowq=j;
|
||
if (snf!=NULL) fprintf(snf,"%d ",global_frame_counter);
|
||
compress_pcx(s);
|
||
}
|
||
}
|
||
else
|
||
while ((i=fgetc(scr))!=EOF && i!='\n');
|
||
i=fgetc(scr);
|
||
}
|
||
closemode();
|
||
fclose(scr);
|
||
if (snf!=NULL) fclose(snf);
|
||
close_mgf_file();
|
||
}
|
||
|
||
main(int argc,char *argv[])
|
||
{
|
||
puts("\n(C)1997 Komprimator Motion GIF v0.9 by Ondrej Novak");
|
||
if (argc<2)
|
||
{
|
||
puts("Pouziti:");putchar('\n');;
|
||
puts("PCX2MGIF [d:\\path\\]source target.mgf [speed] [lowq] [min_fr] [max_fr] [colorq]");putchar('\n');
|
||
puts("source - Jsou 4 znaky kterymi zacina jmeno kazdeho frame (prvni 0). Takto je\n"
|
||
" mozne vytvorit animaci az o 9999 frames. Pokud je potreba delsi,pak\n"
|
||
" je ctvrty znak zmenen na cislo a je mozne vytvorit animaci dlouhou\n"
|
||
" az 99999 frames. Priklad:\n\n"
|
||
" PCX2MGIF logo logo.mgf \n\n"
|
||
" Tento zapis vytvori animaci logo.mgf, jenz bude slozena z mnoha\n"
|
||
" obrazku ve formatu PCX, jejichz jmena budou znit LOGO0000.PCX az\n"
|
||
" LOGO9999.PCX a dale bude pokracovat LOG10000.PCX az LOG99999.PCX\n\n"
|
||
"speed - Prehravaci rychlost ve snimkach za sekundu (pro 22050kHz)\n"
|
||
" Pokud je dosazeno 0 pak neni do animace vkladana zvukova stopa\n"
|
||
" (Default: 0)\n"
|
||
"lowq - Nejnizsi mozny rozptyl barev sousednich bodu (snizuje kvalitu\n"
|
||
" obrazu) (default: 0)\n"
|
||
"min_fr - Pozadavek na nejmensi velikost frame. Pod touto hranici v \n"
|
||
" nasledujicim frame snizi velikost ztraty (default: 0)");
|
||
cprintf("--- klavesu ---\r");getche();
|
||
puts("max_fr - Pozadavek na nejvetsi velikost frame. Pri prekroceni teto \n"
|
||
" hranice se zvysi ztrata o jeden bod. (default 99999)\n"
|
||
"colorq - Tato hodnota slouzi k predvidani velikosti ztraty. Udava\n"
|
||
" kolik bodu z celkoveho poctu zmen ve frame se menit nebude\n"
|
||
" Program pak vybere ty nejmensi rozdily a ty do rozdilove \n"
|
||
" mapy nezahrne. (default: 0)\n\n"
|
||
"Velikost nejmensiho rozdilu je zobrazen pri komprimaci jako treti cislo\n"
|
||
"Nula udava ze se nezapisuji jen ty body, ktere se nemeni.\n\n"
|
||
"Pozn1: Bezne neni nutne uvadet parametr colorq protoze stupen ztraty se \n"
|
||
"voli podle vysledku predchoziho frame. Je dobre ho uvest pri velkych\n"
|
||
"vykyvech velikosti frame. Tak zhruba pri <20>10KB. Hodnoty parametru se \n"
|
||
"voli od 25000-35000, cim vyssi, tim vyssi stupen ztraty\n\n"
|
||
"Pozn2: Pokud nektere parametry vynechas (treba znakem '-', nebo je na konci\n"
|
||
"neuvedes, dosadi se default hodnoty. Ty jsou zvoleny tak, aby program\n"
|
||
"nevypocitaval ztratu.\n");
|
||
exit(0);
|
||
}
|
||
curfont=(void *)&boldcz;
|
||
if (argc>2)
|
||
{
|
||
switch (argc)
|
||
{
|
||
case 8:sscanf(argv[7],"%d",&colorq);
|
||
case 7:sscanf(argv[6],"%d",&max_fr);
|
||
case 6:sscanf(argv[5],"%d",&min_fr);
|
||
case 5:sscanf(argv[4],"%d",&lowq);
|
||
case 4:sscanf(argv[3],"%d",&speed);
|
||
}
|
||
create_mgf_file(argv[2]);
|
||
initmode32();
|
||
compress_pcx(argv[1]);
|
||
closemode();
|
||
}
|
||
else
|
||
{
|
||
script_compress(argv[1]);
|
||
}
|
||
puts("Zaviram Motion GIF...");
|
||
close_mgf_file();
|
||
}
|