OSDN Git Service

Add VC++ Project files for PuTTY DLL without exported functions.
[ffftp/ffftp.git] / putty / ICONS / ICON.PL
diff --git a/putty/ICONS/ICON.PL b/putty/ICONS/ICON.PL
new file mode 100644 (file)
index 0000000..aefd3fa
--- /dev/null
@@ -0,0 +1,270 @@
+#!/usr/bin/perl \r
+\r
+# Take a collection of input image files and convert them into a\r
+# multi-resolution Windows .ICO icon file.\r
+#\r
+# The input images can be treated as having four different colour\r
+# depths:\r
+#\r
+#  - 24-bit true colour\r
+#  - 8-bit with custom palette\r
+#  - 4-bit using the Windows 16-colour palette (see comment below\r
+#    for details)\r
+#  - 1-bit using black and white only.\r
+#\r
+# The images can be supplied in any input format acceptable to\r
+# ImageMagick, but their actual colour usage must already be\r
+# appropriate for the specified mode; this script will not do any\r
+# substantive conversion. So if an image intended to be used in 4-\r
+# or 1-bit mode contains any colour not in the appropriate fixed\r
+# palette, that's a fatal error; if an image to be used in 8-bit\r
+# mode contains more than 256 distinct colours, that's also a fatal\r
+# error.\r
+#\r
+# Command-line syntax is:\r
+#\r
+#   icon.pl -depth imagefile [imagefile...] [-depth imagefile [imagefile...]]\r
+#\r
+# where `-depth' is one of `-24', `-8', `-4' or `-1', and tells the\r
+# script how to treat all the image files given after that option\r
+# until the next depth option. For example, you might execute\r
+#\r
+#   icon.pl -24 48x48x24.png 32x32x24.png -8 32x32x8.png -1 monochrome.png\r
+#\r
+# to build an icon file containing two differently sized 24-bit\r
+# images, one 8-bit image and one black and white image.\r
+#\r
+# Windows .ICO files support a 1-bit alpha channel on all these\r
+# image types. That is, any pixel can be either opaque or fully\r
+# transparent, but not partially transparent. The alpha channel is\r
+# separate from the main image data, meaning that `transparent' is\r
+# not required to take up a palette entry. (So an 8-bit image can\r
+# have 256 distinct _opaque_ colours, plus transparent pixels as\r
+# well.) If the input images have alpha channels, they will be used\r
+# to determine which pixels of the icon are transparent, by simple\r
+# quantisation half way up (e.g. in a PNG image with an 8-bit alpha\r
+# channel, alpha values of 00-7F will be mapped to transparent\r
+# pixels, and 80-FF will become opaque).\r
+\r
+# The Windows 16-colour palette consists of:\r
+#  - the eight corners of the colour cube (000000, 0000FF, 00FF00,\r
+#    00FFFF, FF0000, FF00FF, FFFF00, FFFFFF)\r
+#  - dim versions of the seven non-black corners, at 128/255 of the\r
+#    brightness (000080, 008000, 008080, 800000, 800080, 808000,\r
+#    808080)\r
+#  - light grey at 192/255 of full brightness (C0C0C0).\r
+%win16pal = (\r
+    "\x00\x00\x00\x00" => 0,\r
+    "\x00\x00\x80\x00" => 1,\r
+    "\x00\x80\x00\x00" => 2,\r
+    "\x00\x80\x80\x00" => 3,\r
+    "\x80\x00\x00\x00" => 4,\r
+    "\x80\x00\x80\x00" => 5,\r
+    "\x80\x80\x00\x00" => 6,\r
+    "\xC0\xC0\xC0\x00" => 7,\r
+    "\x80\x80\x80\x00" => 8,\r
+    "\x00\x00\xFF\x00" => 9,\r
+    "\x00\xFF\x00\x00" => 10,\r
+    "\x00\xFF\xFF\x00" => 11,\r
+    "\xFF\x00\x00\x00" => 12,\r
+    "\xFF\x00\xFF\x00" => 13,\r
+    "\xFF\xFF\x00\x00" => 14,\r
+    "\xFF\xFF\xFF\x00" => 15,\r
+);\r
+@win16pal = sort { $win16pal{$a} <=> $win16pal{$b} } keys %win16pal;\r
+\r
+# The black and white palette consists of black (000000) and white\r
+# (FFFFFF), obviously.\r
+%win2pal = (\r
+    "\x00\x00\x00\x00" => 0,\r
+    "\xFF\xFF\xFF\x00" => 1,\r
+);\r
+@win2pal = sort { $win16pal{$a} <=> $win2pal{$b} } keys %win2pal;\r
+\r
+@hdr = ();\r
+@dat = ();\r
+\r
+$depth = undef;\r
+foreach $_ (@ARGV) {\r
+    if (/^-(24|8|4|1)$/) {\r
+       $depth = $1;\r
+    } elsif (defined $depth) {\r
+       &readicon($_, $depth);\r
+    } else {\r
+       $usage = 1;\r
+    }\r
+}\r
+if ($usage || length @hdr == 0) {\r
+    print "usage: icon.pl ( -24 | -8 | -4 | -1 ) image [image...]\n";\r
+    print "             [ ( -24 | -8 | -4 | -1 ) image [image...] ...]\n";\r
+    exit 0;\r
+}\r
+\r
+# Now write out the output icon file.\r
+print pack "vvv", 0, 1, scalar @hdr; # file-level header\r
+$filepos = 6 + 16 * scalar @hdr;\r
+for ($i = 0; $i < scalar @hdr; $i++) {\r
+    print $hdr[$i];\r
+    print pack "V", $filepos;\r
+    $filepos += length($dat[$i]);\r
+}\r
+for ($i = 0; $i < scalar @hdr; $i++) {\r
+    print $dat[$i];\r
+}\r
+\r
+sub readicon {\r
+    my $filename = shift @_;\r
+    my $depth = shift @_;\r
+    my $pix;\r
+    my $i;\r
+    my %pal;\r
+\r
+    # Determine the icon's width and height.\r
+    my $w = `identify -format %w $filename`;\r
+    my $h = `identify -format %h $filename`;\r
+\r
+    # Read the file in as RGBA data. We flip vertically at this\r
+    # point, to avoid having to do it ourselves (.BMP and hence\r
+    # .ICO are bottom-up).\r
+    my $data = [];\r
+    open IDATA, "convert -flip -depth 8 $filename rgba:- |";\r
+    push @$data, $rgb while (read IDATA,$rgb,4,0) == 4;\r
+    close IDATA;\r
+    # Check we have the right amount of data.\r
+    $xl = $w * $h;\r
+    $al = scalar @$data;\r
+    die "wrong amount of image data ($al, expected $xl) from $filename\n"\r
+      unless $al == $xl;\r
+\r
+    # Build the alpha channel now, so we can exclude transparent\r
+    # pixels from the palette analysis. We replace transparent\r
+    # pixels with undef in the data array.\r
+    #\r
+    # We quantise the alpha channel half way up, so that alpha of\r
+    # 0x80 or more is taken to be fully opaque and 0x7F or less is\r
+    # fully transparent. Nasty, but the best we can do without\r
+    # dithering (and don't even suggest we do that!).\r
+    my $x;\r
+    my $y;\r
+    my $alpha = "";\r
+\r
+    for ($y = 0; $y < $h; $y++) {\r
+       my $currbyte = 0, $currbits = 0;\r
+       for ($x = 0; $x < (($w+31)|31)-31; $x++) {\r
+           $pix = ($x < $w ? $data->[$y*$w+$x] : "\x00\x00\x00\xFF");\r
+           my @rgba = unpack "CCCC", $pix;\r
+           $currbyte <<= 1;\r
+           $currbits++;\r
+           if ($rgba[3] < 0x80) {\r
+               if ($x < $w) {\r
+                   $data->[$y*$w+$x] = undef;\r
+               }\r
+               $currbyte |= 1; # MS has the alpha channel inverted :-)\r
+           } else {\r
+               # Might as well flip RGBA into BGR0 while we're here.\r
+               if ($x < $w) {\r
+                   $data->[$y*$w+$x] = pack "CCCC",\r
+                     $rgba[2], $rgba[1], $rgba[0], 0;\r
+               }\r
+           }\r
+           if ($currbits >= 8) {\r
+               $alpha .= pack "C", $currbyte;\r
+               $currbits -= 8;\r
+           }\r
+       }\r
+    }\r
+\r
+    # For an 8-bit image, check we have at most 256 distinct\r
+    # colours, and build the palette.\r
+    %pal = ();\r
+    if ($depth == 8) {\r
+       my $palindex = 0;\r
+       foreach $pix (@$data) {\r
+           next unless defined $pix;\r
+           $pal{$pix} = $palindex++ unless defined $pal{$pix};\r
+       }\r
+       die "too many colours in 8-bit image $filename\n" unless $palindex <= 256;\r
+    } elsif ($depth == 4) {\r
+       %pal = %win16pal;\r
+    } elsif ($depth == 1) {\r
+       %pal = %win2pal;\r
+    }\r
+\r
+    my $raster = "";\r
+    if ($depth < 24) {\r
+       # For a non-24-bit image, flatten the image into one palette\r
+       # index per pixel.\r
+       $pad = 32 / $depth; # number of pixels to pad scanline to 4-byte align\r
+       $pmask = $pad-1;\r
+       for ($y = 0; $y < $h; $y++) {\r
+           my $currbyte = 0, $currbits = 0;\r
+           for ($x = 0; $x < (($w+$pmask)|$pmask)-$pmask; $x++) {\r
+               $currbyte <<= $depth;\r
+               $currbits += $depth;\r
+               if ($x < $w && defined ($pix = $data->[$y*$w+$x])) {\r
+                   if (!defined $pal{$pix}) {\r
+                        $pixhex = sprintf "%02x%02x%02x", unpack "CCC", $pix;\r
+                       die "illegal colour value $pixhex at pixel ($x,$y) in $filename\n";\r
+                   }\r
+                   $currbyte |= $pal{$pix};\r
+               }\r
+               if ($currbits >= 8) {\r
+                   $raster .= pack "C", $currbyte;\r
+                   $currbits -= 8;\r
+               }\r
+           }\r
+       }\r
+    } else {\r
+       # For a 24-bit image, reverse the order of the R,G,B values\r
+       # and stick a padding zero on the end.\r
+       #\r
+       # (In this loop we don't need to bother padding the\r
+       # scanline out to a multiple of four bytes, because every\r
+       # pixel takes four whole bytes anyway.)\r
+       for ($i = 0; $i < scalar @$data; $i++) {\r
+           if (defined $data->[$i]) {\r
+               $raster .= $data->[$i];\r
+           } else {\r
+               $raster .= "\x00\x00\x00\x00";\r
+           }\r
+       }\r
+       $depth = 32; # and adjust this\r
+    }\r
+\r
+    # Prepare the icon data. First the header...\r
+    my $data = pack "VVVvvVVVVVV",\r
+      40, # size of bitmap info header\r
+      $w, # icon width\r
+      $h*2, # icon height (x2 to indicate the subsequent alpha channel)\r
+      1, # 1 plane (common to all MS image formats)\r
+      $depth, # bits per pixel\r
+      0, # no compression\r
+      length $raster, # image size\r
+      0, 0, 0, 0; # resolution, colours used, colours important (ignored)\r
+    # ... then the palette ...\r
+    if ($depth <= 8) {\r
+       my $ncols = (1 << $depth);\r
+       my $palette = "\x00\x00\x00\x00" x $ncols;\r
+       foreach $i (keys %pal) {\r
+           substr($palette, $pal{$i}*4, 4) = $i;\r
+       }\r
+       $data .= $palette;\r
+    }\r
+    # ... the raster data we already had ready ...\r
+    $data .= $raster;\r
+    # ... and the alpha channel we already had as well.\r
+    $data .= $alpha;\r
+\r
+    # Prepare the header which will represent this image in the\r
+    # icon file.\r
+    my $header = pack "CCCCvvV",\r
+      $w, $h, # width and height (this time the real height)\r
+      1 << $depth, # number of colours, if less than 256\r
+      0, # reserved\r
+      1, # planes\r
+      $depth, # bits per pixel\r
+      length $data; # size of real icon data\r
+\r
+    push @hdr, $header;\r
+    push @dat, $data;\r
+}\r