This article describes how to generate GIF animation in PHP. For more information, see
The code is as follows:
The code is as follows:
Class GifMerge {
Var $ ver = '1. 1 ';
Var $ dly = 50;
Var $ mod = 'c _ file ';
Var $ first = true;
Var $ use_loop = false;
Var $ transparent = false;
Var $ use_global_in = false;
Var $ x = 0;
Var $ y = 0;
Var $ ch = 0;
Var $ fin = 0;
Var $ fout = '';
Var $ loop = 0;
Var $ delay = 0;
Var $ width = 0;
Var $ height = 0;
Var $ trans1 = 255;
Var $ trans2 = 255;
Var $ trans3 = 255;
Var $ disposal = 2;
Var $ out_color_table_size = 0;
Var $ local_color_table_flag = 0;
Var $ global_color_table_size = 0;
Var $ out_color_table_sizecode = 0;
Var $ global_color_table_sizecode = 0;
Var $ gif = array (0x47, 0x49, 0x46 );
Var $ buffer = array ();
Var $ local_in = array ();
Var $ global_in = array ();
Var $ global_out = array ();
Var $ logical_screen_descriptor = array ();
Function GifMerge ($ images, $ t1, $ t2, $ t3, $ loop, $ dl, $ xpos, $ ypos, $ model ){
If ($ model ){
$ This-> mod = $ model;
}
If ($ loop>-1 ){
$ This-> loop = floor ($ loop-1 );
$ This-> use_loop = true;
}
If ($ t1>-1 & $ t2>-1 & $ t3>-1 ){
$ This-> trans1 = $ t1;
$ This-> trans2 = $ t2;
$ This-> trans3 = $ t3;
$ This-> transparent = true;
}
For ($ I = 0; $ I <count ($ images); $ I ++ ){
$ Dl [$ I]? $ This-> delay = $ dl [$ I]: $ this-> delay = $ this-> dly;
$ Xpos [$ I]? $ This-> x = $ xpos [$ I]: $ this-> x = 0;
$ Ypos [$ I]? $ This-> y = $ ypos [$ I]: $ this-> y = 0;
$ This-> start_gifmerge_process ($ images [$ I]);
}
$ This-> fout. = "/x3b ";
}
Function start_gifmerge_process ($ fp ){
If ($ this-> mod = 'c _ file '){
If (! $ This-> fin = fopen ($ fp, 'RB ')){
Return;
}
} Elseif ($ this-> mod = 'c _ MEMORY '){
$ This-> ch = 0;
$ This-> fin = $ fp;
}
$ This-> getbytes (6 );
If (! $ This-> arrcmp ($ this-> buffer, $ this-> gif, 3 )){
Return;
}
$ This-> getbytes (7 );
If ($ this-> first) $ this-> logical_screen_descriptor = $ this-> buffer;
$ This-> global_color_table_sizecode = $ this-> buffer [4] & 0x07;
$ This-> global_color_table_size = 2 <$ this-> global_color_table_sizecode;
If ($ this-> buffer [4] & 0x80 ){
$ This-> getbytes (3 * $ this-> global_color_table_size ));
For ($ I = 0; $ I <(3 * $ this-> global_color_table_size); $ I ++ ){
$ This-> global_in [$ I] = $ this-> buffer [$ I];
}
If ($ this-> out_color_table_size = 0 ){
$ This-> out_color_table_size = $ this-> global_color_table_size;
$ Out_color_table_sizecode = $ this-> global_color_table_sizecode;
$ This-> global_out = $ this-> global_in;
}
If ($ this-> global_color_table_size! = $ This-> out_color_table_size | $ this-> arrcmp ($ this-> global_out, $ this-> global_in, (3 * $ this-> global_color_table_size ))){
$ This-> use_global_in = true;
}
}
For ($ loop = true; $ loop ;){
$ This-> getbytes (1 );
Switch ($ this-> buffer [0]) {
Case 0x21:
$ This-> read_extension ();
Break;
Case 0x2c:
$ This-> read_image_descriptor ();
Break;
Case 0x3b:
$ Loop = false;
Break;
Default:
$ Loop = false;
}
}
If ($ this-> mod = 'c _ file '){
Fclose ($ this-> fin );
}
}
Function read_image_descriptor (){
$ This-> getbytes (9 );
$ Head = $ this-> buffer;
$ This-> local_color_table_flag = ($ this-> buffer [8] & 0x80 )? True: false;
If ($ this-> local_color_table_flag ){
$ Sizecode = $ this-> buffer [8] & 0x07;
$ Size = 2 <$ sizecode;
$ This-> getbytes (3 * $ size );
For ($ I = 0; $ I <(3 * $ size); $ I ++ ){
$ This-> local_in [$ I] = $ this-> buffer [$ I];
}
If ($ this-> out_color_table_size = 0 ){
$ This-> out_color_table_size = $ size;
$ Out_color_table_sizecode = $ sizecode;
For ($ I = 0; $ I <(3 * $ size); $ I ++)
{
$ This-> global_out [$ I] = $ this-> local_in [$ I];
}
}
}
If ($ this-> first ){
$ This-> first = false;
$ This-> fout. = "/x47/x49/x46/x38/x39/x61 ";
If ($ this-> width & $ this-> height ){
$ This-> logical_screen_descriptor [0] = $ this-> width & 0xFF;
$ This-> logical_screen_descriptor [1] = ($ this-> width & 0xFF00)> 8;
$ This-> logical_screen_descriptor [2] = $ this-> height & 0xFF;
$ This-> logical_screen_descriptor [3] = ($ this-> height & 0xFF00)> 8;
}
$ This-> logical_screen_descriptor [4] | = 0x80;
$ This-> logical_screen_descriptor [5] & = 0xF0;
$ This-> logical_screen_descriptor [6] | = $ this-> out_color_table_sizecode;
$ This-> putbytes ($ this-> logical_screen_descriptor, 7 );
$ This-> putbytes ($ this-> global_out, ($ this-> out_color_table_size * 3 ));
If ($ this-> use_loop ){
$ Ns [0] = 0x21;
$ Ns [1] = 0xFF;
$ Ns [2] = 0x0B;
$ Ns [3] = 0x4e;
$ Ns [4] = 0x45;
$ Ns [5] = 0x54;
$ Ns [6] = 0x53;
$ Ns [7] = 0x43;
$ Ns [8] = 0x41;
$ Ns [9] = 0x50;
$ Ns [10] = 0x45;
$ Ns [11] = 0x32;
$ Ns [12] = 0x2e;
$ Ns [13] = 0x30;
$ Ns [14] = 0x03;
$ Ns [15] = 0x01;
$ Ns [16] = $ this-> loop & 255;
$ Ns [17] = $ this-> loop> 8;
$ Ns [18] = 0x00;
$ This-> putbytes ($ ns, 19 );
}
}
If ($ this-> use_global_in ){
$ Outtable = $ this-> global_in;
$ Outsize = $ this-> global_color_table_size;
$ Outsizecode = $ this-> global_color_table_sizecode;
} Else {
$ Outtable = $ this-> global_out;
$ Outsize = $ this-> out_color_table_size;
}
If ($ this-> local_color_table_flag ){
If ($ size = $ this-> out_color_table_size &&! $ This-> arrcmp ($ this-> local_in, $ this-> global_out, $ size )){
$ Outtable = $ global_out;
$ Outsize = $ this-> out_color_table_size;
} Else {
$ Outtable = $ this-> local_in;
$ Outsize = $ size;
$ Outsizecode = $ sizecode;
}
}
$ Use_trans = false;
If ($ this-> transparent ){
For ($ I = 0; $ I <$ outsize; $ I ++ ){
If ($ outtable [3 * $ I] ==$ this-> trans1 & $ outtable [3 * $ I + 1] ==$ this-> trans2 & $ outtable [3 * $ I + 2] ==$ this-> trans3) {
Break;
}
}
If ($ I <$ outsize ){
$ Transindex = $ I;
$ Use_trans = true;
}
}
If ($ this-> delay | $ use_trans ){
$ This-> buffer [0] = 0x21;
$ This-> buffer [1] = 0xf9;
$ This-> buffer [2] = 0x04;
$ This-> buffer [3] = ($ this-> disposal <2) + ($ use_trans? 1: 0 );
$ This-> buffer [4] = $ this-> delay & 0xff;
$ This-> buffer [5] = ($ this-> delay & 0xff00)> 8;
$ This-> buffer [6] = $ use_trans? $ Transindex: 0;
$ This-> buffer [7] = 0x00;
$ This-> putbytes ($ this-> buffer, 8 );
}
$ This-> buffer [0] = 0x2c;
$ This-> putbytes ($ this-> buffer, 1 );
$ Head [0] = $ this-> x & 0xff;
$ Head [1] = ($ this-> x & 0xff00)> 8;
$ Head [2] = $ this-> y & 0xff;
$ Head [3] = ($ this-> y & 0xff00)> 8;
$ Head [8] & = 0x40;
If ($ outtable! = $ This-> global_out ){
$ Head [8] | = 0x80;
$ Head [8] | = $ outsizecode;
}
$ This-> putbytes ($ head, 9 );
If ($ outtable! = $ This-> global_out ){
$ This-> putbytes ($ outtable, (3 * $ outsize ));
}
$ This-> getbytes (1 );
$ This-> putbytes ($ this-> buffer, 1 );
For (;;){
$ This-> getbytes (1 );
$ This-> putbytes ($ this-> buffer, 1 );
If ($ u = $ this-> buffer [0]) = 0 ){
Break;
}
$ This-> getbytes ($ u );
$ This-> putbytes ($ this-> buffer, $ u );
}
}
Function read_extension (){
$ This-> getbytes (1 );
Switch ($ this-> buffer [0]) {
Case 0xf9:
$ This-> getbytes (6 );
Break;
Case 0xfe:
For (;;){
$ This-> getbytes (1 );
If ($ u = $ this-> buffer [0]) = 0 ){
Break;
}
$ This-> getbytes ($ u );
}
Break;
Case 0x01:
$ This-> getbytes (13 );
For (;;){
$ This-> getbytes (0 );
If ($ u = $ this-> buffer [0]) = 0 ){
Break;
}
$ This-> getbytes ($ u );
}
Break;
Case 0xff:
$ This-> getbytes (9 );
$ This-> getbytes (3 );
For (;;){
$ This-> getbytes (1 );
If (! $ This-> buffer [0]) {
Break;
}
$ This-> getbytes ($ this-> buffer [0]);
}
Break;
Default:
For (;;){
$ This-> getbytes (1 );
If (! $ This-> buffer [0]) {
Break;
}
$ This-> getbytes ($ this-> buffer [0]);
}
}
}
Function arrcmp ($ B, $ s, $ l ){
For ($ I = 0; $ I <$ l; $ I ++ ){
If ($ s {$ I }! = $ B {$ I }){
Return false;
}
}
Return true;
}
Function getbytes ($ l ){
For ($ I = 0; $ I <$ l; $ I ++ ){
If ($ this-> mod = 'c _ file '){
$ Bin = unpack ('C * ', fread ($ this-> fin, 1 ));
$ This-> buffer [$ I] = $ bin [1];
} Elseif ($ this-> mod = 'c _ MEMORY '){
$ Bin = unpack ('C * ', substr ($ this-> fin, $ this-> ch, 1 ));
$ This-> buffer [$ I] = $ bin [1];
$ This-> ch ++;
}
}
Return $ this-> buffer;
}
Function putbytes ($ s, $ l ){
For ($ I = 0; $ I <$ l; $ I ++ ){
$ This-> fout. = pack ('C * ', $ s [$ I]);
}
}
Function getAnimation (){
Return $ this-> fout;
}
}
?>