Created
January 14, 2024 14:03
-
-
Save jaggzh/70c77cf1959c2cc41f2eeee2c7e0541f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/perl | |
| # Copyright (C) 2016, jaggz.h {who is at} gmail.com | |
| # If you look or use this code, any further than this and the following line, | |
| # you agree to all the terms and conditions outlined below in code. | |
| # Otherwise, it's free to use, but if you make money off it, you must submit | |
| # to me your first-born child.. nevermind. I don't want it. Go ahead | |
| # and use it (the code) however you wish; I wish you well in life. | |
| # gist-paste -u https://gist.github.com/jaggzh/70c77cf1959c2cc41f2eeee2c7e0541f | |
| use strict; | |
| use warnings; | |
| my $fn; | |
| my $f; | |
| my ($r, $b, $g); | |
| my $str; | |
| my ($w,$h); | |
| my $depth; | |
| my @pixels; | |
| use Getopt::Long; | |
| my $opt_varname="img"; | |
| my $opt_help; | |
| my $verbose=0; | |
| GetOptions( | |
| "v|verbose+" => \$verbose, | |
| "n|var=s" => \$opt_varname, | |
| "h|help" => \$opt_help, | |
| ) or die("Error in command line arguments\n"); | |
| if ($opt_help) { | |
| print <<EOT; | |
| Usage: ppmto565 [options] [input] | |
| Generates a .C source file of RGB 16-bit data, suitable for use with many LCD | |
| displays. Modification might be necessary if your MCU or API/libraries can't | |
| make use of the unsigned int[] output. It also is customized for my ESP8266 | |
| use, with the Arduino IDE, where the INFLASH define, which you'll see in its | |
| output, places the image data in flash memory so as not to consume program | |
| space. Improvements are welcome <jaggz.h\@gmail.com> | |
| As its name states, it requires PPM input (magic P6 in the file); this means, | |
| if you're converting a greyscale or bw image with, say, pngtopnm, the output | |
| will likely be rejected by this program (because it'll probably be in pbm | |
| or pgm format). See the 'netpbm' package of utilities. | |
| Options: | |
| -n name, --var=name Output variable name for image data | |
| Also defines name_w and name_h for width/height | |
| Default: img | |
| Results in an array img[] and img_w img_h defined | |
| (They are not capitalized, but they are #defines) | |
| -f, --useflash Export defines and variable for alignment and use | |
| in PROGMEM (Arduino/ESP8266 use). | |
| -h, --help This help | |
| Examples: | |
| ppmto565 -n myimg someimage.ppm > someimage.cpp | |
| Outputs unsigned int myimg[] data, as well as defines | |
| myimg_w and myimg_h | |
| pngtopnm file.png | ppmto565 -f -n myimg someimage.ppm > someimage.cpp | |
| Same as above, but includes #defines, and modifies the declaration, | |
| for storage in the flash memory of the ESP8266. | |
| Example steps: | |
| 1. Run: ppmto565 -n myimg someimage.ppm > someimage.cpp | |
| 2. Copy the top lines, from the #include to the //extern variable | |
| declaration for myimg[], into your project's .c/.cpp file. | |
| 3. Remove // from the extern line (within your .c/.cpp file) | |
| EOT | |
| exit; | |
| } | |
| if ($#ARGV > -1) { | |
| my $fn = shift @ARGV; | |
| print STDERR "Using $fn\n"; | |
| open($f, "<", "$fn") || die "Can't open $fn: $!"; | |
| } else { | |
| $f = *STDIN; | |
| } | |
| $str = <$f>; | |
| die "Not ppm format" if $str !~ /^P6\s*$/; | |
| $str = <$f>; | |
| ($w,$h) = ($str =~ /^(\d+)\s+(\d+)\s*$/); | |
| die "Not ppm format (line 2)" if !defined $h; | |
| $str = <$f>; | |
| ($depth) = ($str =~ /^(\d+)\s*$/); | |
| die "Not ppm format (line 3)" if !defined $depth; | |
| #die "Color depth too deep for current board (depth = ($depth) is > 15)" | |
| # if $depth > 15; | |
| while (read($f, $r, 1) && read($f, $g, 1) && read($f, $b, 1)) { | |
| printf STDERR ("%d-%d-%d\n", ord $r, ord $g, ord $b) if $verbose>0; | |
| push(@pixels, [ord $r,ord $g,ord $b]); | |
| } | |
| die "Invalid pixel count. Num pixels (".scalar(@pixels).") != ${w}x{$h} (" . $w*$h . ")" | |
| if @pixels != $w*$h; | |
| print <<EOT; | |
| #include <pgmspace.h> | |
| //#define ALIGN __attribute__ (( aligned (__BIGGEST_ALIGNMENT__) )) | |
| #define ALIGN __attribute__ (( aligned ( sizeof(char*) ) )) | |
| #define INFLASH PROGMEM ALIGN | |
| EOT | |
| print "#define ${opt_varname}_w $w\n"; | |
| print "#define ${opt_varname}_h $h\n"; | |
| printf("//extern unsigned int ${opt_varname}[%d] INFLASH;\n", $w*$h); | |
| printf("unsigned int ${opt_varname}[%d] INFLASH = {\n", $w*$h); | |
| for my $y (0 .. $h-1) { | |
| print " "; | |
| for my $x (0 .. $w-1) { | |
| my $p = $pixels[$y*$w + $x]; | |
| $r = $p->[0]; | |
| $g = $p->[1]; | |
| $b = $p->[2]; | |
| #$r = 0; | |
| #$g = 0; | |
| #$b = 0; | |
| printf STDERR ("Converting %d %d %d at depth $depth ==> ", $r, $g, $b) | |
| if $verbose>0; | |
| my $int = int(($r/$depth)*31)<<11 | int(($g/$depth)*63)<<5 | int(($b/$depth)*31)<<0; | |
| printf STDERR ("$int -> 0x%x\n", $int) if $verbose>0; | |
| printf("0x%x", $int); | |
| #printf("0x%x%x%xF", ord($p->[0]), ord($p->[1]), ord($p->[2])); | |
| #printf("0x%x%x%x%x", 0, 0xF, 0, 0); | |
| if ($x != $w-1 || $y<$h-1) { print ", "; } | |
| } | |
| print "\n"; | |
| } | |
| print "};"; | |
| close $f; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/perl | |
| # Copyright (C) 2016, jaggz.h {who is at} gmail.com | |
| # If you look or use this code, any further than this and the following line, | |
| # you agree to all the terms and conditions outlined below in code. | |
| # Otherwise, it's free to use, but if you make money off it, you must submit | |
| # to me your first-born child.. nevermind. I don't want it. Go ahead | |
| # and use it (the code) however you wish; I wish you well in life. | |
| use strict; | |
| use warnings; | |
| my $fn; | |
| my $f; | |
| my ($r, $b, $g); | |
| my $str; | |
| my ($w,$h); | |
| my $depth; | |
| my @pixels; | |
| use Getopt::Long; | |
| my $opt_varname="img"; | |
| my $opt_help; | |
| my $verbose=0; | |
| GetOptions( | |
| "v|verbose+" => \$verbose, | |
| "n|var=s" => \$opt_varname, | |
| "h|help" => \$opt_help, | |
| ) or die("Error in command line arguments\n"); | |
| if ($opt_help) { | |
| print <<EOT; | |
| Usage: ppmto565 [options] [input] | |
| Generates a .C source file of RGB 16-bit data, suitable for use with many LCD | |
| displays. Modification might be necessary if your MCU or API/libraries can't | |
| make use of the unsigned int[] output. It also is customized for my ESP8266 | |
| use, with the Arduino IDE, where the INFLASH define, which you'll see in its | |
| output, places the image data in flash memory so as not to consume program | |
| space. Improvements are welcome <jaggz.h\@gmail.com> | |
| As its name states, it requires PPM input (magic P6 in the file); this means, | |
| if you're converting a greyscale or bw image with, say, pngtopnm, the output | |
| will likely be rejected by this program (because it'll probably be in pbm | |
| or pgm format). See the 'netpbm' package of utilities. | |
| Options: | |
| -n name, --var=name Output variable name for image data | |
| Also defines name_w and name_h for width/height | |
| Default: img | |
| Results in an array img[] and img_w img_h defined | |
| (They are not capitalized, but they are #defines) | |
| -f, --useflash Export defines and variable for alignment and use | |
| in PROGMEM (Arduino/ESP8266 use). | |
| -h, --help This help | |
| Examples: | |
| ppmto565 -n myimg someimage.ppm > someimage.cpp | |
| Outputs unsigned int myimg[] data, as well as defines | |
| myimg_w and myimg_h | |
| pngtopnm file.png | ppmto565 -f -n myimg someimage.ppm > someimage.cpp | |
| Same as above, but includes #defines, and modifies the declaration, | |
| for storage in the flash memory of the ESP8266. | |
| Example steps: | |
| 1. Run: ppmto565 -n myimg someimage.ppm > someimage.cpp | |
| 2. Copy the top lines, from the #include to the //extern variable | |
| declaration for myimg[], into your project's .c/.cpp file. | |
| 3. Remove // from the extern line (within your .c/.cpp file) | |
| EOT | |
| exit; | |
| } | |
| if ($#ARGV > -1) { | |
| my $fn = shift @ARGV; | |
| print STDERR "Using $fn\n"; | |
| open($f, "<", "$fn") || die "Can't open $fn: $!"; | |
| } else { | |
| $f = *STDIN; | |
| } | |
| $str = <$f>; | |
| die "Not ppm format" if $str !~ /^P6\s*$/; | |
| $str = <$f>; | |
| ($w,$h) = ($str =~ /^(\d+)\s+(\d+)\s*$/); | |
| die "Not ppm format (line 2)" if !defined $h; | |
| $str = <$f>; | |
| ($depth) = ($str =~ /^(\d+)\s*$/); | |
| die "Not ppm format (line 3)" if !defined $depth; | |
| #die "Color depth too deep for current board (depth = ($depth) is > 15)" | |
| # if $depth > 15; | |
| while (read($f, $r, 1) && read($f, $g, 1) && read($f, $b, 1)) { | |
| printf STDERR ("%d-%d-%d\n", ord $r, ord $g, ord $b) if $verbose>0; | |
| push(@pixels, [ord $r,ord $g,ord $b]); | |
| } | |
| die "Invalid pixel count. Num pixels (".scalar(@pixels).") != ${w}x{$h} (" . $w*$h . ")" | |
| if @pixels != $w*$h; | |
| print <<EOT; | |
| #include <pgmspace.h> | |
| //#define ALIGN __attribute__ (( aligned (__BIGGEST_ALIGNMENT__) )) | |
| #define ALIGN __attribute__ (( aligned ( sizeof(char*) ) )) | |
| #define INFLASH PROGMEM ALIGN | |
| EOT | |
| print "#define ${opt_varname}_w $w\n"; | |
| print "#define ${opt_varname}_h $h\n"; | |
| printf("//extern unsigned int ${opt_varname}[%d] INFLASH;\n", $w*$h); | |
| printf("unsigned int ${opt_varname}[%d] INFLASH = {\n", $w*$h); | |
| for my $y (0 .. $h-1) { | |
| print " "; | |
| for my $x (0 .. $w-1) { | |
| my $p = $pixels[$y*$w + $x]; | |
| $r = $p->[0]; | |
| $g = $p->[1]; | |
| $b = $p->[2]; | |
| #$r = 0; | |
| #$g = 0; | |
| #$b = 0; | |
| printf STDERR ("Converting %d %d %d at depth $depth ==> ", $r, $g, $b) | |
| if $verbose>0; | |
| my $int = int(($r/$depth)*31)<<11 | int(($g/$depth)*63)<<5 | int(($b/$depth)*31)<<0; | |
| printf STDERR ("$int -> 0x%x\n", $int) if $verbose>0; | |
| printf("0x%x", $int); | |
| #printf("0x%x%x%xF", ord($p->[0]), ord($p->[1]), ord($p->[2])); | |
| #printf("0x%x%x%x%x", 0, 0xF, 0, 0); | |
| if ($x != $w-1 || $y<$h-1) { print ", "; } | |
| } | |
| print "\n"; | |
| } | |
| print "};"; | |
| close $f; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment