File Coverage

blib/lib/Image/Dot.pm
Criterion Covered Total %
statement 27 37 72.9
branch 0 2 0.0
condition n/a
subroutine 8 9 88.8
pod 0 5 0.0
total 35 53 66.0


line stmt bran cond sub pod time code
1             #
2             # $Id: Dot.pm,v 1.2 2002/10/17 12:14:35 rgiersig Exp $
3             #
4              
5             package Image::Dot;
6              
7 1     1   16596 use strict;
  1         3  
  1         52  
8 1     1   6 use warnings;
  1         2  
  1         38  
9 1     1   6 use Exporter;
  1         7  
  1         62  
10              
11             =head1 NAME
12              
13             Image::Dot - create 1x1 pixel image files (pure-perl)
14              
15             =head1 VERSION
16              
17             1.1
18              
19             =head1 SYNOPSIS
20              
21             use Image::Dot;
22              
23             $reddot = dot_PNG_RGB(255, 0, 0);
24             $bluetransparentdot = dot_PNG_RGBA(0, 0, 255, 32);
25             $cleardot = dot_PNG_RGBA(0, 0, 0, 0);
26             $cleargifdot = dot_GIF_transparent;
27              
28             =head1 DESCRIPTION
29              
30             This package provides 1x1 pixel PNG images of a certain RGB color
31             (also with transparency) without relying on any external modules like
32             GD, libpng or Compress::Zlib. These pixel dots can be useful in a
33             pure-perl HTTP server to be able to create colored dots on-the-fly,
34             e.g. for formatting or drawing purposes.
35              
36             Additionally, a transparent GIF dot is provided (PNG transparency
37             support in some common browsers is bad to non-existent).
38              
39             =head1 COPYRIGHT / AUTHOR / LICENSE
40              
41             (c) 2002 Roland Giersig ERGIERSIG@cpan.orgE
42              
43             This module can be used under the same license as perl itself.
44              
45             =cut
46              
47 1     1   6 use vars qw(@ISA @EXPORT $VERSION);
  1         2  
  1         1266  
48             @ISA = qw(Exporter);
49             @EXPORT = qw(dot_PNG_RGB dot_PNG_RGBA dot_GIF_transparent);
50             $VERSION = "1.1";
51              
52             # a simple implementation of the adler32 checksum algorithm
53             # expects the numeric byte values already presplit/unpacked in @_; not
54             # a very fast implementation, as you can delay the modulo for 5552 bytes.
55              
56             sub MyAdler32 {
57 2     2 0 3 my ($sum1, $sum2) = (1, 0);
58 2         40 foreach my $d (@_) {
59 9         13 $sum1 = ($sum1 + $d) % 65521;
60 9         12 $sum2 = ($sum2 + $sum1) % 65521;
61             }
62 2         12 return ($sum1 + ($sum2 << 16));
63             }
64              
65             #
66             # here comes the CRC32 for the compression part
67             #
68             my @crc_table = ( 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
69             0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832,
70             0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD,
71             0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148,
72             0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
73             0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F,
74             0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E,
75             0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD,
76             0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
77             0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC,
78             0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
79             0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2,
80             0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
81             0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589,
82             0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934,
83             0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97,
84             0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
85             0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6,
86             0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49,
87             0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074,
88             0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
89             0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73,
90             0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
91             0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409,
92             0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
93             0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320,
94             0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF,
95             0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E,
96             0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
97             0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D,
98             0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0,
99             0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43,
100             0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
101             0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA,
102             0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
103             0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0,
104             0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
105             0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7,
106             0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226,
107             0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785,
108             0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
109             0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4,
110             0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B,
111             0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA,
112             0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
113             0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661,
114             0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
115             0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F,
116             0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
117             0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E,
118             0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1,
119             0x5A05DF1B, 0x2D02EF8D, );
120              
121             #
122             # the polynome calculation that produced the above table
123             #
124             sub make_crc_table {
125 0     0 0 0 my ($c, $n, $k);
126 0         0 for ($n = 0; $n < 256; $n++) {
127 0         0 $c = $n;
128 0         0 for ($k = 0; $k < 8; $k++) {
129 0 0       0 if ($c & 1) {
130 0         0 $c = 0xEDB88320 ^ ($c >> 1);
131             } else {
132 0         0 $c = $c >> 1;
133             }
134             }
135 0         0 $crc_table[$n] = $c;
136             }
137 0         0 print STDERR "my \@crc_table = (", (map {sprintf "0x%08X, ", $_} @crc_table), ");\n";
  0         0  
138             }
139              
140             #
141             # expects the values already presplit/unpacked in @_
142             #
143             sub MyPNGcrc {
144             # make_crc_table if not @crc_table;
145 2     2 0 4 my $crc = 0xFFFFFFFF;
146 2         3 foreach my $d (@_) {
147 39         58 $crc = $crc_table[($crc ^ $d) & 0xff] ^ ($crc >> 8);
148             }
149 2         9 return $crc ^ 0xffffffff;
150             }
151              
152             ######################################################################
153             # For those who peek here to find out how we can do this without using
154             # Compress::Zlib: no, I haven't implemented Zlib in pure perl.
155             # Instead I'm using a trick: the deflate algorithm can be instructed
156             # to not compress at all. So I'm using a pre-calculated deflate
157             # template and just patch in the uncompressed RGB bytes; I do have to
158             # re-calculate the checksums, but that's not too hard...
159              
160             sub dot_PNG_RGB ($$$) {
161 1     1 0 69 my ($r, $g, $b) = @_;
162 1         7 my $idat = pack("C11N",
163             0x78, 0x01, 0x01, 0x04, 0x00, 0xFB, 0xFF, 0, $r, $g, $b,
164             MyAdler32(0, $r, $g, $b));
165             return (# ID + IHDR
166 1         8 pack ("H*",
167             "89504e470d0a1a0a".
168             "0000000d4948445200000001000000010802000000907753de").
169             # IDAT
170             pack ("H*", "0000000f49444154").
171             $idat.
172             pack("N", MyPNGcrc(unpack("C*", "IDAT".$idat))).
173             # IEND
174             pack ("H*", "0000000049454e44ae426082")
175             );
176             }
177              
178             ######################################################################
179             sub dot_PNG_RGBA ($$$$) {
180 1     1 0 35 my ($r, $g, $b, $a) = @_;
181 1         3 my $idat = pack("C12N",
182             0x78, 0x01, 0x01, 0x05, 0x00, 0xFA, 0xFF, 0, $r, $g, $b, $a,
183             MyAdler32(0, $r, $g, $b, $a));
184             return (# ID + IHDR
185 1         6 pack ("H*",
186             "89504e470d0a1a0a".
187             "0000000d49484452000000010000000108060000001f15c489").
188             # IDAT
189             pack ("H*", "0000001049444154").
190             $idat.
191             pack("N", MyPNGcrc(unpack("C*", "IDAT".$idat))).
192             # IEND
193             pack ("H*", "0000000049454e44ae426082")
194             );
195             }
196              
197             ######################################################################
198             # this is just a constant
199             sub dot_GIF_transparent () {
200             "\x47\x49\x46\x38\x39\x61\x01\x00\x01\x00\x80\xff\x00\xc0\xc0\xc0".
201             "\x00\x00\x00\x21\xf9\x04\x01\x00\x00\x00\x00\x2c\x00\x00\x00\x00".
202             "\x01\x00\x01\x00\x40\x02\x02\x44\x01\x00\x3b"
203             }
204              
205             1;
206              
207             __END__