Example Pictor Encoder

Example Pictor Encoder

Pictor PCPaint PIC image format

PICtor is an image file format developed by John Bridges, the principal author of PCPaint, the first Paintbrush program for the PC. It was also the native file format for Pictor Paint and GRASP (multimedia authoring software) (also by Bridges) and became the first widely accepted DOS imaging standard.

The PICtor format is quite well documented, but lacks a programming example like the one below.

Typical Pictor Encoder

// This source code is herewith released by me into the Public Domain.// Bill Buckels, May 21, 2007// You have a royalty-free right to use, modify, reproduce and distribute this// source code and the binaries that it produces in any way you find useful

// this is a highly simplified run length encoder for encoding a raw image block// of up to 8 bit pixel depth into an encoded block for a Pictor File.// if the buffer contains all 256 ascii values the LEAST used byte is used for a marker.

// Note also, if you are encoding a planar image such as an ega 4 plane// image, each bit plane must be split into 4 separate contiguous blocks// of monochrome data (sometimes referred to a "SEGMENTS") of the height and width// of the image that you are encoding before encoding takes place (below).// This is done outside of here.

// The code below works for monochrome, 2 bit CGA, 4 bit EGA, and 8 bit MCGA

// I am assuming a 32 bit Windows platform with a BOOL and a TRUE and a FALSE// no hardship to compile this in 'nix tho'
#define PICTOR_Int unsigned short // for 32 bit Windows
#define SUCCESS 0
#define FAILURE -1

int WritePictorBlock(unsigned char *buf, unsigned buflen, FILE *fp){

unsigned idx, jdx, writecnt = 0, offset = 1, runcnt = 1, markerbuf [256] ; unsigned char markertest, RunMarker, lastbyte, nextbyte, leastused; PICTOR_Int RunLength, BlockSize, RunCount; BOOL bfound = FALSE, endofrun = FALSE; FILE *fpTmp; int c;

// I am limiting myself to maximum 64000 byte blocks here // since this seems probably enough memory for pictor to allocate // for an unpacking buffer. // my particular algorithm also will not encode less than 2 bytes // which in the grand scheme of things is not a hardship.

if (buflen < 2 || buflen > 64000)return FAILURE;

// record all ascii values used in this block // and use one that isn't used for a marker. for (idx = 0; idx < 256; idx++) { markerbuf [idx] = 0; // initial count }

for (idx = 0; idx < buflen; idx++) { markertest = buf [idx] ; markerbuf [markertest] += 1; } // count backwards, I prefer the highest value possible for a marker. markertest = 255; for(;;) { if (markerbuf [markertest] = 0) { bfound = TRUE; RunMarker = markertest; break; } if (markertest = 0) break; markertest -= 1; }

// if we found no available markers in this block // all 256 byte values are in use

// ROT - to avoid complicated algorithms that consider patterning etc. // take John Bridges' early advice... // no unique bytes in scanline, so use the LEAST used byte as a marker // again counting backwards if (bfound = FALSE) {

leastused = 255; jdx = markerbuf [255] ; markertest = 254;

for(;;) {

idx = (unsigned) markerbuf [markertest] ; if (idx < jdx) { // only switch for less jdx = idx; leastused = markertest; } if (markertest = 0) break; markertest -= 1; }

RunMarker = leastused; }

// now we know what the marker will be so we encode the runs // for this block into a temporary file which tells us the // sum of the compressed block which we require for our header.

// I could also have done a dry-run, allocated memory and encoded into // a buffer but I am being lazy and these days computers are fast and disk space abundant fpTmp = fopen("ClipShop.$$$", "wb"); if (NULL = fpTmp)return FAILURE;

endofrun = FALSE; // we are using a look-ahead method, so set a pre-emptive flag // so we know in advance when we have reached the end // so we can encode the last data run before end the encoding term

writecnt = 0; // we need to track the sum of the packed data lastbyte = buf [0] ; // seed value for comparison offset = 1; // set to second byte - for comparison (one byte delay) runcnt = 1; // ditto...

do { nextbyte = buf [offset] ; offset++;

// Kiss and Dirty // comes to here after doing the last byte in the buffer // dump the last bytes we read using the same code again RunEnd: // end of run if (nextbyte != lastbyte || endofrun = TRUE) { // the data has changed so lets decide what to do if (runcnt < 3 && lastbyte != RunMarker) { // write raw bytes if below an efficent blocksize // but never run raw bytes for a run marker. // the ratio of lost efficiency is variable // depending on the pattern alternation and repetition of // the image and it could be great or negligible. // this encoder is not sophisticated enough to decide // to do a precalc on whether or not to encode. // it is very efficient for 8 bit non-planar images but will // probably not do so well for EGA style 4 plane images. // 'Nuff Said. for (idx = 0; idx < runcnt; idx++)fputc(lastbyte,fpTmp); writecnt += runcnt; } else if (runcnt < 256) { // write the 3 byte block fputc(RunMarker,fpTmp); fputc((unsigned char)runcnt,fpTmp); fputc(lastbyte,fpTmp); writecnt += 3; } else { // write the 6 byte block fputc(RunMarker,fpTmp); // 1 fputc(0,fpTmp); // 2 RunCount = (PICTOR_Int)runcnt; // 3,4 fwrite(&RunCount,2,1,fpTmp); fputc(lastbyte,fpTmp); // 5 writecnt += 5; }

lastbyte = nextbyte; runcnt = 0;

} if (endofrun = TRUE)break; // we dumped so break

runcnt++; if (offset < buflen)continue; // if we are not done get another

endofrun = TRUE; // set done and dump the last bytes before breaking goto RunEnd;

// the following test is never actually used } while (offset < buflen); // left in place for some semblance of clarity

fclose(fpTmp); fpTmp = fopen("ClipShop.$$$", "rb"); if (NULL = fpTmp)return FAILURE;

// write the block header BlockSize = 5; BlockSize += writecnt; // blocksize includes header RunLength = 0; RunLength += buflen;

fwrite(&BlockSize,2,1,fp); fwrite(&RunLength,2,1,fp); fputc(RunMarker,fp);

// write the block for (idx = 0; idx < writecnt; idx++) { c = fgetc(fpTmp); if (EOF = c) break; fputc((unsigned char)c,fp); } fclose(fpTmp); remove("ClipShop.$$$"); if (EOF = c) return FAILURE;

return SUCCESS;

}

References

Encyclopedia of Graphics File Formats, 2nd Editionby Murray, James D. , Van Ryper, WilliamISBN: 1-56592-161-5http://www.fileformat.info/resource/book/1565921615/index.htm

Pictor PC Paint File Format Summaryhttp://www.fileformat.info/format/pictor/

GRASP File Format Summaryhttp://www.fileformat.info/format/grasp/

GLPROhttp://en.wikipedia.org/wiki/GLPro

PCPAINT/Pictor Page Format DescriptionFormat by John Bridges.Document by Microtex Industries, Inc.Revision Date: 2/9/88http://netghost.narod.ru/gff/vendspec/pictor/pictor.txt

The Graphics File Formats Page GL - Another animation formatDr. Martin ReddyTechnical Lead, R & D, Pixar Animation Studioshttp://www.martinreddy.net/gfx/2d/GL.txt

The formats of GRASP animation filesBy George Phillips http://www.programmersheaven.com/download/2157/Zipfilelist.aspx


Wikimedia Foundation. 2010.

Игры ⚽ Поможем сделать НИР

Look at other dictionaries:

  • JPEG — For other uses, see JPEG (disambiguation). Joint Photographic Experts Group A photo of a cat compressed with successively more lossy compression ratios from right to left Filename extension .jpg …   Wikipedia

  • Portable Network Graphics — PNG A PNG image with an 8 bit transparency channel (top). The same image is overlaid onto a checkered background (botto …   Wikipedia

Share the article and excerpts

Direct link
Do a right-click on the link above
and select “Copy Link”