line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Image::Caa; |
2
|
|
|
|
|
|
|
|
3
|
3
|
|
|
3
|
|
108328
|
use strict; |
|
3
|
|
|
|
|
11
|
|
|
3
|
|
|
|
|
134
|
|
4
|
3
|
|
|
3
|
|
16
|
use warnings; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
145
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
our $VERSION = '1.01'; |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
# dark colors |
9
|
3
|
|
|
3
|
|
24
|
use constant CAA_COLOR_BLACK => 0; |
|
3
|
|
|
|
|
11
|
|
|
3
|
|
|
|
|
317
|
|
10
|
3
|
|
|
3
|
|
16
|
use constant CAA_COLOR_RED => 1; |
|
3
|
|
|
|
|
4
|
|
|
3
|
|
|
|
|
134
|
|
11
|
3
|
|
|
3
|
|
14
|
use constant CAA_COLOR_GREEN => 2; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
129
|
|
12
|
3
|
|
|
3
|
|
15
|
use constant CAA_COLOR_YELLOW => 3; |
|
3
|
|
|
|
|
3
|
|
|
3
|
|
|
|
|
209
|
|
13
|
3
|
|
|
3
|
|
15
|
use constant CAA_COLOR_BLUE => 4; |
|
3
|
|
|
|
|
41
|
|
|
3
|
|
|
|
|
136
|
|
14
|
3
|
|
|
3
|
|
15
|
use constant CAA_COLOR_MAGENTA => 5; |
|
3
|
|
|
|
|
4
|
|
|
3
|
|
|
|
|
162
|
|
15
|
3
|
|
|
3
|
|
13
|
use constant CAA_COLOR_CYAN => 6; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
187
|
|
16
|
3
|
|
|
3
|
|
44
|
use constant CAA_COLOR_LIGHTGRAY => 7; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
238
|
|
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
# light colors |
19
|
3
|
|
|
3
|
|
22
|
use constant CAA_COLOR_DARKGRAY => 8; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
133
|
|
20
|
3
|
|
|
3
|
|
15
|
use constant CAA_COLOR_LIGHTRED => 9; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
125
|
|
21
|
3
|
|
|
3
|
|
24
|
use constant CAA_COLOR_LIGHTGREEN => 10; |
|
3
|
|
|
|
|
4
|
|
|
3
|
|
|
|
|
126
|
|
22
|
3
|
|
|
3
|
|
20
|
use constant CAA_COLOR_BROWN => 11; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
278
|
|
23
|
3
|
|
|
3
|
|
14
|
use constant CAA_COLOR_LIGHTBLUE => 12; |
|
3
|
|
|
|
|
11
|
|
|
3
|
|
|
|
|
151
|
|
24
|
3
|
|
|
3
|
|
15
|
use constant CAA_COLOR_LIGHTMAGENTA => 13; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
117
|
|
25
|
3
|
|
|
3
|
|
16
|
use constant CAA_COLOR_LIGHTCYAN => 14; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
131
|
|
26
|
3
|
|
|
3
|
|
15
|
use constant CAA_COLOR_WHITE => 15; |
|
3
|
|
|
|
|
4
|
|
|
3
|
|
|
|
|
131
|
|
27
|
|
|
|
|
|
|
|
28
|
3
|
|
|
3
|
|
15
|
use constant CAA_LOOKUP_VAL => 32; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
128
|
|
29
|
3
|
|
|
3
|
|
22
|
use constant CAA_LOOKUP_SAT => 32; |
|
3
|
|
|
|
|
4
|
|
|
3
|
|
|
|
|
174
|
|
30
|
3
|
|
|
3
|
|
45
|
use constant CAA_LOOKUP_HUE => 16; |
|
3
|
|
|
|
|
4
|
|
|
3
|
|
|
|
|
5375
|
|
31
|
|
|
|
|
|
|
|
32
|
3
|
|
|
3
|
|
25
|
use constant CAA_HSV_XRATIO => 6; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
183
|
|
33
|
3
|
|
|
3
|
|
16
|
use constant CAA_HSV_YRATIO => 3; |
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
117
|
|
34
|
3
|
|
|
3
|
|
14
|
use constant CAA_HSV_HRATIO => 3; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
13482
|
|
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
sub new { |
38
|
15
|
|
|
15
|
1
|
6406
|
my $class = shift; |
39
|
15
|
|
|
|
|
60
|
my %opts = @_; |
40
|
15
|
|
|
|
|
36
|
my $opts = \%opts; |
41
|
|
|
|
|
|
|
|
42
|
15
|
|
|
|
|
549
|
my $self = bless {}, $class; |
43
|
|
|
|
|
|
|
|
44
|
15
|
|
100
|
|
|
131
|
$self->{driver} = $self->load_submodule($opts->{driver} || 'DriverANSI', $opts); |
45
|
14
|
|
100
|
|
|
75
|
$self->{dither} = $self->load_submodule($opts->{dither} || 'DitherNone', $opts); |
46
|
14
|
100
|
|
|
|
64
|
$self->{solid_background} = $opts->{black_bg} ? 0 : 1; |
47
|
|
|
|
|
|
|
|
48
|
14
|
|
|
|
|
103
|
$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
|
|
|
|
|
47
|
$self->init(); |
61
|
|
|
|
|
|
|
|
62
|
14
|
|
|
|
|
259
|
return $self; |
63
|
|
|
|
|
|
|
} |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
sub init { |
67
|
14
|
|
|
14
|
0
|
26
|
my ($self) = @_; |
68
|
|
|
|
|
|
|
|
69
|
14
|
|
|
|
|
34
|
$self->{hsv_distances} = []; |
70
|
|
|
|
|
|
|
|
71
|
14
|
|
|
|
|
52
|
for (my $v = 0; $v < CAA_LOOKUP_VAL; $v++){ |
72
|
448
|
|
|
|
|
966
|
for (my $s = 0; $s < CAA_LOOKUP_SAT; $s++){ |
73
|
14336
|
|
|
|
|
28102
|
for (my $h = 0; $h < CAA_LOOKUP_HUE; $h++){ |
74
|
|
|
|
|
|
|
|
75
|
229376
|
|
|
|
|
316223
|
my $val = 0xfff * $v / (CAA_LOOKUP_VAL - 1); |
76
|
229376
|
|
|
|
|
298320
|
my $sat = 0xfff * $s / (CAA_LOOKUP_SAT - 1); |
77
|
229376
|
|
|
|
|
279769
|
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
|
|
|
|
|
245760
|
my $outbg = 3; |
83
|
229376
|
|
|
|
|
245480
|
my $outfg = 3; |
84
|
229376
|
|
|
|
|
448520
|
my $distbg = $self->HSV_DISTANCE(0, 0, 0, 3); |
85
|
229376
|
|
|
|
|
455098
|
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
|
229376
|
|
|
|
|
540708
|
for (my $i = 0; $i < 8; $i++){ |
92
|
|
|
|
|
|
|
|
93
|
1835008
|
|
|
|
|
3585878
|
my $dist = $self->HSV_DISTANCE($hue, $sat, $val, $i); |
94
|
|
|
|
|
|
|
|
95
|
1835008
|
100
|
|
|
|
5473272
|
if ($dist <= $distbg){ |
|
|
100
|
|
|
|
|
|
96
|
|
|
|
|
|
|
|
97
|
651252
|
|
|
|
|
705941
|
$outfg = $outbg; |
98
|
651252
|
|
|
|
|
701596
|
$distfg = $distbg; |
99
|
651252
|
|
|
|
|
738054
|
$outbg = $i; |
100
|
651252
|
|
|
|
|
1550822
|
$distbg = $dist; |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
}elsif ($dist <= $distfg){ |
103
|
|
|
|
|
|
|
|
104
|
286846
|
|
|
|
|
282773
|
$outfg = $i; |
105
|
286846
|
|
|
|
|
650782
|
$distfg = $dist; |
106
|
|
|
|
|
|
|
} |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
|
109
|
229376
|
|
|
|
|
978311
|
$self->{hsv_distances}->[$v]->[$s]->[$h] = ($outfg << 4) | $outbg; |
110
|
|
|
|
|
|
|
} |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
} |
113
|
|
|
|
|
|
|
} |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
sub init_instance { |
116
|
5
|
|
|
5
|
0
|
10
|
my ($self) = @_; |
117
|
|
|
|
|
|
|
|
118
|
5
|
|
|
|
|
18
|
$self->{lookup_colors} = []; |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
# These ones are constant |
121
|
5
|
|
|
|
|
17
|
$self->{lookup_colors}->[0] = CAA_COLOR_BLACK; |
122
|
5
|
|
|
|
|
10
|
$self->{lookup_colors}->[1] = CAA_COLOR_DARKGRAY; |
123
|
5
|
|
|
|
|
12
|
$self->{lookup_colors}->[2] = CAA_COLOR_LIGHTGRAY; |
124
|
5
|
|
|
|
|
14
|
$self->{lookup_colors}->[3] = CAA_COLOR_WHITE; |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
# These ones will be overwritten |
127
|
5
|
|
|
|
|
10
|
$self->{lookup_colors}->[4] = CAA_COLOR_MAGENTA; |
128
|
5
|
|
|
|
|
26
|
$self->{lookup_colors}->[5] = CAA_COLOR_LIGHTMAGENTA; |
129
|
5
|
|
|
|
|
12
|
$self->{lookup_colors}->[6] = CAA_COLOR_RED; |
130
|
5
|
|
|
|
|
11
|
$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
|
|
|
5
|
1
|
43
|
my ($self, $x1, $y1, $x2, $y2, $image) = @_; |
148
|
|
|
|
|
|
|
|
149
|
5
|
|
|
|
|
9
|
my $w = $x2-$x1; |
150
|
5
|
|
|
|
|
9
|
my $h = $y2-$y1; |
151
|
|
|
|
|
|
|
|
152
|
5
|
|
|
|
|
9
|
my $iw = 0; |
153
|
5
|
|
|
|
|
9
|
my $ih = 0; |
154
|
5
|
|
|
|
|
8
|
my $h_pad = 0; |
155
|
5
|
|
|
|
|
11
|
my $v_pad = 0; |
156
|
|
|
|
|
|
|
|
157
|
5
|
50
|
|
|
|
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
|
|
|
|
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
|
|
|
|
|
21
|
$self->init_instance(); |
172
|
5
|
|
|
|
|
34
|
$self->{driver}->init(); |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
# Only used when background is black |
176
|
|
|
|
|
|
|
|
177
|
5
|
|
|
|
|
14
|
my $white_colors = [ |
178
|
|
|
|
|
|
|
CAA_COLOR_BLACK, |
179
|
|
|
|
|
|
|
CAA_COLOR_DARKGRAY, |
180
|
|
|
|
|
|
|
CAA_COLOR_LIGHTGRAY, |
181
|
|
|
|
|
|
|
CAA_COLOR_WHITE, |
182
|
|
|
|
|
|
|
]; |
183
|
|
|
|
|
|
|
|
184
|
5
|
|
|
|
|
19
|
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
|
|
|
|
|
18
|
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
|
|
|
|
|
18
|
my $density_chars = |
208
|
|
|
|
|
|
|
" ". |
209
|
|
|
|
|
|
|
". ". |
210
|
|
|
|
|
|
|
".. ". |
211
|
|
|
|
|
|
|
"....". |
212
|
|
|
|
|
|
|
"::::". |
213
|
|
|
|
|
|
|
";=;=". |
214
|
|
|
|
|
|
|
"tftf". |
215
|
|
|
|
|
|
|
'%$%$'. |
216
|
|
|
|
|
|
|
"&KSZ". |
217
|
|
|
|
|
|
|
"WXGM". |
218
|
|
|
|
|
|
|
'@@@@'. |
219
|
|
|
|
|
|
|
"8888". |
220
|
|
|
|
|
|
|
"####". |
221
|
|
|
|
|
|
|
"????"; |
222
|
|
|
|
|
|
|
|
223
|
5
|
|
|
|
|
183
|
my @density_chars = split //, $density_chars; |
224
|
5
|
|
|
|
|
23
|
$density_chars = \@density_chars; |
225
|
|
|
|
|
|
|
|
226
|
5
|
|
|
|
|
8
|
my $density_chars_size = scalar(@{$density_chars}) - 1; |
|
5
|
|
|
|
|
13
|
|
227
|
|
|
|
|
|
|
|
228
|
5
|
|
|
|
|
7
|
my $x = 0; |
229
|
5
|
|
|
|
|
10
|
my $y = 0; |
230
|
5
|
|
|
|
|
7
|
my $deltax = 0; |
231
|
5
|
|
|
|
|
6
|
my $deltay = 0; |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
|
234
|
5
|
|
|
|
|
7
|
my $tmp; |
235
|
5
|
50
|
|
|
|
16
|
if ($x1 > $x2){ $tmp = $x2; $x2 = $x1; $x1 = $tmp; } |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
236
|
5
|
50
|
|
|
|
14
|
if ($y1 > $y2){ $tmp = $y2; $y2 = $y1; $y1 = $tmp; } |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
237
|
|
|
|
|
|
|
|
238
|
5
|
|
|
|
|
9
|
$deltax = $x2 - $x1 + 1; |
239
|
5
|
|
|
|
|
9
|
$deltay = $y2 - $y1 + 1; |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
|
242
|
5
|
50
|
|
|
|
67
|
for ($y = $y1 > 0 ? $y1 : 0; $y <= $y2; $y++){ |
243
|
10
|
|
|
|
|
45
|
$self->{dither}->init($y); |
244
|
10
|
50
|
|
|
|
38
|
for ($x = $x1 > 0 ? $x1 : 0; $x <= $x2; $x++){ |
245
|
|
|
|
|
|
|
|
246
|
20
|
|
|
|
|
25
|
my $ch = 0; |
247
|
20
|
|
|
|
|
22
|
my $r = 0; |
248
|
20
|
|
|
|
|
20
|
my $g = 0; |
249
|
20
|
|
|
|
|
15
|
my $b = 0; |
250
|
20
|
|
|
|
|
23
|
my $a = 0; |
251
|
20
|
|
|
|
|
20
|
my $hue = 0; |
252
|
20
|
|
|
|
|
20
|
my $sat = 0; |
253
|
20
|
|
|
|
|
24
|
my $val = 0; |
254
|
20
|
|
|
|
|
21
|
my $fromx = 0; |
255
|
20
|
|
|
|
|
20
|
my $fromy = 0; |
256
|
20
|
|
|
|
|
20
|
my $tox = 0; |
257
|
20
|
|
|
|
|
20
|
my $toy = 0; |
258
|
20
|
|
|
|
|
13
|
my $myx = 0; |
259
|
20
|
|
|
|
|
26
|
my $myy = 0; |
260
|
20
|
|
|
|
|
19
|
my $dots = 0; |
261
|
20
|
|
|
|
|
24
|
my $outfg = 0; |
262
|
20
|
|
|
|
|
18
|
my $outbg = 0; |
263
|
20
|
|
|
|
|
23
|
my $outch = chr 0; |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
# First get RGB |
266
|
|
|
|
|
|
|
|
267
|
20
|
50
|
|
|
|
33
|
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
|
0
|
|
|
0
|
if ($to_l || $to_t || $to_r || $to_b){ |
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
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
|
|
|
|
|
38
|
$hue = int(0x5fff * (($x-$x1) / ($x2-$x1))); |
300
|
20
|
|
|
|
|
29
|
$sat = int(0xfff * (($y-$y1) / ($y2-$y1))); |
301
|
20
|
|
|
|
|
26
|
$val = int(0xfff * (($y-$y1) / ($y2-$y1))); |
302
|
20
|
|
|
|
|
24
|
$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
|
50
|
|
|
|
39
|
if ($self->{solid_background}){ |
310
|
|
|
|
|
|
|
|
311
|
20
|
|
|
|
|
26
|
my $point = chr 0; |
312
|
20
|
|
|
|
|
19
|
my $distfg = 0; |
313
|
20
|
|
|
|
|
26
|
my $distbg = 0; |
314
|
|
|
|
|
|
|
|
315
|
20
|
|
|
|
|
44
|
$self->{lookup_colors}->[4] = $dark_colors->[1 + $hue / 0x1000]; |
316
|
20
|
|
|
|
|
38
|
$self->{lookup_colors}->[5] = $light_colors->[1 + $hue / 0x1000]; |
317
|
20
|
|
|
|
|
31
|
$self->{lookup_colors}->[6] = $dark_colors->[$hue / 0x1000]; |
318
|
20
|
|
|
|
|
32
|
$self->{lookup_colors}->[7] = $light_colors->[$hue / 0x1000]; |
319
|
|
|
|
|
|
|
|
320
|
20
|
|
|
|
|
65
|
my $idx_v = ($val + $self->{dither}->get() * (0x1000 / CAA_LOOKUP_VAL) / 0x100) * (CAA_LOOKUP_VAL - 1) / 0x1000; |
321
|
20
|
|
|
|
|
56
|
my $idx_s = ($sat + $self->{dither}->get() * (0x1000 / CAA_LOOKUP_SAT) / 0x100) * (CAA_LOOKUP_SAT - 1) / 0x1000; |
322
|
20
|
|
|
|
|
92
|
my $idx_h = (($hue & 0xfff) + $self->{dither}->get() * (0x1000 / CAA_LOOKUP_HUE) / 0x100) * (CAA_LOOKUP_HUE - 1) / 0x1000; |
323
|
|
|
|
|
|
|
|
324
|
20
|
|
|
|
|
49
|
$point = $self->{hsv_distances}->[$idx_v]->[$idx_s]->[$idx_h]; |
325
|
|
|
|
|
|
|
|
326
|
20
|
|
|
|
|
120
|
$distfg = $self->HSV_DISTANCE($hue % 0xfff, $sat, $val, ($point >> 4)); |
327
|
20
|
|
|
|
|
57
|
$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
|
50
|
|
|
|
49
|
if ($distbg > $distfg){ $distbg = $distfg; } |
|
0
|
|
|
|
|
0
|
|
333
|
|
|
|
|
|
|
|
334
|
20
|
|
|
|
|
34
|
$outfg = $self->{lookup_colors}->[($point >> 4)]; |
335
|
20
|
|
|
|
|
30
|
$outbg = $self->{lookup_colors}->[($point & 0xf)]; |
336
|
|
|
|
|
|
|
|
337
|
20
|
|
|
|
|
33
|
$ch = $distbg * 2 * ($density_chars_size - 1) / ($distbg + $distfg); |
338
|
20
|
|
|
|
|
64
|
$ch = 4 * $ch + $self->{dither}->get() / 0x40; |
339
|
|
|
|
|
|
|
|
340
|
20
|
100
|
|
|
|
25
|
if ($ch >= scalar(@{$density_chars})){ |
|
20
|
|
|
|
|
55
|
|
341
|
|
|
|
|
|
|
|
342
|
15
|
|
|
|
|
14
|
$ch = scalar(@{$density_chars}) - 1; |
|
15
|
|
|
|
|
25
|
|
343
|
|
|
|
|
|
|
} |
344
|
|
|
|
|
|
|
|
345
|
20
|
|
|
|
|
40
|
$outch = $density_chars->[$ch]; |
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
}else{ |
348
|
|
|
|
|
|
|
|
349
|
0
|
|
|
|
|
0
|
$outbg = CAA_COLOR_BLACK; |
350
|
|
|
|
|
|
|
|
351
|
0
|
0
|
|
|
|
0
|
if ($sat < 0x200 + $self->{dither}->get() * 0x8){ |
|
|
0
|
|
|
|
|
|
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
|
|
|
|
|
64
|
$self->{driver}->set_color($outfg, $outbg); |
371
|
20
|
|
|
|
|
57
|
$self->{driver}->putchar($x, $y, $outch); |
372
|
|
|
|
|
|
|
|
373
|
20
|
|
|
|
|
58
|
$self->{dither}->increment(); |
374
|
|
|
|
|
|
|
} |
375
|
|
|
|
|
|
|
} |
376
|
|
|
|
|
|
|
|
377
|
5
|
|
|
|
|
18
|
$self->{driver}->fini(); |
378
|
|
|
|
|
|
|
} |
379
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
sub rgb2hsv_default { |
381
|
0
|
|
|
0
|
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
|
|
|
|
0
|
$min = $g if $min > $g; |
389
|
0
|
0
|
|
|
|
0
|
$max = $g if $max < $g; |
390
|
0
|
0
|
|
|
|
0
|
$min = $b if $min > $b; |
391
|
0
|
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
|
|
|
|
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
|
|
|
|
0
|
if ($r == $max){ |
|
|
0
|
|
|
|
|
|
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
|
|
|
2293800
|
0
|
3165216
|
my ($self, $h, $s, $v, $index) = @_; |
420
|
|
|
|
|
|
|
|
421
|
2293800
|
|
|
|
|
4128561
|
my $v1 = $v - $self->{hsv_palette}->[$index * 4 + 3]; |
422
|
2293800
|
|
|
|
|
3456118
|
my $s1 = $s - $self->{hsv_palette}->[$index * 4 + 2]; |
423
|
2293800
|
|
|
|
|
3500070
|
my $h1 = $h - $self->{hsv_palette}->[$index * 4 + 1]; |
424
|
|
|
|
|
|
|
|
425
|
2293800
|
100
|
|
|
|
4919191
|
my $s2 = $self->{hsv_palette}->[$index * 4 + 3] ? CAA_HSV_YRATIO * $s1 * $s1 : 0; |
426
|
2293800
|
100
|
|
|
|
4409578
|
my $h2 = $self->{hsv_palette}->[$index * 4 + 2] ? CAA_HSV_HRATIO * $h1 * $h1 : 0; |
427
|
|
|
|
|
|
|
|
428
|
2293800
|
|
|
|
|
5935058
|
return $self->{hsv_palette}->[$index * 4] * ((CAA_HSV_XRATIO * $v1 * $v1) + $s2 + $h2); |
429
|
|
|
|
|
|
|
} |
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
sub load_submodule { |
432
|
29
|
|
|
29
|
0
|
51
|
my ($self, $module, $args) = @_; |
433
|
|
|
|
|
|
|
|
434
|
29
|
|
|
|
|
2206
|
eval "require Image::Caa::$module"; |
435
|
29
|
100
|
|
|
|
185
|
warn $@ if $@; |
436
|
|
|
|
|
|
|
|
437
|
29
|
|
|
|
|
46
|
my $obj = undef; |
438
|
29
|
|
|
|
|
8761
|
eval "\$obj = new Image::Caa::$module(\$args)"; |
439
|
29
|
100
|
|
|
|
138
|
warn $@ if $@; |
440
|
|
|
|
|
|
|
|
441
|
29
|
100
|
66
|
|
|
163
|
if (!$@ && defined $obj){ |
442
|
|
|
|
|
|
|
|
443
|
28
|
|
|
|
|
113
|
return $obj; |
444
|
|
|
|
|
|
|
} |
445
|
|
|
|
|
|
|
|
446
|
1
|
|
|
|
|
205
|
die "Image::Caa - Couldn't load 'Image::Caa::$module'"; |
447
|
|
|
|
|
|
|
} |
448
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
1; |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
__END__ |