-
Notifications
You must be signed in to change notification settings - Fork 1
/
ppmmosaic
executable file
·399 lines (290 loc) · 9.71 KB
/
ppmmosaic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
#!/usr/bin/perl -w
# Expand pixels in a PPM to make mosaic like images.
#
# To do: separate color choices for each border.
# user-defined pixel manipulation function.
#
# Benjamin Elijah Griffin 28 Feb 2003
use strict;
use integer;
use Image::PPMlib;
use vars qw( $id $arg $err $i $j $k $r $g $b $br $bg $bb $tri
$inforef @line @out $pc $pix $mpix
$file $bmode $bpixels $bpT $bpB $bpL $bpR $pixels
$VERSION
);
$id = $0;
$id =~ s:.*/::;
$VERSION = "0.5";
$bmode = 'none';
$bpT = $bpB = $bpL = $bpR = 1;
$pixels = 10;
while (defined($ARGV[0]) and $ARGV[0] =~ /^-(.*)/) {
$arg = $1; # stripped of first hyphen
shift;
if ($arg eq '-help' or $arg eq '-version' or $arg eq 'v') {
&usage(0);
} elsif ($arg eq 'b' or $arg eq '-border') {
$bmode = shift;
if ($bmode eq 'none' or $bmode eq 'dark' or $bmode eq 'light') {
1; # valid mode that requires no processing now
} elsif ($bmode eq 'darker' or $bmode eq 'lighter') {
$bmode =~ s/er$//;
} elsif ($bmode eq 'black') {
($br, $bg, $bb) = ( 0, 0, 0 );
} elsif ($bmode eq 'white') {
($br, $bg, $bb) = ( 255, 255, 255 );
} elsif ($bmode eq 'red') {
($br, $bg, $bb) = ( 255, 0, 0 );
} elsif ($bmode eq 'green') {
($br, $bg, $bb) = ( 0, 255, 0 );
} elsif ($bmode eq 'blue') {
($br, $bg, $bb) = ( 0, 0, 255 );
} elsif ($bmode =~ /^fixed:(\d+:\d+:\d+)$/) {
$tri = $1;
$bmode = 'fixed';
($br, $bg, $bb) = split(/:/, $tri, 3)
} elsif ($bmode =~ /^fixed:([0-9a-fA-F]{6})$/) {
$tri = $1;
$bmode = 'fixed';
($br, $bg, $bb) = hextriplettoraw($tri);
$br = ord($br);
$bg = ord($bg);
$bb = ord($bb);
} else {
$err = 1;
warn "$id: Invalid mode for -b (--border)\n";
}
} elsif ($arg eq 'e' or $arg eq '-borderpixels') {
$bpixels = shift;
if ($bpixels =~ /^(\d+),(\d+),(\d+),(\d+)$/) {
$bpT = $1;
$bpB = $2;
$bpL = $3;
$bpR = $4;
$bpixels = '';
}
elsif ($bpixels =~ /^[1-9]\d*$/) {
$bpT = $bpB = int($bpixels / 2);
if ($bpixels % 2) {
$bpT ++;
}
$bpL = $bpT;
$bpR = $bpR;
}
else {
$err = 1;
warn "$id: Invalid pixel value for -e (--borderpixels)\n";
}
} elsif ($arg eq 'p' or $arg eq '-pixels') {
$pixels = shift;
if ($pixels !~ /^[1-9]\d*$/) {
$err = 1;
warn "$id: Invalid pixel value for -p (--pixels)\n";
}
} elsif ($arg eq '-') {
last;
} else {
$err = 1;
warn "$id: unrecognized argument: -$arg\n";
}
}
if ($err) {
die "Use --help for usage\n";
}
$file = shift;
if(!defined($file)) { $file = '-'; }
if(!open(PPM, "< $file")) {
die "$id: Cannot open $file: $!\n";
}
$inforef = readppmheader(\*PPM);
if ($$inforef{error}) {
die "$id: $file: $$inforef{error}\n";
}
if ($$inforef{bgp} ne 'p') {
die "$id: $file is not a ppm file\n";
}
# No border overrides any specified border size
if ($bmode eq 'none') {
$bpT = $bpB = $bpL = $bpR = 0;
}
printf("P6\n%d %d\n%d\n", $$inforef{width} * ($bpL + $bpR + $pixels),
$$inforef{height} * ($bpT + $bpB + $pixels),
255);
# If we can, calculate the border stuff now.
if($bmode ne 'none') {
$pc = $bpL + $bpR + $pixels; # width of border + cell
if(($bmode ne 'light') and ($bmode ne 'dark')) {
$pix = $Image::PPMlib::decraw{$br} .
$Image::PPMlib::decraw{$bg} .
$Image::PPMlib::decraw{$bb};
}
}
# loop i: each line of height
for ($i = 0; $i < $$inforef{height}; $i ++) {
@line = readpixels_dec(\*PPM, $$inforef{type}, $$inforef{width});
for($k = 0; $k < $bpT + $bpB + $pixels; $k ++) {
$out[$k] = '';
}
# loop j: each pixel in the line
for($j = 0; $j < @line; $j ++) {
# figure out per-pixel borders
if ($bmode eq 'light') {
$br = $line[$j][0] * 11 / 10; # mult by 1.1 with 'use integer'
$bg = $line[$j][1] * 11 / 10; # mult by 1.1 with 'use integer'
$bb = $line[$j][2] * 11 / 10; # mult by 1.1 with 'use integer'
$br = ($br>255)? 255 : $br;
$bg = ($bg>255)? 255 : $bg;
$bb = ($bb>255)? 255 : $bb;
$pix = $Image::PPMlib::decraw{$br} .
$Image::PPMlib::decraw{$bg} .
$Image::PPMlib::decraw{$bb};
} elsif ($bmode eq 'dark') {
$br = $line[$j][0] * 9 / 10; # mult by 0.9 with 'use integer'
$bg = $line[$j][1] * 9 / 10; # mult by 0.9 with 'use integer'
$bb = $line[$j][2] * 9 / 10; # mult by 0.9 with 'use integer'
$pix = $Image::PPMlib::decraw{$br} .
$Image::PPMlib::decraw{$bg} .
$Image::PPMlib::decraw{$bb};
}
# if any border, apply top and left now
if($bmode ne 'none' and ($bpT or $bpL)) {
for ($k = 0; $k < $bpT; $k ++) { # top border, top $bpT rows
$out[$k] .= $pix x $pc;
}
for ($k = 0; $k < $pixels; $k ++) { # left border, after $bpT rpws
$out[$k + $bpT] .= $pix x $bpL;
}
}
# main pixel body
$mpix = $Image::PPMlib::decraw{$line[$j][0]} .
$Image::PPMlib::decraw{$line[$j][1]} .
$Image::PPMlib::decraw{$line[$j][2]};
for ($k = 0; $k < $pixels; $k ++) { # inside main pixel, after $bpT rows
$out[$k + $bpT] .= $mpix x $pixels;
}
# if any border, apply bottom and right now
if($bmode ne 'none' and ($bpB or $bpR)) {
for ($k = 0; $k < $bpB; $k ++) { # bottom border, after $bpT + $pixels
$out[$k + $pixels + $bpT] .= $pix x $pc;
}
for ($k = 0; $k < $pixels; $k ++) { # right border, after $bpT rows
$out[$k + $bpT] .= $pix x $bpR;
}
}
} # end j: per pixel loop
for($k = 0; $k < $bpT + $bpB + $pixels; $k ++) {
# if no border, those strings will still be '' and are safe to print
print $out[$k];
}
if(@line != $$inforef{width}) {
warn "$id: ran out of pixels prematurely\n";
last;
}
} # for line of height
sub usage($) {
my $rc = shift;
print STDERR <<"ProgramUsage";
$id version $VERSION usage:
ppmmosaic reads PPM(5) files and makes larger pixelated versions of them,
with several border options.
Arguments:
-b MODE --border MODE MODE can be black, white, red, green,
blue, fixed:RGB, lighter, darker, or
none. RGB can 6 hex digits or a colon-
seperated decimal triple. 'lighter' and
'darker' are 10% changed from inner pixel
-e SIZE --borderpixels SIZE make the border be SIZE pixels (total, if
odd top and left borders will be larger)
-e T,B,L,R --borderpixels T,B,L,R set sizes for Top, Bottom, Left, and
Right borders
-p SIZE --pixels SIZE make the tile be SIZE pixels (plus border)
-- end arguments
bordermode defaults to none, borderpixels defaults to 1, pixels defaults to 10
Examples:
ppmmosaic -e 5 -p 20 -b fixed:255:150:200 foo.ppm > new-foo.ppm
If foo.ppm was 10x10, the new image will be 250x250, with pink
borders 3 pixels on top and left, 2 pixels on bottom and right
around each of the original pixels, which will now be 20x20 in
size.
ppmmosaic --borderpixels 2 --border fixed:808080 --pixels 6 bar.ppm \
> new-bar.ppm
Image new-bar.ppm will be 8 times larger than bar.ppm with 1 pixel
all around gray borders on the 6x6 tiles from bar.ppm, looking
something like a mosaic complete with grout.
ppmmosaic -e 1,0,0,0 --border black --pixels 1 bar.ppm > new-bar.ppm
Image new-bar.ppm will be twice as tall with a black line between
each row. If bar.ppm had previously been compressed 50% vertically,
it now has an early CRT scan-line look to it.
ProgramUsage
exit $rc;
}
__END__
=pod
=head1 NAME
ppmmosaic - make mosaic images by expanding pixels into bordered tiles
=head1 DESCRIPTION
ppmmosaic reads PPM(5) files and makes larger pixelated versions of them,
with several border options. Such images can look like simple block mosaics,
eg pick a big value for inner pixel size, and small border evenly sized on
all edges. Or venetian blind effects can be created by having borders in
one dimension only.
Options:
=over 4
=item *
-b MODE --border MODE
MODE can be C<black>, C<white>, C<red>, C<green>,
C<blue>, C<fixed:>I<RGB>, C<lighter>, C<darker>, or
C<none>.
For fixed color borders, the RGB value can 6 hex digits (eg "99CC33")
or a colon-seperated decimal triple (eg "153:204:51"). The C<black>,
C<white>, etc, border options are short hand for C<fixed:000000>,
C<fixed:FFFFFF>, etc.
The 'lighter' and 'darker' options are 10% changed from inner pixel.
Default is C<none>.
=item *
-e SIZE --borderpixels SIZE
Makes the border be SIZE pixels total. If SIZE is
odd, the top and left borders will be larger.
So C<-e 5> is equivilent to C<-e 3,2,3,2>
making the top and left borders three pixels,
and the bottom and right borders two pixels.
Default is equivilent to C<-e 2>.
=item *
-e T,B,L,R --borderpixels T,B,L,R
Sets the sizes for Top, Bottom, Left, and Right borders
individually.
Default is equivilent to C<-e 1,1,1,1>
=item *
-p SIZE --pixels SIZE
Makes the inner pixel tile be SIZE pixels. The border goes around
this inner pixel.
Default is C<10>.
=item *
--
Marks the end of the arguments
=item *
--help
Show a help message and exit.
=item *
--version
Same as C<--help>.
=back
=head1 COPYRIGHT
Copyright 2003 by Eli the Bearded / Benjamin Elijah Griffin.
Released under the same license(s) as Perl.
=head1 AUTHOR
Eli the Bearded originally the Image::PPMlib to make a script
very much like this one easier to code.
=head1 CPAN INFO
=head1 SCRIPT CATEGORIES
Image
=head1 README
ppmmosaic - make mosaic images by expanding pixels into bordered tiles
=head1 PREREQUISITES
This uses the C<strict>, C<vars>, C<integer>, and C<Image::PPMlib> modules.
=head1 COREQUISITES
None.
=head1 OSNAMES
Should be OS independent.
=cut