GIFデータ・フォーマットをPHPでコントロール

2016年5月10日

PHP テクノロジー プログラミング

GIFファイルのデータを直接コントロールするために、PHPを使ってデータ操作を行なってみたいと思います。 バイナリデータ・フォーマットにも詳しくなれるので、前回のGIFデータ仕様を元に、カラーパレットをテキストコードに変換して、別の画像データのカラーテーブルと入れ替えてバイナリ状態に戻してみたいと思います。 ※各プログラムの実行は、プログラムのヘッダに書かれているサンプル記述を元に使ってください。 【注意事項】 カラーパレットは同じ深度のデータで行なってください。

GIF画像ファイルをdump

<?php /** * Git Input-Output Controller * date @ 2016/5/1 * write @ yugeta.koji * param @ read-file (*.gif) * sample @ php git_dump.php [**sample.gif] **/ if( $argc < 2 || !is_file($argv[1]) ){ echo "None target-file !".PHP_EOL; exit(); } $readFile = $argv[1]; $readData = file_get_contents($readFile); $gif = new IO_GIF($argv[1]); $data = $gif->getGIF(); print_r($data); echo PHP_EOL; exit(); class IO_GIF{ var $_file; var $_data; var $_byte = 0; var $_bit = 0; var $data = array(); var $localOffset = 0; function __construct($gifFile=null){ //--check if(is_null($gifFile)){return;} //--setData $this->_file = $gifFile; $this->_data = file_get_contents($this->_file); } function getBit() { $value = ord($this->_data{$this->_byte}); $value = 1 & ($value >> (7 - $this->_bit)); $this->_bit++; if (8 <= $this->_bit) { $this->_byte++; $this->_bit = 0; } return $value; } function getBits($count=1) { $value = 0; for ($i=0; $i<$count; $i++) { $value <<= 1; $value |= $this->getBit(); } return $value; } function getByte(){ $data = ord($this->_data{$this->_byte}); $this->_byte++; return $data; } function getBytes($offset=1){ $data = substr($this->_data, $this->_byte, $offset); $this->_byte += strlen($data); //$this->_byte += $offset; return $data; } function getNUM8(){ $offset = 1; $data = ord(substr($this->_data, $this->_byte, $offset)); $this->_byte += $offset; return $data; } function getNUM16LE(){ $offset = 2; $data = unpack("v",substr($this->_data, $this->_byte, $offset)); //$data = ord(substr($this->_data, $this->localOffset, $offset)); $this->_byte += $offset; return $data[1]; } function getNUM32LE(){ //$this->checkByte(); $offset = 4; $data = unpack("V",substr($this->_data, $this->_byte, $offset)); $this->_byte += $offset; return $data[1]; } function getGIF(){ //--Header $this->data["Header"] = $this->getGif_Header(); //block while(true){ $block = array(); //$block["start-byte"] = $this->_byte; $separator = $this->getByte(); //$block["separator"] = dechex($separator); switch ($separator){ //--Extension case 0x21: $extFlg = $this->getByte(); switch ($extFlg): case 0xF9: $block = $this->getGif_Extension_F9($separator,$extFlg); break; case 0xFE: $block = $this->getGif_Extension_FE($separator,$extFlg); break; case 0x01: $block = $this->getGif_Extension_01($separator,$extFlg); break; case 0xFF: $block = $this->getGif_Extension_FF($separator,$extFlg); break; endswitch; if($block){ $this->data["Extension"][] = $block; } break; //--Image case 0x2C: $this->data["ImageBlock"][] = $this->getGif_imageBlock($separator); break; //--Finish case 0x3B: break; } //--block-finish if($separator === 0x3B){ $this->data["Finish"] = $this->_byte; break; } } return $this->data; } function getGif_Header(){ $Header = array(); $Header['Signature'] = $this->getBytes(3);//GIT $Header['Version'] = $this->getBytes(3);//87a,89a $Header['Width'] = $this->getNUM16LE(); $Header['Height'] = $this->getNUM16LE(); $Header['GlobalColorTableFlg'] = $this->getBit(); $Header['ColorResolution'] = $this->getBits(3); $Header['SortFlag'] = $this->getBit(); $Header['SizeOfGlobalColorTable'] = $this->getBits(3); $Header['BackgroundColorIndex'] = $this->getByte(); $Header['PixelAspectRatio'] = $this->getByte(); if($Header["GlobalColorTableFlg"]=="1"){ $Header["GlobalColorTable"] = array(); $cnt = pow(2,$Header["SizeOfGlobalColorTable"]+1); $colorData = array(); for($i=0; $i<$cnt; $i++){ $GlobalColorTable = array( sprintf("%02d",dechex($this->getByte())), sprintf("%02d",dechex($this->getByte())), sprintf("%02d",dechex($this->getByte())), ); $colorData[] = "#".join("",$GlobalColorTable); } $Header["GlobalColorTable"] = join(",",$colorData); } return $Header; } function getGif_Extension_F9($separator, $extFlg){ $block = array(); $block['separator'] = dechex($separator); $block['ExtensionLabel'] = dechex($extFlg); $block['BlockSize'] = $this->getByte(); $block['Reserved'] = $this->getBits(3);//未使用 $block['DisposalMothod'] = $this->getBits(3); $block['UserInputFlag'] = $this->getBit(); $block['TransparentColorFlag'] = $this->getBit();//透過処理を行う場合は1、行わない場合は0。 $block['DelayTime'] = $this->getBytes(2);//表示する際の遅延時間(100分の1秒単位)。 $block['TransparentColorIndex']= $this->getByte();//透過処理する色のインデックス。 $block['BlockTerminator'] = dechex($this->getByte());//ブロック並びの終わりを表わす。0x00 固定値。 return $block; } function getGif_Extension_FE($separator, $extFlg){ $block = array(); $block['separator'] = dechex($separator); $block['ExtensionLabel'] = dechex($extFlg); $block['BlockSize'] = $this->getByte(); $block["CommentData"] = $this->getBytes($blockSize); $block["BlockTerminator"] = dechex($this->getByte()); return $block; } function getGif_Extension_01($separator, $extFlg){ $block = array(); $block['separator'] = dechex($separator); $block['ExtensionLabel'] = dechex($extFlg); $block['BlockSize'] = $this->getByte(); $block['TextGridLeftPosition'] = $this->getBytes(2); $block['TextGridTopPosition'] = $this->getBytes(2); $block['TextGridWidth'] = $this->getBytes(2); $block['TextGridHeight'] = $this->getBytes(2); $block['CharacterCellWidth'] = $this->getByte(); $block['CharacterCellHeight'] = $this->getByte(); $block['TextForegroundColorIndex']= $this->getByte(); $block['TextBackgroundColorIndex']= $this->getByte(); $block["PlainTextData"] = array(); while(true){ $BlockSize2 = $this->getByte(); if($BlockSize2 > 0){ $block["PlainTextData"][] = $this->getBytes($BlockSize2); } else{ $block["BlockTerminator"] = dechex($BlockSize2); break; } } return $block; } function getGif_Extension_FF($separator, $extFlg){ $block = array(); $block['separator'] = dechex($separator); $block['ExtensionLabel'] = dechex($extFlg); $block['BlockSize'] = $this->getByte(); $block["ApplicationIdentifier"] = $this->getBytes(8); $block["ApplicationAuthenticationCode"] = $this->getBytes(3); while(true){ $BlockSize2 = $this->getByte(); if($BlockSize2 > 0){ $block["ApplicationData"][] = $this->getBytes($BlockSize2); } else{ $block["BlockTerminator"] = dechex($BlockSize2); break; } } return $block; } function getGif_imageBlock($separator){ $block = array(); $block["separator"] = dechex($separator);//このブロックがImage Blockであることを示す。0x2c の固定値。 $block['ImageLeftPosition'] = $this->getNUM16LE();//GIF画像全体に対するこのイメージブロックの左端相対位置。 $block['ImageTopPosition'] = $this->getNUM16LE();//GIF画像全体に対するこのイメージブロックの上端さ相対位置。 $block['ImageWidth'] = $this->getNUM16LE();//このイメージブロックの横幅。 $block['ImageHeight'] = $this->getNUM16LE();//このイメージブロックの縦幅。 $block['LocalColorTableFlag'] = $this->getBit();//Local Color Tableが存在する場合は1、存在しない場合は0。 $block['InterlaceFlag'] = $this->getBit();//インタレースする場合は1、しない場合は0。 $block['SortFlag'] = $this->getBit();//Local Color Tableがソートされている場合は1、ソートされていない場合は0。 $block['Reserved'] = $this->getBits(2);//未使用 $block['SizeofLocalColorTable'] = $this->getBits(3);//この値(0~7)に1を足した値をnとして、2のn乗がLocal Color Tableの個数となる。 if($block["LocalColorTableFlag"]==1){ $block['LocalColorTable'] = array(); $cnt = pow(2,$block['SizeofLocalColorTable']+1); $colorData = array(); for($i=0; $i<$cnt; $i++){ $LocalColorTable = array($this->getByte(),$this->getByte(),$this->getByte()); //$block['LocalColorTable'][] = "#".join(",",$LocalColorTable); $colorData[] = "#".join(",",$LocalColorTable); } $block['LocalColorTable'] = join(",",$colorData); } $block['LZWMinimumCodeSide'] = $this->getByte();//LZWコードの最小ビット数。 $block['ImageData'] = array(); $imageData = array(); while(true){ $blocksize = $this->getByte(); if($blocksize !== 0x00){ //$block['ImageData'][] = $this->getBytes($blocksize);//data //$block['ImageData'][] = $blocksize;//size $this->getBytes($blocksize); $imageData[] = $blocksize; } else{ $block['BlockTerminator'] = dechex($blocksize);//ブロック並びの終わりを表わす。0x00 固定値。 break; } } $block['ImageData'] = join(",",$imageData); return $block; } }

GIF画像のパレット情報をファイルに出力

<?php /** * Git Input-Output Controller * date @ 2016/5/1 * write @ yugeta.koji * -- * param @ read-file (*.gif) * -- * sample @ php gif_getPallet.php [%in-gif-file%] * -- * output @ sample.[header/img_*].plt **/ if( $argc < 2 || !is_file($argv[1]) ){ echo "None target-file !".PHP_EOL; exit(); } $readFile = $argv[1]; $readData = file_get_contents($readFile); $gif = new IO_GIF($argv[1]); $data = $gif->getGIF(); echo "finished !"; echo PHP_EOL; exit(0); class IO_GIF{ var $_file; var $_data; var $_byte = 0; var $_bit = 0; // var $signature; // var $version; var $data = array(); var $localOffset = 0; function __construct($gifFile=null){ //--check if(is_null($gifFile)){return;} //--setData $this->_file = $gifFile; $this->_data = file_get_contents($this->_file); } function getBit() { $value = ord($this->_data{$this->_byte}); $value = 1 & ($value >> (7 - $this->_bit)); $this->_bit++; if (8 <= $this->_bit) { $this->_byte++; $this->_bit = 0; } return $value; } function getBits($count=1) { $value = 0; for ($i=0; $i<$count; $i++) { $value <<= 1; $value |= $this->getBit(); } return $value; } function getByte(){ $data = ord($this->_data{$this->_byte}); $this->_byte++; return $data; } function getBytes($offset=1){ //$this->checkByte(); $data = substr($this->_data, $this->_byte, $offset); $this->_byte += strlen($data); return $data; } function getNUM8(){ $offset = 1; $data = ord(substr($this->_data, $this->_byte, $offset)); $this->_byte += $offset; return $data; } function getNUM16LE(){ $offset = 2; $data = unpack("v",substr($this->_data, $this->_byte, $offset)); $this->_byte += $offset; return $data[1]; } function getNUM32LE(){ $offset = 4; $data = unpack("V",substr($this->_data, $this->_byte, $offset)); $this->_byte += $offset; return $data[1]; } function getGIF(){ //--Header $this->data["Header"] = $this->getGif_Header(); //block while(true){ $block = array(); $separator = $this->getByte(); switch ($separator){ //--Extension case 0x21: $extFlg = $this->getByte(); switch ($extFlg): case 0xF9: $block = $this->getGif_Extension_F9($separator,$extFlg); break; case 0xFE: $block = $this->getGif_Extension_FE($separator,$extFlg); break; case 0x01: $block = $this->getGif_Extension_01($separator,$extFlg); break; case 0xFF: $block = $this->getGif_Extension_FF($separator,$extFlg); break; endswitch; if($block){$this->data["Extension"][] = $block;} break; //--Image case 0x2C: $this->data["ImageBlock"][] = $this->getGif_imageBlock($separator); break; //--Finish case 0x3B: break; default: echo "Error: block-type: ".dechex(ord($separator)).PHP_EOL; exit(0); break; } //--block-finish if($separator === 0x3B){ $this->data["Finish"] = $this->_byte; break; } } return $this->data; } function getGif_Header(){ $Header = array(); //$Header["start-byte"] = $this->_byte; $Header['Signature'] = $this->getBytes(3);//GIT $Header['Version'] = $this->getBytes(3);//87a,89a $Header['Width'] = $this->getNUM16LE(); $Header['Height'] = $this->getNUM16LE(); $Header['GlobalColorTableFlg'] = $this->getBit(); $Header['ColorResolution'] = $this->getBits(3); $Header['SortFlag'] = $this->getBit(); $Header['SizeOfGlobalColorTable'] = $this->getBits(3); $Header['BackgroundColorIndex'] = $this->getByte(); $Header['PixelAspectRatio'] = $this->getByte(); if($Header["GlobalColorTableFlg"]=="1"){ $Header["GlobalColorTable"] = array(); $cnt = pow(2,$Header["SizeOfGlobalColorTable"]+1); $colorData = array(); for($i=0; $i<$cnt; $i++){ $GlobalColorTable = array( sprintf("%02x",$this->getByte()), sprintf("%02x",$this->getByte()), sprintf("%02x",$this->getByte()), ); $colorData[] = "#".join("",$GlobalColorTable); } $Header["GlobalColorTable"] = join(",",$colorData); $this->outputPallet("header", $colorData); } return $Header; } function getGif_Extension_F9($separator, $extFlg){ $block = array(); $block['separator'] = dechex($separator); $block['ExtensionLabel'] = dechex($extFlg); $block['BlockSize'] = $this->getByte(); $block['Reserved'] = $this->getBits(3);//未使用 $block['DisposalMothod'] = $this->getBits(3); $block['UserInputFlag'] = $this->getBit(); $block['TransparentColorFlag'] = $this->getBit();//透過処理を行う場合は1、行わない場合は0。 $block['DelayTime'] = $this->getBytes(2);//表示する際の遅延時間(100分の1秒単位)。 $block['TransparentColorIndex']= $this->getByte();//透過処理する色のインデックス。 $block['BlockTerminator'] = dechex($this->getByte());//ブロック並びの終わりを表わす。0x00 固定値。 return $block; } function getGif_Extension_FE($separator, $extFlg){ $block = array(); $block['separator'] = dechex($separator); $block['ExtensionLabel'] = dechex($extFlg); $block['BlockSize'] = $this->getByte(); $block["CommentData"] = $this->getBytes($blockSize); $block["BlockTerminator"] = dechex($this->getByte()); return $block; } function getGif_Extension_01($separator, $extFlg){ $block = array(); $block['separator'] = dechex($separator); $block['ExtensionLabel'] = dechex($extFlg); $block['BlockSize'] = $this->getByte(); $block['TextGridLeftPosition'] = $this->getBytes(2); $block['TextGridTopPosition'] = $this->getBytes(2); $block['TextGridWidth'] = $this->getBytes(2); $block['TextGridHeight'] = $this->getBytes(2); $block['CharacterCellWidth'] = $this->getByte(); $block['CharacterCellHeight'] = $this->getByte(); $block['TextForegroundColorIndex']= $this->getByte(); $block['TextBackgroundColorIndex']= $this->getByte(); $block["PlainTextData"] = array(); while(true){ $BlockSize2 = $this->getByte(); if($BlockSize2 > 0){ $block["PlainTextData"][] = $this->getBytes($BlockSize2); } else{ $block["BlockTerminator"] = dechex($BlockSize2); break; } } return $block; } function getGif_Extension_FF($separator, $extFlg){ $block = array(); $block['separator'] = dechex($separator); $block['ExtensionLabel'] = dechex($extFlg); $block['BlockSize'] = $this->getByte(); $block["ApplicationIdentifier"] = $this->getBytes(8); $block["ApplicationAuthenticationCode"] = $this->getBytes(3); while(true){ $BlockSize2 = $this->getByte(); if($BlockSize2 > 0){ $block["ApplicationData"][] = $this->getBytes($BlockSize2); } else{ $block["BlockTerminator"] = dechex($BlockSize2); break; } } return $block; } function getGif_imageBlock($separator){ $block = array(); $block["separator"] = dechex($separator);//このブロックがImage Blockであることを示す。0x2c の固定値。 $block['ImageLeftPosition'] = $this->getNUM16LE();//GIF画像全体に対するこのイメージブロックの左端相対位置。 $block['ImageTopPosition'] = $this->getNUM16LE();//GIF画像全体に対するこのイメージブロックの上端さ相対位置。 $block['ImageWidth'] = $this->getNUM16LE();//このイメージブロックの横幅。 $block['ImageHeight'] = $this->getNUM16LE();//このイメージブロックの縦幅。 $block['LocalColorTableFlag'] = $this->getBit();//Local Color Tableが存在する場合は1、存在しない場合は0。 $block['InterlaceFlag'] = $this->getBit();//インタレースする場合は1、しない場合は0。 $block['SortFlag'] = $this->getBit();//Local Color Tableがソートされている場合は1、ソートされていない場合は0。 $block['Reserved'] = $this->getBits(2);//未使用 $block['SizeofLocalColorTable'] = $this->getBits(3);//この値(0~7)に1を足した値をnとして、2のn乗がLocal Color Tableの個数となる。 if($block["LocalColorTableFlag"]==1){ $block['LocalColorTable'] = array(); $cnt = pow(2,$block['SizeofLocalColorTable']+1); $colorData = array(); for($i=0; $i<$cnt; $i++){ $LocalColorTable = array( sprintf("%02d",dechex($this->getByte())), sprintf("%02d",dechex($this->getByte())), sprintf("%02d",dechex($this->getByte())) ); $colorData[] = "#".join("",$LocalColorTable); } $block['LocalColorTable'] = join(",",$colorData); $this->outputPallet("img_".count($this->data["ImageBlock"]), $colorData); } $block['LZWMinimumCodeSide'] = $this->getByte();//LZWコードの最小ビット数。 $block['ImageData'] = array(); $imageData = array(); while(true){ $blocksize = $this->getByte(); if($blocksize !== 0x00){ $this->getBytes($blocksize); $imageData[] = $blocksize; } else{ $block['BlockTerminator'] = dechex($blocksize);//ブロック並びの終わりを表わす。0x00 固定値。 break; } } $block['ImageData'] = join(",",$imageData); return $block; } function outputPallet($mode, $data){ $file = preg_replace("/\.gif$/i", ".".$mode.".plt", $this->_file); file_put_contents($file, join("\n",$data)); } }

出力されたテキストデータからバイナリデータを作成

<?php /** * Git Input-Output Controller * date @ 2016/5/1 * write @ yugeta.koji * * --[Summery]-- * change-pallet is header-pallet only * -- * param @ read-file (*.gif) * -- * sample @ php changePallet.php [%in-gif-file%] [%other-gifFile-pallet%] * -- * output @ img/changePallet.gif **/ if( $argc < 2 || !is_file($argv[1]) ){ echo "None target-file !".PHP_EOL; exit(); } $readFile = $argv[1]; $readData = file_get_contents($readFile); $gif = new IO_GIF($argv[1],$argv[2]); $data = $gif->getGIF(); $gif->setGIF(); echo "finished !"; echo PHP_EOL; exit(); class IO_GIF{ var $_file; var $_pallet; var $_data; var $_byte = 0; var $_bit = 0; // var $signature; // var $version; var $data = array(); var $localOffset = 0; //bin-data var $bin_header; var $bin_header_pallet; var $bin_extension = array(); var $bin_image = array(); var $bin_finish; function __construct($gifFile=null,$palletFile){ //--check if(is_null($gifFile)){return;} //--setData $this->_file = $gifFile; $this->_pallet = $palletFile; $this->_data = file_get_contents($this->_file); } function getBins($from,$length){ $data = substr($this->_data, $from, $length); return $data; } function getBit() { $value = ord($this->_data{$this->_byte}); $value = 1 & ($value >> (7 - $this->_bit)); $this->_bit++; if (8 <= $this->_bit) { $this->_byte++; $this->_bit = 0; } return $value; } function getBits($count=1) { $value = 0; for ($i=0; $i<$count; $i++) { $value <<= 1; $value |= $this->getBit(); } return $value; } function getByte(){ //$this->checkByte(); $data = ord($this->_data{$this->_byte}); $this->_byte++; return $data; } function getBytes($offset=1){ //$this->checkByte(); $data = substr($this->_data, $this->_byte, $offset); $this->_byte += strlen($data); //$this->_byte += $offset; return $data; } function getNUM8(){ //$this->checkByte(); $offset = 1; $data = ord(substr($this->_data, $this->_byte, $offset)); $this->_byte += $offset; return $data; } function getNUM16LE(){ //$this->checkByte(); $offset = 2; $data = unpack("v",substr($this->_data, $this->_byte, $offset)); //$data = ord(substr($this->_data, $this->localOffset, $offset)); $this->_byte += $offset; return $data[1]; } function getNUM32LE(){ //$this->checkByte(); $offset = 4; $data = unpack("V",substr($this->_data, $this->_byte, $offset)); $this->_byte += $offset; return $data[1]; } function getGIF(){ //--Header $this->data["Header"] = $this->getGif_Header(); //block while(true){ $block = array(); $separator = $this->getByte(); switch ($separator){ //--Extension case 0x21: $extFlg = $this->getByte(); switch ($extFlg): case 0xF9: $block = $this->getGif_Extension_F9($separator,$extFlg); break; case 0xFE: $block = $this->getGif_Extension_FE($separator,$extFlg); break; case 0x01: $block = $this->getGif_Extension_01($separator,$extFlg); break; case 0xFF: $block = $this->getGif_Extension_FF($separator,$extFlg); break; endswitch; //if($block){ $this->data["Extension"][] = $block; //} break; //--Image case 0x2C: $this->data["ImageBlock"][] = $this->getGif_imageBlock($separator); break; //--Finish case 0x3B: $this->bin_finish = $this->getBins($this->_byte-1,1); break; default: echo "Error: block-type: ".dechex(ord($separator)).PHP_EOL; exit(0); break; } //--block-finish if($separator === 0x3B){ $this->data["Finish"] = $this->_byte; break; } } return $this->data; } function getGif_Header(){ $byte_start = $this->_byte; $Header = array(); //$Header["start-byte"] = $this->_byte; $Header['Signature'] = $this->getBytes(3);//GIT $Header['Version'] = $this->getBytes(3);//87a,89a $Header['Width'] = $this->getNUM16LE(); $Header['Height'] = $this->getNUM16LE(); $Header['GlobalColorTableFlg'] = $this->getBit(); $Header['ColorResolution'] = $this->getBits(3); $Header['SortFlag'] = $this->getBit(); $Header['SizeOfGlobalColorTable'] = $this->getBits(3); $Header['BackgroundColorIndex'] = $this->getByte(); $Header['PixelAspectRatio'] = $this->getByte(); $byte_headEnd = $this->_byte; if($Header["GlobalColorTableFlg"]=="1"){ $Header["GlobalColorTable"] = array(); $cnt = pow(2,$Header["SizeOfGlobalColorTable"]+1); $colorData = array(); for($i=0; $i<$cnt; $i++){ $GlobalColorTable = array( sprintf("%02d",dechex($this->getByte())), sprintf("%02d",dechex($this->getByte())), sprintf("%02d",dechex($this->getByte())), ); //$Header["GlobalColorTable"][] = "#".join("",$GlobalColorTable); $colorData[] = "#".join("",$GlobalColorTable); } $Header["GlobalColorTable"] = join(",",$colorData); //$this->outputPallet("header", $colorData); } $byte_headPalletEnd = $this->_byte; echo $byte_start."(".$byte_headEnd.")".PHP_EOL; $this->bin_header = $this->getBins($byte_start , $byte_headEnd); echo $byte_headEnd."(".($byte_headPalletEnd - $byte_headEnd).")".PHP_EOL; $this->bin_header_pallet = $this->getBins($byte_headEnd , $byte_headPalletEnd - $byte_headEnd); return $Header; } function getGif_Extension_F9($separator, $extFlg){ $byte_start = $this->_byte-2; $block = array(); $block['separator'] = dechex($separator); $block['ExtensionLabel'] = dechex($extFlg); $block['BlockSize'] = $this->getByte(); $block['Reserved'] = $this->getBits(3);//未使用 $block['DisposalMothod'] = $this->getBits(3); $block['UserInputFlag'] = $this->getBit(); $block['TransparentColorFlag'] = $this->getBit();//透過処理を行う場合は1、行わない場合は0。 $block['DelayTime'] = $this->getBytes(2);//表示する際の遅延時間(100分の1秒単位)。 $block['TransparentColorIndex']= $this->getByte();//透過処理する色のインデックス。 $block['BlockTerminator'] = dechex($this->getByte());//ブロック並びの終わりを表わす。0x00 固定値。 $byte_end = $this->_byte; echo $byte_start."(".($byte_end-$byte_start).")".PHP_EOL; $this->bin_extension[] = $this->getBins($byte_start,$byte_end-$byte_start); return $block; } function getGif_Extension_FE($separator, $extFlg){ $byte_start = $this->_byte-2; $block = array(); $block['separator'] = dechex($separator); $block['ExtensionLabel'] = dechex($extFlg); $block['BlockSize'] = $this->getByte(); $block["CommentData"] = $this->getBytes($blockSize); $block["BlockTerminator"] = dechex($this->getByte()); $byte_end = $this->_byte; echo $byte_start."(".($byte_end-$byte_start).")".PHP_EOL; $this->bin_extension[] = $this->getBins($byte_start,$byte_end-$byte_start); return $block; } function getGif_Extension_01($separator, $extFlg){ $byte_start = $this->_byte-2; $block = array(); $block['separator'] = dechex($separator); $block['ExtensionLabel'] = dechex($extFlg); $block['BlockSize'] = $this->getByte(); $block['TextGridLeftPosition'] = $this->getBytes(2); $block['TextGridTopPosition'] = $this->getBytes(2); $block['TextGridWidth'] = $this->getBytes(2); $block['TextGridHeight'] = $this->getBytes(2); $block['CharacterCellWidth'] = $this->getByte(); $block['CharacterCellHeight'] = $this->getByte(); $block['TextForegroundColorIndex']= $this->getByte(); $block['TextBackgroundColorIndex']= $this->getByte(); $block["PlainTextData"] = array(); while(true){ $BlockSize2 = $this->getByte(); if($BlockSize2 > 0){ $block["PlainTextData"][] = $this->getBytes($BlockSize2); } else{ $block["BlockTerminator"] = dechex($BlockSize2); break; } } $byte_end = $this->_byte; echo $byte_start."(".($byte_end-$byte_start).")".PHP_EOL; $this->bin_extension[] = $this->getBins($byte_start,$byte_end-$byte_start); return $block; } function getGif_Extension_FF($separator, $extFlg){ $byte_start = $this->_byte-2; $block = array(); $block['separator'] = dechex($separator); $block['ExtensionLabel'] = dechex($extFlg); $block['BlockSize'] = $this->getByte(); $block["ApplicationIdentifier"] = $this->getBytes(8); $block["ApplicationAuthenticationCode"] = $this->getBytes(3); while(true){ $BlockSize2 = $this->getByte(); if($BlockSize2 > 0){ $block["ApplicationData"][] = $this->getBytes($BlockSize2); } else{ $block["BlockTerminator"] = dechex($BlockSize2); break; } } $byte_end = $this->_byte; echo $byte_start."(".($byte_end-$byte_start).")".PHP_EOL; $this->bin_extension[] = $this->getBins($byte_start,$byte_end-$byte_start); return $block; } function getGif_imageBlock($separator){ $byte_start = $this->_byte-1; $block = array(); $block["separator"] = dechex($separator);//このブロックがImage Blockであることを示す。0x2c の固定値。 $block['ImageLeftPosition'] = $this->getNUM16LE();//GIF画像全体に対するこのイメージブロックの左端相対位置。 $block['ImageTopPosition'] = $this->getNUM16LE();//GIF画像全体に対するこのイメージブロックの上端さ相対位置。 $block['ImageWidth'] = $this->getNUM16LE();//このイメージブロックの横幅。 $block['ImageHeight'] = $this->getNUM16LE();//このイメージブロックの縦幅。 $block['LocalColorTableFlag'] = $this->getBit();//Local Color Tableが存在する場合は1、存在しない場合は0。 $block['InterlaceFlag'] = $this->getBit();//インタレースする場合は1、しない場合は0。 $block['SortFlag'] = $this->getBit();//Local Color Tableがソートされている場合は1、ソートされていない場合は0。 $block['Reserved'] = $this->getBits(2);//未使用 $block['SizeofLocalColorTable'] = $this->getBits(3);//この値(0~7)に1を足した値をnとして、2のn乗がLocal Color Tableの個数となる。 if($block["LocalColorTableFlag"]==1){ $block['LocalColorTable'] = array(); $cnt = pow(2,$block['SizeofLocalColorTable']+1); $colorData = array(); for($i=0; $i<$cnt; $i++){ $LocalColorTable = array( sprintf("%02d",dechex($this->getByte())), sprintf("%02d",dechex($this->getByte())), sprintf("%02d",dechex($this->getByte())) ); //$block['LocalColorTable'][] = "#".join(",",$LocalColorTable); $colorData[] = "#".join("",$LocalColorTable); } $block['LocalColorTable'] = join(",",$colorData); //$this->outputPallet("img_".count($this->data["ImageBlock"]), $colorData); } $block['LZWMinimumCodeSide'] = $this->getByte();//LZWコードの最小ビット数。 $block['ImageData'] = array(); $imageData = array(); while(true){ $blocksize = $this->getByte(); if($blocksize !== 0x00){ //$block['ImageData'][] = $this->getBytes($blocksize);//data //$block['ImageData'][] = $blocksize;//size $this->getBytes($blocksize); $imageData[] = $blocksize; } else{ $block['BlockTerminator'] = dechex($blocksize);//ブロック並びの終わりを表わす。0x00 固定値。 break; } } $block['ImageData'] = join(",",$imageData); //$block["BlockTerminator"] = dechex($this->getByte()); $byte_end = $this->_byte; echo $byte_start."(".($byte_end-$byte_start).")".PHP_EOL; $this->bin_image[] = $this->getBins($byte_start,$byte_end-$byte_start); return $block; } function outputPallet($mode, $data){ $file = preg_replace("/\.gif$/i", ".".$mode.".plt", $this->_file); file_put_contents($file, join("\n",$data)); } function setGIF(){ //--chenge-header-pallet $palletData = explode("\n",file_get_contents($this->_pallet)); $newPalletData=""; for($i=0;$i<count($palletData);$i++){ if(!$palletData[$i]){continue;} $newPalletData.= chr(hexdec(substr($palletData[$i],1,2))); $newPalletData.= chr(hexdec(substr($palletData[$i],3,2))); $newPalletData.= chr(hexdec(substr($palletData[$i],5,2))); } $this->bin_header_pallet = $newPalletData; //-- $data = $this->bin_header; $data.= $this->bin_header_pallet; for($i=0;$i<count($this->bin_extension);$i++){ $data.= $this->bin_extension[$i]; } for($i=0;$i<count($this->bin_image);$i++){ $data.= $this->bin_image[$i]; } $data.= $this->bin_finish; //-- $outFile = "img/changePallet.gif"; file_put_contents($outFile,$data); $outData = file_get_contents($outFile); } }

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。