OpenCores
URL https://opencores.org/ocsvn/395_vgs/395_vgs/trunk

Subversion Repositories 395_vgs

[/] [395_vgs/] [trunk/] [devkit/] [img2xes/] [img2xes.pl] - Blame information for rev 32

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 8 zuofu
#
2
# img2xes - Convert various types of image files into an XES-formatted hexadecimal data file
3
#
4
# The man page for this program is stored at the end of this file in POD format.
5
# Use 'pod2text img2xes.pl' in order to generate the man page.
6
#
7
 
8
 
9
 
10
use Math::Complex;
11
use Getopt::Long;
12
 
13
#
14
# create pointers to the netpbm image translation programs
15
#
16
# $netpbm_bin_dir = "C:/progra~1/gnuwin32/bin/"; # set this to the location of the netpbm utilities if it's not in your path already
17
$bmptopnm = $netpbm_bin_dir . "bmptopnm.exe";
18
$pngtopnm = $netpbm_bin_dir . "pngtopnm.exe";
19
$giftopnm = $netpbm_bin_dir . "giftopnm.exe";
20
$tifftopnm = $netpbm_bin_dir . "tifftopnm.exe";
21
$jpegtopnm = $netpbm_bin_dir . "jpegtopnm.exe";
22
 
23
#
24
# get options for the program
25
#
26
GetOptions(
27
    "help"         => \$help,
28
    "width=i"      => \$screen_width,       # width of screen in pixels
29
    "x=i"          => \$screen_width,       # also width of screen
30
    "height=i"     => \$screen_height,      # height of screen in scanlines
31
    "y=i"          => \$screen_height,      # also height of screen
32
    "depth=s"      => \$screen_depth,       # #bits of each RGB component
33
    "pixelwidth=i" => \$pixel_width,        # #bits per pixel
34
    "memwidth=i"   => \$mem_width,          # #bits per word of memory
35
    "address=s"    => \$mem_start_address,  # starting address of image in memory
36
    "ifile=s"      => \$in_file,            # input image file
37
    "ofile=s"      => \$xes_file            # output hex file in XES format
38
);
39
 
40
# convert the hex or octal starting address to a decimal integer
41
$mem_start_address = oct($mem_start_address);
42
 
43
print "Unknown options:\n" if $ARGV[0];
44
foreach (@ARGV) {
45
    print "$_\n";
46
}
47
 
48
if ( $ARGV[0] || $help ) {
49
    print "perl $0 [-help] [(-width|-x) <#pixels>] [(-height|-y) <#lines>] [-depth <#R>+<#G>+<#B>] [-pixelwidth <#bits>] [-memwidth <#bits>] [-address <hex_or_oct_address>] [-ifile <file.pnm>] [-ofile <file.xes>]\n";
50
    die;
51
}
52
 
53
#
54
# set default parameter values if not already set by the program options
55
#
56
!$screen_width      && ( $screen_width      = 800 );
57
!$screen_height     && ( $screen_height     = 600 );
58
!$screen_depth      && ( $screen_depth      = "3+2+3" );
59
!$pixel_width       && ( $pixel_width       = 8 );
60
!$mem_width         && ( $mem_width         = 16 );
61
!$mem_start_address && ( $mem_start_address = 0 );
62
 
63
$pixel_width > $mem_width && die "Error: pixel width cannot exceed the memory width!\n";
64
($num_r_bits,$num_g_bits,$num_b_bits) = split(/\+/,$screen_depth);
65
$color_depth = $num_r_bits + $num_g_bits + $num_b_bits;
66
$pixel_width < $color_depth && die "Error: pixel width is too small to hold the RGB values!\n";
67
 
68
#
69
# open the file containing the image data or run the external program to convert the
70
# image file into a portable pixel map file (PGM, PPM or PNM)
71
#
72
if ( defined $in_file ) {
73
    if($in_file =~ /\.(\w+)$/) {
74
        $_ = $1;
75
        /^bmp/i && (open(IN,"$bmptopnm $in_file |") || die "$!\n");
76
        /^png/i && (open(IN,"$pngtopnm $in_file |") || die "$!\n");
77
        /^gif/i && (open(IN,"$giftopnm $in_file |") || die "$!\n");
78
        /^tif/i && (open(IN,"$tifftopnm $in_file |") || die "$!\n");
79
        /^jpeg/i && (open(IN,"$jpegtopnm $in_file |") || die "$!\n");
80
        /^jpg/i && (open(IN,"$jpegtopnm $in_file |") || die "$!\n");
81
        /^pnm/i && (open( IN, "$in_file" ) || die "$!\n");
82
        /^ppm/i && (open( IN, "$in_file" ) || die "$!\n");
83
        /^pgm/i && (open( IN, "$in_file" ) || die "$!\n");
84
    }
85
}
86
else {
87
    open( IN, "-" ) || die "$!\n";    # open the standard input if there is no file specified
88
}
89
binmode(IN);
90
 
91
#
92
# open the file where the hexadecimal data will be stored
93
#
94
if ( defined $xes_file ) {
95
    open( OUT, ">$xes_file" ) || die "$!\n";
96
}
97
else {
98
    open( OUT, ">-" ) || die "$!\n";    # open the standard output if there is no file specified
99
}
100
 
101
#
102
# read the header that gives the image type, dimensions and grayscale/color range
103
#
104
while (<IN>) {
105
    /^\s*#/ && next;    # skip comment lines
106
    $_ =~ s/\s*#.*$//;  # strip comments from the ends of lines
107
    chomp;              # remove newlines from ends of lines
108
    $header .= "$_ ";   # append current field to the header information
109
    @header = split( /\s+/, $header );
110
    ( $header[0] =~ /^P[2356]$/ ) && ( @header == 4 ) && last;    # got all the header information for PGM and PPM files
111
    ( $header[0] =~ /^P[14]$/ )   && ( @header == 3 ) && last;    # got all the header information for PBM files
112
    ( $header[0] !~ /^P[123456]$/ ) && die "unknown type of PNM file!!\n";
113
    ( @header < 4 )                 && next;                                 # keep going until we have all the info from the header
114
}
115
 
116
#
117
# get the dimensions of the image and the range of each pixel value
118
#
119
$image_width  = $header[1];
120
$image_height = $header[2];
121
( $header[0] =~ /^P[2356]$/ ) && ( $num_img_pixel_bits = int( logn( $header[3] + 1, 2 ) ) );
122
 
123
#
124
# determine some characteristics of the image data
125
#
126
$is_bitmap = ( $header[0] =~ /P[14]/ );                                      # is it a bitmap, graymap or pixelmap?
127
$is_text   = ( $header[0] =~ /P[123]/ );                                     # is the data stored as ASCII text or binary values?
128
$is_color  = ( $header[0] =~ /P[36]/ );                                      # is the data RGB or grayscale/BW?
129
 
130
#
131
# process pixelmap and graymap image data
132
#
133
if ( !$is_bitmap ) {
134
    $address = $mem_start_address;                                           # initialize address pointer
135
 
136
    # create hexadecimal data records of pixel data for each line of the screen
137
    for ( $r = 0 ; $r < $screen_height ; $r++ ) {
138
 
139
        # clear the RGB values for the pixels in this row of the image
140
        @row_r = ();
141
        @row_g = ();
142
        @row_b = ();
143
 
144
        #
145
        # Read the current line of pixel data from the image file until all the lines are processed.
146
        # Once all image lines are processed, the RGB arrays for any further screen lines will be left with
147
        # all zeroes (blank pixels).  If there are more image lines than screen lines, then the excess
148
        # image lines will be ignored.
149
        #
150
 
151
        for ( $c = 0 ; $r < $image_height && $c < $image_width ; $c++ ) {
152
            if ($is_color) {
153
 
154
                # read RGB values for the current pixel
155
                if ($is_text) {
156
 
157
                    # RGB values are stored as decimal number text strings
158
                    # if the data array is empty, then refill it with data from lines of the image data file
159
                    while(@data == 0){
160
                      $t = <IN>; # get a line from the file
161
                      $t =~ s/^\s+//; # strip off leading whitespace
162
                      $t =~ s/\s+$//; # strip off trailing whitespace
163
                      @data = split(/\s+/,$t); # split the rest into individual numbers and store them in the array
164
                    }
165
                    $row_r[$c] = shift @data; # extract next number from array and store it in the current pixel's red component
166
 
167
                    # now get the value of the green component
168
                    while(@data == 0){
169
                      $t = <IN>;
170
                      $t =~ s/^\s+//;
171
                      $t =~ s/\s+$//;
172
                      @data = split(/\s+/,$t);
173
                    }
174
                    $row_g[$c] = shift @data;
175
 
176
                    # finally, get the value of the blue component
177
                    while(@data == 0){
178
                      $t = <IN>;
179
                      $t =~ s/^\s+//;
180
                      $t =~ s/\s+$//;
181
                      @data = split(/\s+/,$t);
182
                    }
183
                    $row_b[$c] = shift @data;
184
                }
185
                else {
186
 
187
                    # RGB values are stored as bytes of binary data
188
                    read( IN, $t, 1 );
189
                    $row_r[$c] = ord($t); # store the value of the red component for this pixel
190
                    read( IN, $t, 1 );
191
                    $row_g[$c] = ord($t); # store the value of the green component
192
                    read( IN, $t, 1 );
193
                    $row_b[$c] = ord($t); # store the value of the blue component
194
                }
195
            }
196
            else {
197
 
198
                # read gray value for the current pixel
199
                if ($is_text) {
200
 
201
                    # gray value is stored as a decimal number text string
202
                    # if the data array is empty, then refill it with data from lines of the image data file
203
                    while(@data == 0){
204
                      $t = <IN>; # get a line from the file
205
                      $t =~ s/^\s+//; # strip off leading whitespace
206
                      $t =~ s/\s+$//; # strip off trailing whitespace
207
                      @data = split(/\s+/,$t); # split the rest into individual numbers and store them in the array
208
                    }
209
                    $row_r[$c] = shift @data; # extract next number from array and store it in the current pixel's red component
210
                }
211
                else {
212
 
213
                    # gray value is stored as a byte of binary data
214
                    read( IN, $t, 1 );
215
                    $row_r[$c] = ord($t); # store the value of the red component for this pixel
216
                }
217
 
218
                # gray value is created by making the green and blue components identical to the red component
219
                $row_g[$c] = $row_r[$c];
220
                $row_b[$c] = $row_r[$c];
221
            }
222
 
223
            # scale the RGB components of each image pixel so they fit the color depth of the screen
224
            $row_r[$c] = ( $row_r[$c] >> ( $num_img_pixel_bits - $num_r_bits ) ) & ( ( 1 << $num_r_bits ) - 1 );
225
            $row_g[$c] = ( $row_g[$c] >> ( $num_img_pixel_bits - $num_g_bits ) ) & ( ( 1 << $num_g_bits ) - 1 );
226
            $row_b[$c] = ( $row_b[$c] >> ( $num_img_pixel_bits - $num_b_bits ) ) & ( ( 1 << $num_b_bits ) - 1 );
227
        }
228
 
229
        #
230
        # Now create the hex records in XES hex format for the current row of pixel RGB data.
231
        # Read the pixel RGB values from the current line of image data until all the pixels are processed.
232
        # Once all image pixels are processed, the RGB values for any further screen pixels will be read as
233
        # all zeroes (blank pixels).  But if there are more image pixels than screen pixels, then the excess
234
        # image pixelss will be ignored.
235
        #
236
 
237
        $hex_record = ""; # start with an empty hex record
238
        $nbytes = 0; # number of bytes of data in the hex record
239
        $mem_word = 0; # current word to be stored in memory (composed of packed pixels)
240
        $npixels = 0; # number of pixels packed into a word of memory
241
        for ( $c = 0 ; $c < $screen_width ; $c++ ) {
242
 
243
            # pack the RGB components for the current pixel into a single pixel value with red, green, blue
244
            # data arranged from the most to least significant bit
245
            $pixel_value = ( $row_r[$c] << ($num_g_bits+$num_b_bits) ) | ( $row_g[$c] << $num_b_bits ) | $row_b[$c];
246
 
247
            # pack the pixel value into the memory word
248
            $mem_word = $mem_word | ( $pixel_value << ( $pixel_width * $npixels ) );
249
            $npixels++;    # increment the number of pixels currently stored in the memory word
250
 
251
            # if the memory word is full, then append it to the hex record
252
            if ( $pixel_width * $npixels >= $mem_width ) {
253
 
254
                # divide the memory word into bytes, starting with the least-significant, and append them
255
                # into a string that proceeds from the most-to-least significant
256
                for ( $hex = "", $w = 0 ; $w < $mem_width ; $w += 8 ) {
257
                    $hex = sprintf( " %02X%s", $mem_word & 0xFF, $hex );    # put the current byte at the head of the string
258
                    $mem_word = $mem_word >> 8;                             # shift the current byte off the end of the memory word
259
                    $nbytes++;                                              # increment the number of bytes stored in the hex record
260
                }
261
                $hex_record .= $hex;                                        # append the hex data for the current memory word to the hex record
262
                $npixels = 0;                                               # all pixels were removed from the memory word
263
                $mem_word = 0;
264
 
265
                # create a complete hex record if enough bytes have been appended
266
                if ( $nbytes >= 16 || (($address+$nbytes) & 0xF)==0 ) {
267
                    printf OUT "+ %02X %08X%s\n", $nbytes, $address, $hex_record; # prepend record length and address
268
                    $address += $nbytes;                                        # compute the address for the next hex record
269
                    $hex_record = "";                                           # clear the string for the next hex record
270
                    $nbytes     = 0;                                            # no bytes in the new hex record
271
                }
272
            }
273
        }
274
 
275
        # take care of any partial memory words that were in-process at the end of the line
276
        if ( $npixels > 0 ) {
277
 
278
            # divide the memory word into bytes, starting with the least-significant, and append them
279
            # into a string that proceeds from the most-to-least significant
280
            for ( $hex = "", $w = 0 ; $w < $mem_width ; $w += 8 ) {
281
                $hex = sprintf( " %02X%s", $mem_word & 0xFF, $hex );
282
                $mem_word = $mem_word >> 8;
283
                $nbytes++;
284
            }
285
            $hex_record .= $hex;
286
            $npixels = 0;
287
        }
288
 
289
        # take care of any partial hex records that were in process at the end of a line
290
        if ( $nbytes > 0 ) {
291
            printf OUT "+ %02X %08X%s\n", $nbytes, $address, $hex_record;
292
            $address += $nbytes;
293
            $hex_record = "";
294
            $nbytes     = 0;
295
        }
296
    }
297
}
298
 
299
 
300
 
301
 
302
=pod
303
 
304
 
305
=head1 NAME
306
 
307
img2xes - Convert various types of image files into an XES-formatted hexadecimal data file
308
 
309
 
310
=head1 SYNOPSIS
311
 
312
perl img2xes.pl [B<-width>=I<integer>]  [B<-x>=I<integer>]
313
[B<-height>=I<integer>]  [B<-y>=I<integer>]
314
[B<-depth>=I<string>] [B<-pixelwidth>=I<number>] [B<-memwidth>=I<number>]
315
[B<-address>=I<integer>] [B<-ifile>=I<filename>] [B<-ofile>=I<filename>]
316
 
317
perl img2xes.pl B<-help>
318
 
319
 
320
=head1 DESCRIPTION
321
 
322
B<img2xes> converts image files into hexadecimal data files in the XES format.
323
These hex files can be downloaded into the memory on an XS Board and displayed
324
on a VGA monitor.
325
 
326
 
327
=head1 OPTIONS
328
 
329
=over 4
330
 
331
=item B<-width> I<integer>
332
 
333
Sets width of the image (in pixels) that will be displayed on the VGA monitor.  This is not necessarily
334
the same as the width of the image in the image file.  The default value is 800.
335
 
336
=item B<-x> I<integer>
337
 
338
Same as the B<-width> option.
339
 
340
=item B<-height> I<integer>
341
 
342
Sets height of the image (in scanlines) that will be displayed on the VGA monitor.  This is not necessarily
343
the same as the height of the image in the image file.  The default value is 600.
344
 
345
=item B<-y> I<integer>
346
 
347
Same as the B<-height> option.
348
 
349
=item B<-depth> I<string>
350
 
351
Sets the depth of the image that will be displayed on the VGA monitor.  This is not necessarily
352
the same as the depth of the image in the image file.  The depth is expressed as a string with the
353
format I<R+G+B> where R, G and B are the number of bits of resolution of the red, green and blue
354
components of the colors displayed on the monitor.  The default value is 3+2+3.
355
 
356
=item B<-pixelwidth> I<integer>
357
 
358
Sets the width (in bits) of a pixel.  A pixel should be at least R+G+B bits wide.  The default value is 8.
359
 
360
=item B<-memwidth> I<integer>
361
 
362
Sets the width (in bits) of the memory word that contains one or more pixels.  The memory width should be
363
at least as wide as the pixels.  The default value is 16.
364
 
365
=item B<-address> I<hex or octal address>
366
 
367
Sets the starting address in memory for the hexadecimal image data.  The image data proceeds upward from there.
368
The address is interpreted as an octal number unless you precede it with an initial "0x" to indicate
369
it is a hexadecimal address.  The default value is 0.
370
 
371
=item B<-ifile> I<filename>
372
 
373
Gives the name of the file containing the image data.  The suffix of I<filename> is used to determine the
374
type of the image data as follows:
375
 
376
=over
377
 
378
=item B<.bmp> Windows bitmap file.
379
 
380
=item B<.png> PNG file.
381
 
382
=item B<.gif> GIF file.
383
 
384
=item B<.tif> TIF file.
385
 
386
=item B<.jpeg>, B<.jpg> JPEG file.
387
 
388
=item B<.pgm> Portable gray-map file.
389
 
390
=item B<.ppm> Portable pixel-map file.
391
 
392
=item B<.pnm> Portable any-map file.
393
 
394
=back
395
 
396
If B<-ifile> is not used, then the image data is read from the standard input and is assumed to be in
397
portable any-map format.
398
 
399
=item B<-ofile> I<filename>
400
 
401
Gives the name of the file where the XES-formatted hexadecimal data will be stored.  If B<-ofile> is not used,
402
then the hexadecimal data is written to the standard output.
403
 
404
=back
405
 
406
 
407
=head1 DIAGNOSTICS
408
 
409
B<img2xes> will abort if it does not recognize the suffix of the input image file or if the following
410
contraint is not met:
411
 
412
=over
413
 
414
R+G+B <= pixel width <= memory width
415
 
416
=back
417
 
418
 
419
=head1 EXAMPLES
420
 
421
For the XSA Boards using the VGA generator circuit described in
422
http://www.xess.com/appnotes/an-101204-vgagen.pdf, here are the commands to convert a JPEG file
423
and produce an S<800 x 600> display with
424
pixel widths of 4, 8 and 16.  (We will not explicitly set some options since the default settings
425
will work in this case)
426
 
427
=over
428
 
429
perl img2xes.pl -depth 1+1+1 -pixelwidth 4 -ifile image.jpg -ofile image.xes
430
 
431
perl img2xes.pl -depth 3+2+3 -pixelwidth 8 -ifile image.jpg -ofile image.xes
432
 
433
perl img2xes.pl -depth 3+3+3 -pixelwidth 16 -ifile image.jpg -ofile image.xes
434
 
435
=back
436
 
437
To display a PNG file on a S<1024 x 768> display, then do this:
438
 
439
=over
440
 
441
perl img2xes.pl -x 1024 -y 768 -depth 1+1+1 -pixelwidth 4 -ifile image.png -ofile image.xes
442
 
443
perl img2xes.pl -x 1024 -y 768 -depth 3+2+3 -pixelwidth 8 -ifile image.png -ofile image.xes
444
 
445
perl img2xes.pl -x 1024 -y 768 -depth 3+3+3 -pixelwidth 16 -ifile image.png -ofile image.xes
446
 
447
=back
448
 
449
 
450
=head1 ENVIRONMENT
451
 
452
B<img2xes> requires a perl interpreter for its execution.  You can get a free perl interpreter
453
for Windows at www.activestate.com.  You already have a perl interpreter if you are running
454
linux, solaris or unix.
455
 
456
B<img2xes> requires the I<netpbm> suite of image conversion programs in order to convert
457
the various image file formats.
458
You can get these from http://netpbm.sourceforge.net.
459
Once installed, you need to place the I<netpbm> directory in your path or store
460
it directly in the C<$netpbm_bin_dir> variable in F<img2xes.pl>.
461
 
462
 
463
=head1 FILES
464
 
465
None.
466
 
467
 
468
=head1 CAVEATS
469
 
470
None.
471
 
472
 
473
=head1 BUGS
474
 
475
Portable bitmap files (.pbm) are not handled, yet.
476
 
477
 
478
=head1 RESTRICTIONS
479
 
480
None.
481
 
482
 
483
=head1 NOTES
484
 
485
B<img2xes> takes the red, green and blue component values of each pixel in the image file and
486
does the following:
487
 
488
=over
489
 
490
=item 1.
491
 
492
Each color component is truncated to the number of bits specified for that component by the B<-depth> option.
493
 
494
=item 2.
495
 
496
The truncated color components are concatenated with the blue component in the least-significant bit positions,
497
the red component in the most-significant bit positions, and the green component in between.
498
 
499
=item 3.
500
 
501
The concatenated components are placed into the least-significant bit positions of a pixel field whose
502
width is set using the B<-pixelwidth> option.  Any unused bits in the upper portion of the pixel field
503
are set to zero.
504
 
505
=item 4.
506
 
507
Pixel fields are concatenated until no more will fit into a memory word whose width is set using the
508
B<-memwidth> option.  Pixel I<N> occupies the least-significant bit positions while
509
pixels I<N+1>, I<N+2>, ... occupy successively more-significant bit positions in the memory word.
510
 
511
=item 5.
512
 
513
The memory word is chopped into eight-bit bytes and output as two-digit hexadecimal values starting
514
with the most-significant byte and proceeding to the least-significant byte.
515
 
516
=back
517
 
518
 
519
=head1 SEE ALSO
520
 
521
The most-current version of B<img2xes.pl> can be found at http://wwww.xess.com/ho07000.html.
522
 
523
 
524
=head1 AUTHOR
525
 
526
Dave Vanden Bout, X Engineering Software Systems Corp.
527
 
528
Send bug reports to bugs@xess.com.
529
 
530
 
531
=head1 COPYRIGHT AND LICENSE
532
 
533
Copyright 2004 by X Engineering Software Systems Corporation.
534
 
535
This library is free software; you may redistribute it and/or modify
536
it under the same terms as Perl itself.
537
 
538
 
539
=head1 HISTORY
540
 
541
10/12/04 - Version 1.0
542
 
543
 
544
=cut
545
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.