Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??
#!/usr/bin/perl =head1 NAME art2bmp - Converts "VGA Art Studio files" to BMP =head1 SYNOPSIS B<art2bmp.pl> I<file.art> =head1 DESCRIPTION Converts "VGA Art Studio" (1991) files to BMP files. Not to be confuse +d with the numerous other formats using the ".art" extension. If you have a .art +file, it's almost certainly a different format. Does not handle any mask data if present. =head1 AUTHOR Lee Pumphret =cut use strict; use warnings; my @files = glob(shift @ARGV); foreach my $file (@files) { next and warn "Mismatched extension in filename [$file]... skippin +g\n" unless $file=~/\.art$/i; print "processing $file...\n"; open( IN, "<$file" ) or die "Couldn't open $file :$!"; binmode(IN); my $buffer; my $ART_HEADER_SIZE = 8; # .art file header size # Read the header ( read( IN, $buffer, $ART_HEADER_SIZE ) == $ART_HEADER_SIZE ) or die "Error reading header data!"; my ( $ident, $mask, $x, $y, $im_compressed, $mask_compressed, ) = unpack( "CCssCC", $buffer ); unless ( $ident == 123 ) { die "Doesn't look like an ART file! [$ident]"; } # Read the palette data (rgb triplets) my @pal; for ( 0 .. 255 ) { read( IN, $buffer, 3 ) == 3 or die "Error reading palette!"; my @rgb = unpack( "CCC", $buffer ); push @pal, pack( "CCC", reverse @rgb ); } # Read image data my @imdata; my $pixel_count = 0; if ($im_compressed) { warn "Decompressing image [$x x $y]....\n"; while ( $pixel_count < $x * $y ) { read( IN, $buffer, 1 ) == 1 or die "Couldn't read! (have $pixel_count pixels $#imdat +a) $!"; my $byte = unpack( "C", $buffer ); if ( $byte < 128 ) { $imdata[ $pixel_count++ ] = $pal[$byte]; } else { # It's RLE my $repeat = $byte - 128; read( IN, $buffer, 1 ) == 1 or die "Couldn't read! :$! +"; $byte = unpack( "C", $buffer ); push @imdata, ( $pal[$byte] ) x ( $repeat + 1 ); $pixel_count += $repeat + 1; } } } else { warn "$file is Uncompressed!"; read( IN, $buffer, $x * $y ) == $x * $y or die "Short read on +$file"; @imdata = map { $pal[$_] } unpack( "C*", $buffer ); } if ($mask){ warn "Image has mask data, ignoring..."; } # Write out the bmp file ( my $outfile = $file ) =~ s/art$/bmp/i; my $written = $#imdata; open( OUT, ">$outfile" ) or die "Couldn't open output!"; binmode(OUT); # BMP 3.1 Header print OUT pack "C C l a a a a l l l l s s l l l l l l", 0x42, 0x4D +, 54 + ( $x * 3 ) * $y, 'l', 'e', 'e', 'p', 54, 0x28, $x, $y, 1, 2 +4, 0, 0, 0, 0, 0, 0; # Write out the image data, bottom to top while ( $written > 0 ) { print OUT @imdata[ $written - ( $x - 1 ) .. $written ]; $written -= $x; } close OUT; } __END__ A snippet of documentation from "VGA Art Studio" * Note, there were some typos, errors in the doc which I have correcte +d. Appendix A: VGA Art Studio .ART and .PAL file formats ========================================================= The .ART file ------------- All VGA Art Studio picture/cutout files are stored in this format. In +fact, there is no distinction between a picture or a cutout - a picture can +be pasted in as a cutting, and a cutting can be loaded in as a file. There are essentially two image formats - compressed and uncompressed. + Before saving a file, VGA Art Studio works out which format will actually res +ult in a smaller file, and then saves the file in this format. Actually, it is +not quite as simple as that - each image may need a 'mask', and whether or not +they the mask is compressed is independent of whether or not the picture itself + is compressed. However, the file format is still relatively easy to use, +and is as follows : +----------+-----------------------------------------------------+---- +---+ | Offset | Description | Byt +es | +----------+-----------------------------------------------------+---- +---+ | 0 | 123 dec. (acts as a file identifier) | 1 + | | 1 | Mask included? (1=yes, 0=no) | 1 + | | 2 | Size (x) in pixels of the image - INTEL format | 2 + | | 4 | Size (y) in pixels of the image - INTEL format | 2 + | | 6 | Image data compressed? (1=yes, 0=no) | 1 + | | 7 | Mask data compressed ? (1=yes, 0=no) | 1 + | | 8 | Palette data - 256 x (R,G,B) triplets, with | 76 +8 | | | individual intensities from 0..255 | + | | 776 | Image data (may be compressed) | ?? +? | | ??? | (optional) Mask data (may be compressed) | ?? +? | +----------------------------------------------------------------+---- +---+ As mentioned, both the image data and the mask data may be compressed +depending on the values in bytes 6 and 7 of the header. The two formats are the +same for both the mask and the image, and work as follows: The data in its uncompressed form consists of 64000 bytes, in a straig +ht forward raster format - with 1 byte per pixel - (acting as an index in +to the palette in the case of image data - in the case of mask data, a non-ze +ro value indicates that the corresponding image pixel IS to be displayed). The +bytes are stored row by row, with each row running from left to right, in standa +rd raster format. In the compressed format, the algorithm for uncompressing the data run +s as follows : +-----------------------------+ | Read the next byte of data | | from the file, (unless we |<-------------------------------------- +-----+ | now have data for 64000 | + | | pixels, in which case stop).| + | +-----------------------------+ + | | | \ / | +--------------------+ Y +---------------------------------- ++ | | Is the byte <128 ? |--------->| Use this byte for the next pixel +|----+ +--------------------+ +---------------------------------- ++ ^ | N | \ / | +--------------------------------------------------------------------+ + | | Subtract 128 from the value of the byte - call this C. Then read | + | | the next byte - this gives you the colour of the next (C+1) | +-----+ | pixels. | +--------------------------------------------------------------------+ Note: Compressed data is stored a line at a time. Compression using a byte > +128 as a repeat count MUST NOT wrap round from one line to the beginning of the + next. The .PAL file ------------- This is very very straightforward. Each file is 769 bytes long, and co +nsists of the following data: +----------+-----------------------------------------------------+---- +---+ | Offset | Description | Byt +es | +----------+-----------------------------------------------------+---- +---+ | 0 | 124 dec. (acts as a file identifier) | 1 + | | 1 | Palette data - 256 x (R,G,B) triplets, with | 76 +8 | | | individual intensities from 0..255 | + | +----------------------------------------------------------------+---- +---+ ---------------------------------------------------------------------- +------ Appendix D : About Mooose Software ================================== "Founded" in 1990 by : Ben Stragnell Graham Sanderson Samer Abdallah \ \ / \/ ___// + \_ / // \] //~~~ + \\ ]] // // + \__\ _]_\_ _\\ __/\// + __ _____\ /_\// _ + __ _/ \/~~~~~~\/ \__ // + _/ ] ] \/ + /] / \ ] + / ](0 0)] + / ] ] + ____________~ ] ] + \ < > / / \______/ + ] ] + ] + ] + The moose is without doubt one of the finest animals ever invented, it +s majestic antlers towering skyward, as it stands proudly, one of Nature +'s most cunning creations. It's also got a really cool name, and you can +put an extra 'o' in it, to make it last just that little bit longer. Oh ye +s. Keep an eye out for more releases from Mooose Software, and please sup +port the Public Domain!

In reply to art2bmp by shotgunefx

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (4)
As of 2024-04-25 14:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found