File: | blib/lib/Image/Caa.pm |
Coverage: | 74.0% |
line | stmt | bran | cond | sub | time | code |
---|---|---|---|---|---|---|
1 | package Image::Caa; | |||||
2 | ||||||
3 | 3 3 3 | 16 5 24 | use strict; | |||
4 | 3 3 3 | 22 8 16 | use warnings; | |||
5 | ||||||
6 | our $VERSION = '1.01'; | |||||
7 | ||||||
8 | # dark colors | |||||
9 | 3 3 3 | 30 8 22 | use constant CAA_COLOR_BLACK => 0; | |||
10 | 3 3 3 | 22 6 16 | use constant CAA_COLOR_RED => 1; | |||
11 | 3 3 3 | 20 5 15 | use constant CAA_COLOR_GREEN => 2; | |||
12 | 3 3 3 | 18 6 16 | use constant CAA_COLOR_YELLOW => 3; | |||
13 | 3 3 3 | 19 6 14 | use constant CAA_COLOR_BLUE => 4; | |||
14 | 3 3 3 | 19 7 14 | use constant CAA_COLOR_MAGENTA => 5; | |||
15 | 3 3 3 | 19 6 17 | use constant CAA_COLOR_CYAN => 6; | |||
16 | 3 3 3 | 17 8 14 | use constant CAA_COLOR_LIGHTGRAY => 7; | |||
17 | ||||||
18 | # light colors | |||||
19 | 3 3 3 | 18 6 15 | use constant CAA_COLOR_DARKGRAY => 8; | |||
20 | 3 3 3 | 19 7 25 | use constant CAA_COLOR_LIGHTRED => 9; | |||
21 | 3 3 3 | 17 7 24 | use constant CAA_COLOR_LIGHTGREEN => 10; | |||
22 | 3 3 3 | 18 11 14 | use constant CAA_COLOR_BROWN => 11; | |||
23 | 3 3 3 | 24 5 20 | use constant CAA_COLOR_LIGHTBLUE => 12; | |||
24 | 3 3 3 | 17 7 14 | use constant CAA_COLOR_LIGHTMAGENTA => 13; | |||
25 | 3 3 3 | 18 6 132 | use constant CAA_COLOR_LIGHTCYAN => 14; | |||
26 | 3 3 3 | 19 7 14 | use constant CAA_COLOR_WHITE => 15; | |||
27 | ||||||
28 | 3 3 3 | 18 7 18 | use constant CAA_LOOKUP_VAL => 32; | |||
29 | 3 3 3 | 20 6 15 | use constant CAA_LOOKUP_SAT => 32; | |||
30 | 3 3 3 | 19 7 14 | use constant CAA_LOOKUP_HUE => 16; | |||
31 | ||||||
32 | 3 3 3 | 24 42 51 | use constant CAA_HSV_XRATIO => 6; | |||
33 | 3 3 3 | 19 6 16 | use constant CAA_HSV_YRATIO => 3; | |||
34 | 3 3 3 | 18 6 15 | use constant CAA_HSV_HRATIO => 3; | |||
35 | ||||||
36 | ||||||
37 | sub new { | |||||
38 | 15 | 189 | my $class = shift; | |||
39 | 15 | 67 | my %opts = @_; | |||
40 | 15 | 47 | my $opts = \%opts; | |||
41 | ||||||
42 | 15 | 65 | my $self = bless {}, $class; | |||
43 | ||||||
44 | 15 | 137 | $self->{driver} = $self->load_submodule($opts->{driver} || 'DriverANSI', $opts); | |||
45 | 14 | 92 | $self->{dither} = $self->load_submodule($opts->{dither} || 'DitherNone', $opts); | |||
46 | 14 | 144 | $self->{solid_background} = $opts->{black_bg} ? 0 : 1; | |||
47 | ||||||
48 | 14 | 190 | $self->{hsv_palette} = [ | |||
49 | # weight, hue, saturation, value | |||||
50 | 4, 0x0, 0x0, 0x0, # black | |||||
51 | 5, 0x0, 0x0, 0x5ff, # 30% | |||||
52 | 5, 0x0, 0x0, 0x9ff, # 70% | |||||
53 | 4, 0x0, 0x0, 0xfff, # white | |||||
54 | 3, 0x1000, 0xfff, 0x5ff, # dark yellow | |||||
55 | 2, 0x1000, 0xfff, 0xfff, # light yellow | |||||
56 | 3, 0x0, 0xfff, 0x5ff, # dark red | |||||
57 | 2, 0x0, 0xfff, 0xfff # light red | |||||
58 | ]; | |||||
59 | ||||||
60 | 14 | 51 | $self->init(); | |||
61 | ||||||
62 | 14 | 107 | return $self; | |||
63 | } | |||||
64 | ||||||
65 | ||||||
66 | sub init { | |||||
67 | 14 | 42 | my ($self) = @_; | |||
68 | ||||||
69 | 14 | 48 | $self->{hsv_distances} = []; | |||
70 | ||||||
71 | for (my $v = 0; $v < CAA_LOOKUP_VAL; $v++){ | |||||
72 | for (my $s = 0; $s < CAA_LOOKUP_SAT; $s++){ | |||||
73 | for (my $h = 0; $h < CAA_LOOKUP_HUE; $h++){ | |||||
74 | ||||||
75 | 229376 | 609410 | my $val = 0xfff * $v / (CAA_LOOKUP_VAL - 1); | |||
76 | 229376 | 587258 | my $sat = 0xfff * $s / (CAA_LOOKUP_SAT - 1); | |||
77 | 229376 | 585285 | my $hue = 0xfff * $h / (CAA_LOOKUP_HUE - 1); | |||
78 | ||||||
79 | # Initialise distances to the distance between pure black HSV | |||||
80 | # coordinates and our white colour (3) | |||||
81 | ||||||
82 | 229376 | 414220 | my $outbg = 3; | |||
83 | 229376 | 409642 | my $outfg = 3; | |||
84 | 229376 | 756508 | my $distbg = $self->HSV_DISTANCE(0, 0, 0, 3); | |||
85 | 229376 | 754860 | my $distfg = $self->HSV_DISTANCE(0, 0, 0, 3); | |||
86 | ||||||
87 | ||||||
88 | # Calculate distances to eight major colour values and store the | |||||
89 | # two nearest points in our lookup table. | |||||
90 | ||||||
91 | for (my $i = 0; $i < 8; $i++){ | |||||
92 | ||||||
93 | 1835008 | 5898019 | my $dist = $self->HSV_DISTANCE($hue, $sat, $val, $i); | |||
94 | ||||||
95 | 1835008 | 9237130 | if ($dist <= $distbg){ | |||
96 | ||||||
97 | 651252 | 1206659 | $outfg = $outbg; | |||
98 | 651252 | 1194489 | $distfg = $distbg; | |||
99 | 651252 | 1169454 | $outbg = $i; | |||
100 | 651252 | 3034117 | $distbg = $dist; | |||
101 | ||||||
102 | }elsif ($dist <= $distfg){ | |||||
103 | ||||||
104 | 286846 | 530220 | $outfg = $i; | |||
105 | 286846 | 1336740 | $distfg = $dist; | |||
106 | } | |||||
107 | 229376 | 434254 | } | |||
108 | ||||||
109 | 229376 | 1840579 | $self->{hsv_distances}->[$v]->[$s]->[$h] = ($outfg << 4) | $outbg; | |||
110 | 14336 | 26359 | } | |||
111 | 448 | 853 | } | |||
112 | 14 | 29 | } | |||
113 | } | |||||
114 | ||||||
115 | sub init_instance { | |||||
116 | 5 | 13 | my ($self) = @_; | |||
117 | ||||||
118 | 5 | 25 | $self->{lookup_colors} = []; | |||
119 | ||||||
120 | # These ones are constant | |||||
121 | 5 | 22 | $self->{lookup_colors}->[0] = CAA_COLOR_BLACK; | |||
122 | 5 | 16 | $self->{lookup_colors}->[1] = CAA_COLOR_DARKGRAY; | |||
123 | 5 | 16 | $self->{lookup_colors}->[2] = CAA_COLOR_LIGHTGRAY; | |||
124 | 5 | 16 | $self->{lookup_colors}->[3] = CAA_COLOR_WHITE; | |||
125 | ||||||
126 | # These ones will be overwritten | |||||
127 | 5 | 17 | $self->{lookup_colors}->[4] = CAA_COLOR_MAGENTA; | |||
128 | 5 | 19 | $self->{lookup_colors}->[5] = CAA_COLOR_LIGHTMAGENTA; | |||
129 | 5 | 17 | $self->{lookup_colors}->[6] = CAA_COLOR_RED; | |||
130 | 5 | 21 | $self->{lookup_colors}->[7] = CAA_COLOR_LIGHTRED; | |||
131 | } | |||||
132 | ||||||
133 | # | |||||
134 | # Draw a bitmap on the screen. | |||||
135 | # | |||||
136 | # Draw a bitmap at the given coordinates. The bitmap can be of any size and | |||||
137 | # will be stretched to the text area. | |||||
138 | # | |||||
139 | # x1 X coordinate of the upper-left corner of the drawing area. | |||||
140 | # y1 Y coordinate of the upper-left corner of the drawing area. | |||||
141 | # x2 X coordinate of the lower-right corner of the drawing area. | |||||
142 | # y2 Y coordinate of the lower-right corner of the drawing area. | |||||
143 | # image Image Magick picture object to be drawn. | |||||
144 | # | |||||
145 | ||||||
146 | sub draw_bitmap{ | |||||
147 | 5 | 76 | my ($self, $x1, $y1, $x2, $y2, $image) = @_; | |||
148 | ||||||
149 | 5 | 12 | my $w = $x2-$x1; | |||
150 | 5 | 12 | my $h = $y2-$y1; | |||
151 | ||||||
152 | 5 | 13 | my $iw = 0; | |||
153 | 5 | 11 | my $ih = 0; | |||
154 | 5 | 10 | my $h_pad = 0; | |||
155 | 5 | 12 | my $v_pad = 0; | |||
156 | ||||||
157 | 5 | 18 | if (defined $image){ | |||
158 | ||||||
159 | # resize to fit in the box | |||||
160 | ||||||
161 | 0 | 0 | $image->Scale('100%,67%'); | |||
162 | 0 | 0 | my $x = $image->Resize(geometry => ($w-2).'x'.($h-2)); | |||
163 | 0 | 0 | warn "$x" if "$x"; | |||
164 | ||||||
165 | 0 | 0 | ($iw, $ih) = $image->Get('columns', 'rows'); | |||
166 | ||||||
167 | 0 | 0 | $h_pad = 1 + int(($w - $iw) / 2); | |||
168 | 0 | 0 | $v_pad = 1 + int(($h - $ih) / 2); | |||
169 | } | |||||
170 | ||||||
171 | 5 | 16 | $self->init_instance(); | |||
172 | 5 | 29 | $self->{driver}->init(); | |||
173 | ||||||
174 | ||||||
175 | # Only used when background is black | |||||
176 | ||||||
177 | 5 | 19 | my $white_colors = [ | |||
178 | CAA_COLOR_BLACK, | |||||
179 | CAA_COLOR_DARKGRAY, | |||||
180 | CAA_COLOR_LIGHTGRAY, | |||||
181 | CAA_COLOR_WHITE, | |||||
182 | ]; | |||||
183 | ||||||
184 | 5 | 24 | my $light_colors = [ | |||
185 | CAA_COLOR_LIGHTMAGENTA, | |||||
186 | CAA_COLOR_LIGHTRED, | |||||
187 | CAA_COLOR_YELLOW, | |||||
188 | CAA_COLOR_LIGHTGREEN, | |||||
189 | CAA_COLOR_LIGHTCYAN, | |||||
190 | CAA_COLOR_LIGHTBLUE, | |||||
191 | CAA_COLOR_LIGHTMAGENTA, | |||||
192 | ]; | |||||
193 | ||||||
194 | 5 | 23 | my $dark_colors = [ | |||
195 | CAA_COLOR_MAGENTA, | |||||
196 | CAA_COLOR_RED, | |||||
197 | CAA_COLOR_BROWN, | |||||
198 | CAA_COLOR_GREEN, | |||||
199 | CAA_COLOR_CYAN, | |||||
200 | CAA_COLOR_BLUE, | |||||
201 | CAA_COLOR_MAGENTA, | |||||
202 | ]; | |||||
203 | ||||||
204 | ||||||
205 | # FIXME: choose better characters! | |||||
206 | ||||||
207 | 5 | 14 | my $density_chars = | |||
208 | " ". | |||||
209 | ". ". | |||||
210 | ".. ". | |||||
211 | "....". | |||||
212 | "::::". | |||||
213 | ";=;=". | |||||
214 | "tftf". | |||||
215 | '%$%$'. | |||||
216 | "&KSZ". | |||||
217 | "WXGM". | |||||
218 | '@@@@'. | |||||
219 | "8888". | |||||
220 | "####". | |||||
221 | "????"; | |||||
222 | ||||||
223 | 5 | 136 | my @density_chars = split //, $density_chars; | |||
224 | 5 | 27 | $density_chars = \@density_chars; | |||
225 | ||||||
226 | 5 5 | 9 17 | my $density_chars_size = scalar(@{$density_chars}) - 1; | |||
227 | ||||||
228 | 5 | 12 | my $x = 0; | |||
229 | 5 | 10 | my $y = 0; | |||
230 | 5 | 10 | my $deltax = 0; | |||
231 | 5 | 9 | my $deltay = 0; | |||
232 | ||||||
233 | ||||||
234 | 5 | 8 | my $tmp; | |||
235 | 5 0 0 0 | 17 0 0 0 | if ($x1 > $x2){ $tmp = $x2; $x2 = $x1; $x1 = $tmp; } | |||
236 | 5 0 0 0 | 19 0 0 0 | if ($y1 > $y2){ $tmp = $y2; $y2 = $y1; $y1 = $tmp; } | |||
237 | ||||||
238 | 5 | 12 | $deltax = $x2 - $x1 + 1; | |||
239 | 5 | 12 | $deltay = $y2 - $y1 + 1; | |||
240 | ||||||
241 | ||||||
242 | for ($y = $y1 > 0 ? $y1 : 0; $y <= $y2; $y++){ | |||||
243 | 10 | 49 | $self->{dither}->init($y); | |||
244 | for ($x = $x1 > 0 ? $x1 : 0; $x <= $x2; $x++){ | |||||
245 | ||||||
246 | 20 | 86 | my $ch = 0; | |||
247 | 20 | 35 | my $r = 0; | |||
248 | 20 | 33 | my $g = 0; | |||
249 | 20 | 37 | my $b = 0; | |||
250 | 20 | 37 | my $a = 0; | |||
251 | 20 | 35 | my $hue = 0; | |||
252 | 20 | 35 | my $sat = 0; | |||
253 | 20 | 35 | my $val = 0; | |||
254 | 20 | 35 | my $fromx = 0; | |||
255 | 20 | 34 | my $fromy = 0; | |||
256 | 20 | 36 | my $tox = 0; | |||
257 | 20 | 34 | my $toy = 0; | |||
258 | 20 | 33 | my $myx = 0; | |||
259 | 20 | 38 | my $myy = 0; | |||
260 | 20 | 34 | my $dots = 0; | |||
261 | 20 | 37 | my $outfg = 0; | |||
262 | 20 | 34 | my $outbg = 0; | |||
263 | 20 | 40 | my $outch = chr 0; | |||
264 | ||||||
265 | # First get RGB | |||||
266 | ||||||
267 | 20 | 50 | if (defined $image){ | |||
268 | ||||||
269 | 0 | 0 | my $px = ($x - $x1) - $h_pad; | |||
270 | 0 | 0 | my $py = ($y - $y1) - $v_pad; | |||
271 | ||||||
272 | 0 | 0 | my $to_l = $px < 0; | |||
273 | 0 | 0 | my $to_t = $py < 0; | |||
274 | 0 | 0 | my $to_r = $px >= $iw; | |||
275 | 0 | 0 | my $to_b = $py >= $ih; | |||
276 | ||||||
277 | 0 | 0 | if ($to_l || $to_t || $to_r || $to_b){ | |||
278 | ||||||
279 | 0 | 0 | $r = 0xfff; | |||
280 | 0 | 0 | $g = 0xfff; | |||
281 | 0 | 0 | $b = 0xfff; | |||
282 | ||||||
283 | }else{ | |||||
284 | ||||||
285 | 0 | 0 | ($r, $g, $b, $a) = split /,/, $image->Get("pixel[$px,$py]"); | |||
286 | ||||||
287 | 0 | 0 | $r >>= 4; | |||
288 | 0 | 0 | $g >>= 4; | |||
289 | 0 | 0 | $b >>= 4; | |||
290 | } | |||||
291 | ||||||
292 | #if (bitmap->has_alpha && a < 0x800) continue; | |||||
293 | ||||||
294 | # Now get HSV from RGB | |||||
295 | 0 | 0 | ($hue, $sat, $val) = $self->rgb2hsv_default($r, $g, $b); | |||
296 | ||||||
297 | }else{ | |||||
298 | ||||||
299 | 20 | 74 | $hue = int(0x5fff * (($x-$x1) / ($x2-$x1))); | |||
300 | 20 | 64 | $sat = int(0xfff * (($y-$y1) / ($y2-$y1))); | |||
301 | 20 | 59 | $val = int(0xfff * (($y-$y1) / ($y2-$y1))); | |||
302 | 20 | 42 | $val = 0x777; | |||
303 | } | |||||
304 | ||||||
305 | ||||||
306 | # The hard work: calculate foreground and background colours, | |||||
307 | # as well as the most appropriate character to output. | |||||
308 | ||||||
309 | 20 | 119 | if ($self->{solid_background}){ | |||
310 | ||||||
311 | 20 | 39 | my $point = chr 0; | |||
312 | 20 | 42 | my $distfg = 0; | |||
313 | 20 | 40 | my $distbg = 0; | |||
314 | ||||||
315 | 20 | 93 | $self->{lookup_colors}->[4] = $dark_colors->[1 + $hue / 0x1000]; | |||
316 | 20 | 90 | $self->{lookup_colors}->[5] = $light_colors->[1 + $hue / 0x1000]; | |||
317 | 20 | 133 | $self->{lookup_colors}->[6] = $dark_colors->[$hue / 0x1000]; | |||
318 | 20 | 126 | $self->{lookup_colors}->[7] = $light_colors->[$hue / 0x1000]; | |||
319 | ||||||
320 | 20 | 84 | my $idx_v = ($val + $self->{dither}->get() * (0x1000 / CAA_LOOKUP_VAL) / 0x100) * (CAA_LOOKUP_VAL - 1) / 0x1000; | |||
321 | 20 | 78 | my $idx_s = ($sat + $self->{dither}->get() * (0x1000 / CAA_LOOKUP_SAT) / 0x100) * (CAA_LOOKUP_SAT - 1) / 0x1000; | |||
322 | 20 | 80 | my $idx_h = (($hue & 0xfff) + $self->{dither}->get() * (0x1000 / CAA_LOOKUP_HUE) / 0x100) * (CAA_LOOKUP_HUE - 1) / 0x1000; | |||
323 | ||||||
324 | 20 | 94 | $point = $self->{hsv_distances}->[$idx_v]->[$idx_s]->[$idx_h]; | |||
325 | ||||||
326 | 20 | 85 | $distfg = $self->HSV_DISTANCE($hue % 0xfff, $sat, $val, ($point >> 4)); | |||
327 | 20 | 137 | $distbg = $self->HSV_DISTANCE($hue % 0xfff, $sat, $val, ($point & 0xf)); | |||
328 | ||||||
329 | # Sanity check due to the lack of precision in hsv_distances, | |||||
330 | # and distbg can be > distfg because of dithering fuzziness. | |||||
331 | ||||||
332 | 20 0 | 65 0 | if ($distbg > $distfg){ $distbg = $distfg; } | |||
333 | ||||||
334 | 20 | 67 | $outfg = $self->{lookup_colors}->[($point >> 4)]; | |||
335 | 20 | 72 | $outbg = $self->{lookup_colors}->[($point & 0xf)]; | |||
336 | ||||||
337 | 20 | 70 | $ch = $distbg * 2 * ($density_chars_size - 1) / ($distbg + $distfg); | |||
338 | 20 | 84 | $ch = 4 * $ch + $self->{dither}->get() / 0x40; | |||
339 | ||||||
340 | 20 20 | 32 72 | if ($ch >= scalar(@{$density_chars})){ | |||
341 | ||||||
342 | 15 15 | 20 42 | $ch = scalar(@{$density_chars}) - 1; | |||
343 | } | |||||
344 | ||||||
345 | 20 | 56 | $outch = $density_chars->[$ch]; | |||
346 | ||||||
347 | }else{ | |||||
348 | ||||||
349 | 0 | 0 | $outbg = CAA_COLOR_BLACK; | |||
350 | ||||||
351 | 0 | 0 | if ($sat < 0x200 + $self->{dither}->get() * 0x8){ | |||
352 | ||||||
353 | 0 | 0 | $outfg = $white_colors->[1 + ($val * 2 + $self->{dither}->get() * 0x10) / 0x1000]; | |||
354 | ||||||
355 | }elsif ($val > 0x800 + $self->{dither}->get() * 0x4){ | |||||
356 | ||||||
357 | 0 | 0 | $outfg = $light_colors->[($hue + $self->{dither}->get() * 0x10) / 0x1000]; | |||
358 | ||||||
359 | }else{ | |||||
360 | 0 | 0 | $outfg = $dark_colors->[($hue + $self->{dither}->get() * 0x10) / 0x1000]; | |||
361 | } | |||||
362 | ||||||
363 | 0 | 0 | $ch = ($val + 0x2 * $self->{dither}->get()) * 10 / 0x1000; | |||
364 | 0 | 0 | $ch = 4 * $ch + $self->{dither}->get() / 0x40; | |||
365 | ||||||
366 | 0 | 0 | $outch = $density_chars->[$ch]; | |||
367 | } | |||||
368 | ||||||
369 | # Now output the character | |||||
370 | 20 | 85 | $self->{driver}->set_color($outfg, $outbg); | |||
371 | 20 | 86 | $self->{driver}->putchar($x, $y, $outch); | |||
372 | ||||||
373 | 20 | 72 | $self->{dither}->increment(); | |||
374 | 10 | 37 | } | |||
375 | 5 | 19 | } | |||
376 | ||||||
377 | 5 | 25 | $self->{driver}->fini(); | |||
378 | } | |||||
379 | ||||||
380 | sub rgb2hsv_default { | |||||
381 | 0 | 0 | my ($self, $r, $g, $b) = @_; | |||
382 | ||||||
383 | 0 | 0 | my ($hue, $sat, $val) = (0, 0, 0); | |||
384 | ||||||
385 | 0 | 0 | my $min = $r; | |||
386 | 0 | 0 | my $max = $r; | |||
387 | ||||||
388 | 0 | 0 | $min = $g if $min > $g; | |||
389 | 0 | 0 | $max = $g if $max < $g; | |||
390 | 0 | 0 | $min = $b if $min > $b; | |||
391 | 0 | 0 | $max = $b if $max < $b; | |||
392 | ||||||
393 | 0 | 0 | my $delta = $max - $min; # 0 - 0xfff | |||
394 | 0 | 0 | $val = $max; # 0 - 0xfff | |||
395 | ||||||
396 | 0 | 0 | if ($delta){ | |||
397 | ||||||
398 | 0 | 0 | $sat = 0xfff * $delta / $max; # 0 - 0xfff | |||
399 | ||||||
400 | # Generate *hue between 0 and 0x5fff | |||||
401 | ||||||
402 | 0 | 0 | if ($r == $max){ | |||
403 | 0 | 0 | $hue = 0x1000 + 0x1000 * ($g - $b) / $delta; | |||
404 | }elsif ($g == $max){ | |||||
405 | 0 | 0 | $hue = 0x3000 + 0x1000 * ($b - $r) / $delta; | |||
406 | }else{ | |||||
407 | 0 | 0 | $hue = 0x5000 + 0x1000 * ($r - $g) / $delta; | |||
408 | } | |||||
409 | }else{ | |||||
410 | 0 | 0 | $sat = 0; | |||
411 | 0 | 0 | $hue = 0; | |||
412 | } | |||||
413 | ||||||
414 | 0 | 0 | return ($hue, $sat, $val); | |||
415 | } | |||||
416 | ||||||
417 | ||||||
418 | sub HSV_DISTANCE{ | |||||
419 | 2293800 | 7470831 | my ($self, $h, $s, $v, $index) = @_; | |||
420 | ||||||
421 | 2293800 | 9814290 | my $v1 = $v - $self->{hsv_palette}->[$index * 4 + 3]; | |||
422 | 2293800 | 9544149 | my $s1 = $s - $self->{hsv_palette}->[$index * 4 + 2]; | |||
423 | 2293800 | 9598570 | my $h1 = $h - $self->{hsv_palette}->[$index * 4 + 1]; | |||
424 | ||||||
425 | 2293800 | 12275405 | my $s2 = $self->{hsv_palette}->[$index * 4 + 3] ? CAA_HSV_YRATIO * $s1 * $s1 : 0; | |||
426 | 2293800 | 11350096 | my $h2 = $self->{hsv_palette}->[$index * 4 + 2] ? CAA_HSV_HRATIO * $h1 * $h1 : 0; | |||
427 | ||||||
428 | 2293800 | 13903880 | return $self->{hsv_palette}->[$index * 4] * ((CAA_HSV_XRATIO * $v1 * $v1) + $s2 + $h2); | |||
429 | } | |||||
430 | ||||||
431 | sub load_submodule { | |||||
432 | 29 | 98 | my ($self, $module, $args) = @_; | |||
433 | ||||||
434 | 29 | 822 | eval "require Image::Caa::$module"; | |||
435 | 29 | 191 | warn $@ if $@; | |||
436 | ||||||
437 | 29 | 65 | my $obj = undef; | |||
438 | 29 | 697 | eval "\$obj = new Image::Caa::$module(\$args)"; | |||
439 | 29 | 121 | warn $@ if $@; | |||
440 | ||||||
441 | 29 | 299 | if (!$@ && defined $obj){ | |||
442 | ||||||
443 | 28 | 119 | return $obj; | |||
444 | } | |||||
445 | ||||||
446 | 1 | 2 | die "Image::Caa - Couldn't load 'Image::Caa::$module'"; | |||
447 | } | |||||
448 | ||||||
449 | 1; | |||||
450 |