home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 2003 August / VPR0308.ISO / OLS / DCP0002 / dcp0002.lzh / dcp0002 / gifcat.pl < prev   
Perl Script  |  2002-06-10  |  17KB  |  452 lines

  1. ;# ====================================================================
  2. ;#
  3. ;# gifcat.pl: GIFファイル連結ライブラリ Ver1.61
  4. ;#
  5. ;# Copyright (c) 1997,2002 http://tohoho.wakusei.ne.jp/
  6. ;#
  7. ;# 著作権は放棄しませんが、自由に使用・改造・再配布可能です。
  8. ;#
  9. ;# 基本的な使い方
  10. ;#    require "gifcat.pl";
  11. ;#    open(OUT, "> out.gif");
  12. ;#    binmode(OUT);    # MS-DOS や Windows の場合に必要です。
  13. ;#    print OUT &gifcat'gifcat("xx.gif", "yy.gif", "zz.gif");
  14. ;#    close(OUT);
  15. ;#
  16. ;# デバッグ用(GIFの解析出力)
  17. ;#    require "gifcat.pl";
  18. ;#    &gifcat'gifprint("xx.gif", "yy.gif", "zz.gif");
  19. ;#
  20. ;# 制限事項
  21. ;#    アニメGIF同士を連結することはできません。
  22. ;#    アニメGIF対応のブラウザでなければ、最初の画像しか表示されません。
  23. ;#    高さの異なるGIFファイルは連結できません。
  24. ;#
  25. ;# 最新版入手先
  26. ;#    http://tohoho.wakusei.ne.jp/wwwsoft.htm
  27. ;#
  28. ;# 更新履歴:
  29. ;#    1997.05.03 初版。
  30. ;#    1997.05.10 スペルミス修正。
  31. ;#    1997.05.29 サイズの異なるカラーテーブルに対応。
  32. ;#    1997.07.07 エラー発生時にexit()しないように修正。
  33. ;#    1998.05.05 Trailerを持たないGIFファイルを連結できないバグを修正。
  34. ;#    1998.05.05 横幅が256を超えるGIFの出力ができないバグを修正。
  35. ;#    1998.05.05 gifprint()で連結結果を出力しないように修正。
  36. ;#    1998.05.10 連結できないGIF画像があるというバグを修正。
  37. ;#    1998.08.20 Ver1.50 変数の初期化を行うように修正。
  38. ;#    1998.08.20 Ver1.50 透過GIFに対応。
  39. ;#    1999.05.30 Ver1.51 動作には関係ないタイプミス修正。
  40. ;#    1999.10.11 Ver1.52 コメントの修正
  41. ;#    2000.05.21 Ver1.53 幅の異なるGIFの連結に対応
  42. ;#    2000.06.04 Ver1.54 perl -wcのwarning対応
  43. ;#    2000.06.04 Ver1.55 インタレースGIF部のコードミスを修正。
  44. ;#    2000.09.17 Ver1.56 連続呼び出しの際のバグ修正
  45. ;#    2000.11.28 Ver1.57 インタレースGIF部のコードミスを修正。
  46. ;#    2001.09.14 Ver1.58 gifcatを連続で呼び出す際の不具合修正。
  47. ;#    2001.10.04 Ver1.59 同上。
  48. ;#    2001.11.25 Ver1.60 gifprintの不具合修正。
  49. ;#    2002.06.10 Ver1.61 Netscape 6.*で1桁目が表示されない問題に対応。
  50. ;#
  51. ;# ====================================================================
  52.  
  53. package gifcat;
  54.  
  55. $pflag = 0;                    # print flag
  56.  
  57. ;# =====================================================
  58. ;# gifcat'gifprint() - print out GIF diagnostics.
  59. ;# =====================================================
  60. sub gifprint {
  61.     $pflag = 1;
  62.     &gifcat(@_);
  63.     $pflag = 0;
  64. }
  65.  
  66. ;# =====================================================
  67. ;# gifcat'gifcat() - get a concatenated GIF image.
  68. ;# =====================================================
  69. sub gifcat {
  70.     @files = @_;
  71.     $Gif = 0;
  72.     $leftpos = 0;
  73.     $logicalScreenWidth = 0;
  74.     $logicalScreenHeight = 0;
  75.     $useLocalColorTable = 0;
  76.     
  77.     foreach $file (@files) {
  78.         $size = -s $file;
  79.         open(IN, "$file") || return("ERROR");
  80.         binmode(IN);
  81.         read(IN, $buf, $size) || return("ERROR");
  82.         close(IN);
  83.  
  84.         $cnt = 0;
  85.         &GifHeader();
  86.         while (1) {
  87.             $x1 = ord(substr($buf, $cnt, 1));
  88.             if ($x1 == 0x2c) {
  89.                 &ImageBlock();
  90.             } elsif ($x1 == 0x21) {
  91.                 $x2 = ord(substr($buf, $cnt + 1, 1));
  92.                 if ($x2 == 0xf9) {
  93.                     &GraphicControlExtension();
  94.                 } elsif ($x2 == 0xfe) {
  95.                     &CommentExtension();
  96.                 } elsif ($x2 == 0x01) {
  97.                     &PlainTextExtension();
  98.                 } elsif ($x2 == 0xff) {
  99.                     &ApplicationExtension();
  100.                 } else {
  101.                     return("ERROR");
  102.                 }
  103.             } elsif ($x1 == 0x3b) {
  104.                 &Trailer();
  105.                 last;
  106.             } elsif ($cnt == $size) {
  107.                 last;
  108.             } else {
  109.                 return("ERROR");
  110.             }
  111.         }
  112.  
  113.         undef($buf);
  114.         $Gif++;
  115.     }
  116.     if ($pflag == 1) {
  117.         return;
  118.     }
  119.  
  120.     $GifImage = "GIF89a";
  121.     $GifImage .= pack("C", $logicalScreenWidth & 0x00ff);
  122.     $GifImage .= pack("C", ($logicalScreenWidth & 0xff00) >> 8);
  123.     $GifImage .= pack("C", $logicalScreenHeight & 0x00ff);
  124.     $GifImage .= pack("C", ($logicalScreenHeight & 0xff00) >> 8);
  125.     if ($useLocalColorTable) {
  126.         $PackedFields18[0] &= ~0x80;
  127.     }
  128.     $GifImage .= pack("C", $PackedFields18[0]);
  129.     $GifImage .= pack("C", $BackgroundColorIndex);
  130.     $GifImage .= pack("C", $PixelAspectRatio);
  131.     if ($useLocalColorTable == 0) {
  132.         $GifImage .= $globalColorTable[0];
  133.     }
  134.     for ($i = -1; $i < $Gif; $i++) {
  135.         $j = ($i == -1) ? 0 : $i;
  136.         $GifImage .= pack("CCC", 0x21, 0xf9, 0x04);
  137.         $GifImage .= pack("C", $PackedFields23 | $TransparentColorFlag[$j]);
  138.         $GifImage .= pack("CC", 0x00, 0x00);
  139.         $GifImage .= pack("C", $TransparentColorIndex[$j]);
  140.         $GifImage .= pack("C", 0x00);
  141.         $GifImage .= pack("C", 0x2c);
  142.         $n = $leftpos;
  143.         $leftpos += ($i == -1) ? 0 : $ImageWidth[$j];
  144.         $GifImage .= pack("C", $n & 0x00ff);
  145.         $GifImage .= pack("C", ($n & 0xff00) >> 8);
  146.         $GifImage .= pack("CC", 0x00, 0x00);
  147.         $GifImage .= pack("C", $ImageWidth[$j] & 0x00ff);
  148.         $GifImage .= pack("C", ($ImageWidth[$j] & 0xff00) >> 8);
  149.         $GifImage .= pack("C", $ImageHeight & 0x00ff);
  150.         $GifImage .= pack("C", ($ImageHeight & 0xff00) >> 8);
  151.         if ($useLocalColorTable) {
  152.             $PackedFields20[$j] |= 0x80;
  153.             $PackedFields20[$j] &= ~0x07;
  154.             $PackedFields20[$j] |= ($PackedFields18[$j] & 0x07);
  155.             $GifImage .= pack("C", $PackedFields20[$j]);
  156.             $GifImage .= $globalColorTable[$j];
  157.         } else {
  158.             $GifImage .= pack("C", $PackedFields20[$j]);
  159.         }
  160.         $GifImage .= pack("C", $LzwMinimumCodeSize[$j]);
  161.         $GifImage .= $ImageData[$j];
  162.     }
  163.     $GifImage .= pack("C", 0x3b);
  164.  
  165. }
  166.  
  167. ;# =====================================
  168. ;# GifHeader
  169. ;# =====================================
  170. sub GifHeader {
  171.     $Signature = substr($buf, $cnt, 3); $cnt += 3;
  172.     $Version   = substr($buf, $cnt, 3); $cnt += 3;
  173.     $LogicalScreenWidth
  174.             = ord(substr($buf, $cnt + 0, 1))
  175.             + ord(substr($buf, $cnt + 1, 1)) * 256; $cnt += 2;
  176.     $LogicalScreenHeight
  177.             = ord(substr($buf, $cnt + 0, 1))
  178.             + ord(substr($buf, $cnt + 1, 1)) * 256; $cnt += 2;
  179.     $PackedFields18[$Gif]   = ord(substr($buf, $cnt, 1)); $cnt++;
  180.     $GlobalColorTableFlag   = ($PackedFields18[$Gif] & 0x80) >> 7;
  181.     $ColorResolution        = (($PackedFields18[$Gif] & 0x70) >> 4) + 1;
  182.     $SortFlag               = ($PackedFields18[$Gif] & 0x08) >> 3;
  183.     $SizeOfGlobalColorTable = 2 ** (($PackedFields18[$Gif] & 0x07) + 1);
  184.     $BackgroundColorIndex   = ord(substr($buf, $cnt, 1)); $cnt++;
  185.     $PixelAspectRatio       = ord(substr($buf, $cnt, 1)); $cnt++;
  186.     if ($GlobalColorTableFlag) {
  187.         $GlobalColorTable 
  188.             = substr($buf, $cnt, $SizeOfGlobalColorTable * 3);
  189.         $cnt += $SizeOfGlobalColorTable * 3;
  190.     } else {
  191.         $GlobalColorTable = "";
  192.     }
  193.  
  194.     $logicalScreenWidth += $LogicalScreenWidth;
  195.     if ($logicalScreenHeight < $LogicalScreenHeight) {
  196.         $logicalScreenHeight = $LogicalScreenHeight;
  197.     }
  198.     if ($GlobalColorTableFlag) {
  199.         $globalColorTable[$Gif] = $GlobalColorTable;
  200.         if ($Gif > 0) {
  201.             if ($GlobalColorTable ne $globalColorTable[$Gif - 1]) {
  202.                 $useLocalColorTable = 1;
  203.             }
  204.         }
  205.     }
  206.  
  207.     if ($pflag) {
  208.         printf("=====================================\n");
  209.         printf("GifHeader\n");
  210.         printf("=====================================\n");
  211.         printf("Signature:                     %s\n", $Signature);
  212.         printf("Version:                       %s\n", $Version);
  213.         printf("Logical Screen Width:          %d\n", $LogicalScreenWidth);
  214.         printf("Logical Screen Height:         %d\n", $LogicalScreenHeight);
  215.         printf("Global Color Table Flag:       %d\n", $GlobalColorTableFlag);
  216.         printf("Color Resolution:              %d\n", $ColorResolution);
  217.         printf("Sort Flag:                     %d\n", $SortFlag);
  218.         printf("Size of Global Color Table:    %d * 3\n", $SizeOfGlobalColorTable);
  219.         printf("Background Color Index:        %d\n", $BackgroundColorIndex);
  220.         printf("Pixel Aspect Ratio:            %d\n", $PixelAspectRatio);
  221.         printf("Global Color Table:            \n");
  222.         Dump($GlobalColorTable);
  223.     }
  224. }
  225.  
  226. ;# =====================================
  227. ;# Image Block
  228. ;# =====================================
  229. sub ImageBlock {
  230.     $ImageSeparator    = ord(substr($buf, $cnt, 1)); $cnt++;
  231.     $ImageLeftPosition = ord(substr($buf, $cnt, 1))
  232.                + ord(substr($buf, $cnt + 1, 1)) * 256; $cnt += 2;
  233.     $ImageTopPosition  = ord(substr($buf, $cnt, 1))
  234.                + ord(substr($buf, $cnt + 1, 1)) * 256; $cnt += 2;
  235.     $ImageWidth[$Gif]  = ord(substr($buf, $cnt, 1))
  236.                + ord(substr($buf, $cnt + 1, 1)) * 256; $cnt += 2;
  237.     $ImageHeight       = ord(substr($buf, $cnt, 1))
  238.                + ord(substr($buf, $cnt + 1, 1)) * 256; $cnt += 2;
  239.     $PackedFields20[$Gif]  = ord(substr($buf, $cnt, 1)); $cnt++;
  240.     $LocalColorTableFlag   = ($PackedFields20[$Gif] & 0x80) >> 7;
  241.     $InterlaceFlag         = ($PackedFields20[$Gif] & 0x40) >> 6;
  242.     $SortFlag              = ($PackedFields20[$Gif] & 0x20) >> 5;
  243.     $Reserved              = ($PackedFields20[$Gif] & 0x18) >> 3;
  244.     if ($LocalColorTableFlag) {
  245.         $SizeOfLocalColorTable = 2 ** (($PackedFields20[$Gif] & 0x07) + 1);
  246.         $LocalColorTable = substr($buf, $cnt, $SizeOfLocalColorTable);
  247.         $cnt += $SizeOfLocalColorTable * 3;
  248.     } else {
  249.         $SizeOfLocalColorTable = 0;
  250.         $LocalColorTable = "";
  251.     }
  252.     $LzwMinimumCodeSize[$Gif] = ord(substr($buf, $cnt, 1)); $cnt++;
  253.     $ImageData[$Gif] = &DataSubBlock();
  254.  
  255.     if ($pflag) {
  256.         printf("=====================================\n");
  257.         printf("Image Block\n");
  258.         printf("=====================================\n");
  259.         printf("Image Separator:               0x%02x\n", $ImageSeparator);
  260.         printf("Image Left Position:           %d\n", $ImageLeftPosition);
  261.         printf("Image Top Position:            %d\n", $ImageTopPosition);
  262.         printf("Image Width:                   %d\n", $ImageWidth[$Gif]);
  263.         printf("Image Height:                  %d\n", $ImageHeight);
  264.         printf("Local Color Table Flag:        %d\n", $LocalColorTableFlag);
  265.         printf("Interlace Flag:                %d\n", $InterlaceFlag);
  266.         printf("Sort Flag:                     %d\n", $SortFlag);
  267.         printf("Reserved:                      --\n");
  268.         printf("Size of Local Color Table:     %d\n", $SizeOfLocalColorTable);
  269.         printf("Local Color Table:             \n");
  270.         Dump($LocalColorTable);
  271.         printf("LZW Minimum Code Size:         %d\n", $LzwMinimumCodeSize[$Gif]);
  272.         printf("Image Data:                    \n");
  273.         Dump($ImageData[$Gif]);
  274.         printf("Block Terminator:              0x00\n");
  275.     }
  276. }
  277.  
  278. ;# =====================================
  279. ;# Graphic Control Extension
  280. ;# =====================================
  281. sub GraphicControlExtension {
  282.     $ExtensionIntroducer   = ord(substr($buf, $cnt, 1)); $cnt++;
  283.     $GraphicControlLabel   = ord(substr($buf, $cnt, 1)); $cnt++;
  284.     $BlockSize             = ord(substr($buf, $cnt, 1)); $cnt++;
  285.     $PackedFields23        = ord(substr($buf, $cnt, 1)); $cnt++;
  286.     $Reserved              = ($PackedFields23 & 0xe0) >> 5;
  287.     $DisposalMethod        = ($PackedFields23 & 0x1c) >> 5;
  288.     $UserInputFlag         = ($PackedFields23 & 0x02) >> 1;
  289.     $TransparentColorFlag[$Gif]  = $PackedFields23 & 0x01;
  290.     $DelayTime             = ord(substr($buf, $cnt, 1))
  291.                    + ord(substr($buf, $cnt+1, 1)) * 256; $cnt += 2;
  292.     $TransparentColorIndex[$Gif] = ord(substr($buf, $cnt, 1)); $cnt++;
  293.     $BlockTerminator       = ord(substr($buf, $cnt, 1)); $cnt++;
  294.  
  295.     if ($pflag) {
  296.         printf("=====================================\n");
  297.         printf("Graphic Control Extension\n");
  298.         printf("=====================================\n");
  299.         printf("Extension Introducer:          0x%02x\n", $ExtensionIntroducer);
  300.         printf("Graphic Control Label:         0x%02x\n", $GraphicControlLabel);
  301.         printf("Block Size:                    %d\n", $BlockSize);
  302.         printf("Reserved:                      --\n");
  303.         printf("Disposal Method:               %d\n", $DisposalMethod);
  304.         printf("User Input Flag:               %d\n", $UserInputFlag);
  305.         printf("Transparent Color Flag:        %d\n", $TransparentColorFlag[$Gif]);
  306.         printf("Delay Time:                    %d\n", $DelayTime);
  307.         printf("Transparent Color Index:       %d\n", $TransparentColorIndex[$Gif]);
  308.         printf("Block Terminator:              0x00\n");
  309.     }
  310. }
  311.  
  312. ;# =====================================
  313. ;# Comment Extension
  314. ;# =====================================
  315. sub CommentExtension {
  316.     $ExtensionIntroducer   = ord(substr($buf, $cnt, 1)); $cnt++;
  317.     $CommentLabel          = ord(substr($buf, $cnt, 1)); $cnt++;
  318.     &DataSubBlock();
  319.  
  320.     if ($pflag) {
  321.         printf("=====================================\n");
  322.         printf("Comment Extension\n");
  323.         printf("=====================================\n");
  324.         printf("Extension Introducer:          0x%02x\n", $ExtensionIntroducer);
  325.         printf("Comment Label:                 0x%02x\n", $CommentLabel);
  326.         printf("Comment Data:                  ...\n");
  327.         printf("Block Terminator:              0x%02x\n", $BlockTerminator);
  328.     }
  329. }
  330.  
  331. ;# =====================================
  332. ;# Plain Text Extension
  333. ;# =====================================
  334. sub PlainTextExtension {
  335.     $ExtensionIntroducer  = ord(substr($buf, $cnt, 1)); $cnt++;
  336.     $PlainTextLabel       = ord(substr($buf, $cnt, 1)); $cnt++;
  337.     $BlockSize            = ord(substr($buf, $cnt, 1)); $cnt++;
  338.     $TextGridLeftPosition = ord(substr($buf, $cnt, 1))
  339.                   + ord(substr($buf, $cnt + 1, 1)) * 256; $cnt += 2;
  340.     $TextGridTopPosition  = ord(substr($buf, $cnt, 1))
  341.                   + ord(substr($buf, $cnt + 1, 1)) * 256; $cnt += 2;
  342.     $TextGridWidth        = ord(substr($buf, $cnt, 1))
  343.                   + ord(substr($buf, $cnt + 1, 1)) * 256; $cnt += 2;
  344.     $TextGridHeight       = ord(substr($buf, $cnt, 1))
  345.                   + ord(substr($buf, $cnt + 1, 1)) * 256; $cnt += 2;
  346.     $CharacterCellWidth   = ord(substr($buf, $cnt, 1)); $cnt++;
  347.     $CharacterCellHeight  = ord(substr($buf, $cnt, 1)); $cnt++;
  348.     $TextForegroundColorIndex = ord(substr($buf, $cnt, 1)); $cnt++;
  349.     $TextBackgroundColorIndex = ord(substr($buf, $cnt, 1)); $cnt++;
  350.     &DataSubBlock();
  351.  
  352.     if ($pflag) {
  353.         printf("=====================================\n");
  354.         printf("Plain Text Extension\n");
  355.         printf("=====================================\n");
  356.         printf("Extension Introducer:        0x%02x\n", $ExtensionIntroducer);
  357.         printf("Plain Text Label:            0x%02x\n", $PlainTextLabel);
  358.         printf("Block Size:                  0x%02x\n", $BlockSize);
  359.         printf("Text Grid Left Position:     %d\n", $TextGridLeftPosition);
  360.         printf("Text Grid Top Position:      %d\n", $TextGridTopPosition);
  361.         printf("Text Grid Width:             %d\n", $TextGridWidth);
  362.         printf("Text Grid Height:            %d\n", $TextGridHeight);
  363.         printf("Text Foreground Color Index: %d\n", $TextForegroundColorIndex);
  364.         printf("Text Background Color Index: %d\n", $TextBackgroundColorIndex);
  365.         printf("Plain Text Data:             ...\n");
  366.         printf("Block Terminator:            0x00\n");
  367.     }
  368. }
  369.  
  370. ;# =====================================
  371. ;# Application Extension
  372. ;# =====================================
  373. sub ApplicationExtension {
  374.     $ExtensionIntroducer           = ord(substr($buf, $cnt, 1)); $cnt++;
  375.     $ExtentionLabel                = ord(substr($buf, $cnt, 1)); $cnt++;
  376.     $BlockSize                     = ord(substr($buf, $cnt, 1)); $cnt++;
  377.     $ApplicationIdentifire         = substr($buf, $cnt, 8); $cnt += 8;
  378.     $ApplicationAuthenticationCode = substr($buf, $cnt, 3); $cnt += 3;
  379.     &DataSubBlock();
  380.  
  381.     if ($pflag) {
  382.         printf("=====================================\n");
  383.         printf("Application Extension\n");
  384.         printf("=====================================\n");
  385.         printf("Extension Introducer:          0x%02x\n",
  386.             $ExtensionIntroducer);
  387.         printf("Extension Label:               0x%02x\n",
  388.             $PlainTextLabel);
  389.         printf("Block Size:                    0x%02x\n",
  390.             $BlockSize);
  391.         printf("Application Identifire:        ...\n");
  392.         printf("ApplicationAuthenticationCode: ...\n");
  393.         printf("Block Terminator:              0x00\n");
  394.     }
  395. }
  396.  
  397. ;# =====================================
  398. ;# Trailer
  399. ;# =====================================
  400. sub Trailer {
  401.     $cnt++;
  402.  
  403.     if ($pflag) {
  404.         printf("=====================================\n");
  405.         printf("Trailer\n");
  406.         printf("=====================================\n");
  407.         printf("Trailer:                       0x3b\n");
  408.         printf("\n");
  409.     }
  410. }
  411.  
  412. ;# =====================================
  413. ;# Data Sub Block
  414. ;# =====================================
  415. sub DataSubBlock {
  416.     local($n, $from);
  417.     $from = $cnt;
  418.     while ($n = ord(substr($buf, $cnt, 1))) {
  419.         $cnt++;
  420.         $cnt += $n;
  421.     }
  422.     $cnt++;
  423.     return(substr($buf, $from, $cnt - $from));
  424. }
  425.  
  426. ;# =====================================
  427. ;# Memory Dump
  428. ;# =====================================
  429. sub Dump {
  430.     local($buf) = @_;
  431.     my($i);
  432.  
  433.     if (length($buf) == 0) {
  434.         return;
  435.     }
  436.     for ($i = 0; $i < length($buf); $i++) {
  437.         if (($i % 16) == 0) {
  438.             printf("  ");
  439.         }
  440.         printf("%02X ", ord(substr($buf, $i, 1)));
  441.         if (($i % 16) == 15) {
  442.             printf("\n");
  443.         }
  444.     }
  445.     if (($i % 16) != 0) {
  446.         printf("\n");
  447.     }
  448. }
  449.  
  450. 1;
  451.  
  452.