-
Notifications
You must be signed in to change notification settings - Fork 34
/
image2prime.pl
195 lines (156 loc) · 6.93 KB
/
image2prime.pl
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
#!/usr/bin/perl
# Author: Trizen
# Date: 29 April 2022
# https://github.com/trizen
# Generate an ASCII representation for an image, using only digits, such that the number is a prime.
# Inspired by the following Matt Parker video:
# https://yewtu.be/watch?v=dET2l8l3upU
# See also:
# https://github.com/TotalTechGeek/pictoprime
use 5.010;
use strict;
use autodie;
use warnings;
use GD qw();
use List::Util qw(max);
use Getopt::Long qw(GetOptions);
use Math::Prime::Util::GMP qw(is_prob_prime);
use constant {
GENERATE_PRIME => 1, # true to generate primes (slow)
};
GD::Image->trueColor(1);
my $size = 80;
sub help {
my ($code) = @_;
print <<"HELP";
usage: $0 [options] [files]
options:
-w --width=i : width size of the ASCII image (default: $size)
example:
perl $0 --width 200 image.png
HELP
exit($code);
}
GetOptions('w|width=s' => \$size,
'h|help' => sub { help(0) },)
or die "Error in command-line arguments!";
sub map_value {
my ($value, $in_min, $in_max, $out_min, $out_max) = @_;
($value - $in_min) * ($out_max - $out_min) / ($in_max - $in_min) + $out_min;
}
my @digits = split(//, "7772299408");
#my @digits = 0..9;
# The ways that we allow the algorithm to substitute a character.
# Like 0 can become 8 or 9, so on and so forth.
my %substitutions = (
'0' => ['8', '9'],
'1' => ['7'],
'7' => ['1'],
'8' => ['0', '9'],
'9' => ['4'],
'4' => ['9'],
);
# These are used to swap out the last digit if necessary.
my %edge_digit_substitutions = (
'0' => '3',
'2' => '3',
'4' => '9',
'6' => '9',
'8' => '9',
'5' => '3'
);
sub create_prime {
my ($pixels) = @_;
GENERATE_PRIME || return $pixels;
if (substr($pixels, 0, 1) == 0) {
substr($pixels, 0, 1, $edge_digit_substitutions{0});
}
if (exists($edge_digit_substitutions{substr($pixels, -1)})) {
my $digit = chop $pixels;
$pixels .= $edge_digit_substitutions{$digit};
}
my $count = 0;
my $copy = $pixels;
my $length = length($pixels);
my @substitution_indices = grep { exists $substitutions{substr($pixels, $_, 1)} } 0 .. $length - 1;
while (1) {
if (is_prob_prime($pixels)) {
return $pixels;
}
if (++$count > 5) {
$pixels = $copy;
$count = 0;
}
my $rand = $substitution_indices[int rand scalar @substitution_indices];
my $digit = substr($pixels, $rand, 1);
my $alt = $substitutions{$digit};
substr($pixels, $rand, 1, $alt->[int rand scalar @$alt]);
}
}
sub img2prime {
my ($image) = @_;
my $img = GD::Image->new($image) // return;
my ($width, $height) = $img->getBounds;
if ($size != 0) {
my $scale_width = $size;
my $scale_height = int($height / ($width / ($size / 2)));
my $resized = GD::Image->new($scale_width, $scale_height);
$resized->copyResampled($img, 0, 0, 0, 0, $scale_width, $scale_height, $width, $height);
($width, $height) = ($scale_width, $scale_height);
$img = $resized;
}
my $avg = 0;
my @averages;
foreach my $y (0 .. $height - 1) {
foreach my $x (0 .. $width - 1) {
my $index = $img->getPixel($x, $y);
my ($r, $g, $b) = $img->rgb($index);
my $value = max($r, $g, $b);
push @averages, $digits[map_value($value, 0, 255, 0, $#digits)];
}
}
my $prime = create_prime(join('', @averages));
unpack("(A$width)*", $prime);
}
say for img2prime($ARGV[0] // help(1));
__END__
30000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000001002222333222221100000000000000000000000000000000000000000
00000000000000000001101343344444444333332211000000000000000000000000000000000000
00000000000000000000355455555555556666666665544332100000000000000000000000000000
00000000000000003543245666666666777777777666665544321000000000000000000000000000
00000000000000001256666666677777777777777776666655432100000000000000000000000000
00000000011144433225666678888888876555556655543433322100000000000000000000000000
00000000012234667777767888888753135554300134310000000000000000000000000000000000
00000000001233356777888888884013366653000000000000000000000110000000000000000000
00000000000013345678888888711335667631000000000000000000000000010000000000000000
00001124556666656888888888123456776520000000000000111111100000011110000000000000
00033334567777788888888885245667776651000000000010000000000000001110001000000000
00021034355667788888888884456778877766520000000100000000022000000100000100000000
00000013044455888888888887788888888875300000000110000000132032111000000110000000
00000000012053888888888888888888888888400000000111001110220301211000001110000000
00000000000020788888888888888888888888830000001000000022021013133211001100000000
00000000000020788888888888888888888888830000010000000001221121121011000001000000
00000000013054888888888888888888888888400000001000001222222122231000000001000000
00000013044455888888888887778888888885400000000001100000001221021000000010000000
00022034355677788888888884456668877766420000000001110000011000000001111000000000
00033335567777788888888885235667776651000000000000100000000000000001100000000000
00000124455666655888888888123456777520000800000000011000011110000011000000000000
00000000000023345678888888711334667641000000000000000110000011111100000000000000
00000000001233356777888888884113366653000000000000000000000000000000000000000000
00000000012234667777767888888753135554300134310000000000000000000000000000000000
00000000011134332225666678888888876555556655544433332100000000000000000000000000
00000000000000001256666666667777777777777776666655432100000000000000000000000000
00000000000000013443245666666666777777777666665544321000000000000000000000000000
00000000000000000000354455555555555666665555543321100000000000000000000000000000
00000000000000000001101343344344434343332210000000000000000000000000000000000000
00000000000000000000001002222223222221100000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000003