/** ** $Header: /roq/libim/immpnt.c 1 11/02/99 4:38p Zaphod $ ** Copyright (c) 1989-1995 San Diego Supercomputer Center (SDSC) ** a division of General Atomics, San Diego, California, USA ** ** Users and possessors of this source code are hereby granted a ** nonexclusive, royalty-free copyright and design patent license to ** use this code in individual software. License is not granted for ** commercial resale, in whole or in part, without prior written ** permission from SDSC. This source is provided "AS IS" without express ** or implied warranty of any kind. ** ** For further information contact: ** E-Mail: info@sds.sdsc.edu ** ** Surface Mail: Information Center ** San Diego Supercomputer Center ** P.O. Box 85608 ** San Diego, CA 92138-5608 ** (619) 534-5000 **/ #define HEADER " $Header: /roq/libim/immpnt.c 1 11/02/99 4:38p Zaphod $" /** ** FILE ** immpnt.c - Apple Macintosh MacPaint image file I/O ** ** PROJECT ** libim - SDSC image manipulation library ** ** DESCRIPTION ** immpnt.c contains routines to read and write Apple Macintosh ** MacPaint files for the image manipulation library. Raster data ** read in is stored in a VFB. Raster data written out is taken ** from a tag table. ** ** PUBLIC CONTENTS ** d =defined constant ** f =function ** m =defined macro ** t =typedef/struct/union ** v =variable ** ? =other ** ** none ** ** PRIVATE CONTENTS ** imMpntRead f read an Apple Macintosh MacPaint file ** imMpntWrite f write an Apple Macintosh MacPaint file ** ** IMtstBit m Test an unsigned bit value ** IMsetBit m Set an unsigned bit value ** ** HISTORY ** $Log: /roq/libim/immpnt.c $ * * 1 11/02/99 4:38p Zaphod ** Revision 1.17 1995/06/29 00:28:04 bduggan ** updated copyright year ** ** Revision 1.16 1995/06/15 20:32:31 bduggan ** Removed anything printing to stderr. (i.e. debug messages) ** ** Revision 1.15 1995/06/14 18:58:32 bduggan ** Added some casts, took out some useless variables. ** ** Revision 1.14 1995/04/03 21:30:18 bduggan ** took out #ifdef NEWMAGIC ** ** Revision 1.13 1995/01/10 23:33:45 bduggan ** put in IMMULTI, IMPIPE instead of TRUE/FALSE ** uncapitlized i's in local functions ** made read/write routines static ** ** Revision 1.12 94/10/03 11:30:18 nadeau ** Updated to ANSI C and C++ compatibility. ** Removed all use of register keyword. ** Minimized use of custom SDSC types (e.g., uchar vs. unsigned char) ** Changed all float arguments to double. ** Added forward declarations. ** Added misc. casts to passify SGI and DEC compilers. ** Changed all macros and defined constants to have names ** starting with IM. ** Rearranged magic number structures for format handlers. ** Made format handler routines static (i.e., local to file). ** Updated comments, adding format descriptions and references. ** Updated indenting on some code. ** Updated copyright message. ** ** Revision 1.11 92/12/03 01:50:02 nadeau ** Corrected info messages. ** ** Revision 1.10 92/11/23 18:42:39 nadeau ** Removed use of IMINFOMSG. ** ** Revision 1.9 92/11/04 12:04:02 groening ** put ImFIleFormat info and magic number info ** from imfmt.c into this file. ** ** Revision 1.8 92/09/29 17:57:58 vle ** Added ImInfo messages. ** ** Revision 1.7 92/08/31 17:28:24 vle ** Updated copyright notice. ** ** Revision 1.6 91/10/03 09:14:30 nadeau ** Fixed #includes. ** ** Revision 1.5 91/03/12 17:56:23 nadeau ** Fixed bug with writing incomming VFBs that are smaller than ** mpnt standard size. The right side of such images were comming ** out black, when they should have been white. ** ** Revision 1.4 91/02/18 16:24:34 moreland ** fixed ! ** ** Revision 1.3 91/02/12 11:34:38 nadeau ** Removed the tag table checking and VFB conversion now ** handled by ImFileRead and ImFileWrite. Removed the ** IMtstBit and IMsetBit functions and turned them into macros. ** Issued warning messages in write when the incomming VFB ** is bigger than MacPaint will allow an image to be. ** Optimized write. Changed GRAY VFB references to MONO. ** ** Revision 1.2 91/01/28 10:49:43 moreland ** Worked on Write routine. ** ** Revision 1.1 91/01/10 16:44:45 soraya ** Initial revision **/ #include "iminternal.h" /** ** FORMAT ** MacPaint - Apple Macintosh MacPaint image file ** ** AKA ** mpnt, macp, pntg ** ** FORMAT REFERENCES ** - Bit-Mapped Graphics, Steve Rimmer ** - Graphics File Formats, David C. Kay, John R. Levine ** ** CODE CREDITS ** Custom development, Soraya Gonzalez, San Diego Supercomputer Center, 1991. ** ** DESCRIPTION ** Apple Macintosh MacPaint image files start with a 512 byte header ** which is typically all 0 (zero) values, and is usually ignored. ** Following the 512 byte header is 720 packed scan lines. ** macpack.c has information about how the lines are packed. **/ /* * MPNT - Apple Macintosh MacPaint * For information on these structures, how to use them, etc. please * see imfmt.c. */ #ifdef __STDC__ static int imMpntRead( int ioType, int fd, FILE *fp, TagTable *flagsTable, TagTable *tagTable ); static int imMpntWrite( ImFileFormatWriteMap *pMap, int ioType, int fd, FILE *fp, TagTable *flagsTable, TagTable *tagTable ); #else static int imMpntRead( ); static int imMpntWrite( ); #endif static char *imMpntNames[ ] = { "mpnt", "macp", "pntg", NULL }; static ImFileFormatReadMap imMpntReadMap[ ] = { /* in out */ /* type,ch,dep, attr. VFB type attr. */ { IN,1,1, PB, IMVFBMONO, 0 }, { -1, 0, -1, 0 }, }; static ImFileFormatWriteMap imMpntWriteMap[ ] = { /* in out */ /* VFB type, attr., type,ch,dep, attr., func */ { IMVFBMONO, 0, IN,1,1, PB, imMpntWrite }, { -1, 0, -1, 0, NULL }, }; static ImFileMagic imFileMpntMagic []= { { 0, 0, NULL }, }; ImFileFormat ImFileMpntFormat = { imMpntNames, "Apple Macintosh MacPaint file", "Apple Computer, Inc.", "1-bit Packbits-compressed MacPaint images.", "1-bit Packbits-compressed MacPaint images.", imFileMpntMagic, IMNOMULTI, IMPIPE, IMNOMULTI, IMPIPE, imMpntRead, imMpntReadMap, imMpntWriteMap }; /* * Macpaint defines */ #define IMMAC_HEADER_SIZE 512 #define IMMAC_MAX_UNPACKED_SIZE 51840 #define IMMAC_IMAGE_HEIGHT 720 #define IMMAC_IMAGE_WIDTH 576 #define IMMAC_ROW_BYTES ( IMMAC_IMAGE_WIDTH/8) #define IMMAC_BLACK 0 #define IMMAC_WHITE 1 /* * MACROS * IMtstBit - Test a bit value * IMsetBit - Set a bit value * * DESCRIPTION * IMtstBit: return the on/off setting of the selected bit. * IMsetBit: if val == 0, turn the bit off, otherwise on. */ #define IMtstBit(byte,bit) ((1<<(bit))&(byte)) #define IMsetBit(pByte,bit) (*(pByte) |= (1<<(bit))) #define IMunsetBit(pByte,bit) (*(pByte) &= ~(1<<(bit))) /* * FUNCTION * imMpntRead - read an Apple Macintosh MacPaint file * * DESCRIPTION * A Macpaint header and image are read in. The image is unpacked * (Mac packbits compression) and copied into a monochrome VFB. */ static int /* Returns # tags read in */ #ifdef __STDC__ imMpntRead( int ioType, int fd, FILE *fp, TagTable *flagsTable, TagTable *tagTable ) #else imMpntRead( ioType, fd, fp, flagsTable, tagTable ) int ioType; /* I/O flags */ int fd; /* Input file descriptor */ FILE * fp; /* Input file pointer */ TagTable * flagsTable; /* Flags */ TagTable * tagTable; /* Tag table to add to */ #endif { ImVfb * vfb; /* Read in image */ ImVfbPtr pPixel; /* Pixel pointer */ unsigned char packed[ IMMAC_MAX_UNPACKED_SIZE ];/* Packed bits buffer*/ unsigned char unpacked[ IMMAC_IMAGE_WIDTH ];/* Unpacked bits buffer */ unsigned char *pPtr, *uPtr; /* Bits buffer pointers */ int sLine; /* Current scanline */ int col; /* Current column */ int byte; /* Byte run counter */ unsigned int bit; /* Which bit in a byte */ unsigned long byteCount; /* # of bytes read */ unsigned int count, oldcount;/* Run counters */ char message[100]; /* ImInfo message */ /* * Read (and ignore) the 512 byte header */ BinByteOrder( BINMBF ); if ( ImBinRead( ioType, fd, fp, packed, UCHAR, 1, IMMAC_HEADER_SIZE ) == -1 ) { ImReturnBinError(); } /* * Allocate a Monochrome VFB of the required size. */ if ( (vfb = ImVfbAlloc( IMMAC_IMAGE_WIDTH, IMMAC_IMAGE_HEIGHT, IMVFBMONO )) == IMVFBNULL ) { ImErrorFatal( ImQError(), -1, ImErrNo ); } /* * Read the whole compressed image into a buffer. */ if ( (byteCount = ImBinRead( ioType, fd, fp, packed, UCHAR, 1, IMMAC_MAX_UNPACKED_SIZE )) == (unsigned long)-1 ) { ImReturnBinError(); } /* * Copy to the VFB, one scanline at a time. */ uPtr = unpacked; pPtr = packed; sLine = 0; col = 0; pPixel = ImVfbQFirst( vfb ); while ( sLine< IMMAC_IMAGE_HEIGHT ) { uPtr = unpacked; if ( pPtr[0] > 127 ) /* Unpack next 2 bytes of compressed data */ count = 2; else /* Unpack next ? bytes of non-compressed data */ count = pPtr[0] + 2; oldcount = count; /* remember BYTE count */ UnpackBits( pPtr, uPtr, &count ); pPtr += oldcount; /* Inc packedPtr by BYTE count*/ for ( byte=0; byte= IMMAC_IMAGE_WIDTH ) { sLine++; col = 0; } } } } TagTableAppend( tagTable, TagEntryAlloc( "image vfb", POINTER, &vfb ) ); /* * Output -verbose message */ ImInfo( "Byte Order", "Most Significant Byte First" ); sprintf( message, "%d x %d", IMMAC_IMAGE_WIDTH, IMMAC_IMAGE_HEIGHT ); ImInfo( "Resolution", message ); ImInfo( "Type", "1-bit Monochrome" ); ImInfo( "Compression Type", "Apple Macintosh Packbits" ); return ( 1 ); } /* * FUNCTION * imMpntWrite - write an Apple Macintosh MacPaint file * * DESCRIPTION * Write a monochrome MacPaint image. */ static int /* Returns # of tags used */ #ifdef __STDC__ imMpntWrite( ImFileFormatWriteMap *pMap, int ioType, int fd, FILE *fp, TagTable *flagsTable, TagTable *tagTable ) #else imMpntWrite( pMap, ioType, fd, fp, flagsTable, tagTable ) ImFileFormatWriteMap *pMap; /* Write map entry to adhear to */ int ioType; /* I/O flags */ int fd; /* Input file descriptor */ FILE * fp; /* Input file pointer */ TagTable * flagsTable; /* Flags */ TagTable * tagTable; /* Tag table to read from */ #endif { ImVfb *vfb; /* Image to output */ ImVfbPtr pPixel; /* Pixel pointer */ char * buf[ IMMAC_HEADER_SIZE ]; /* MacPaint file header */ unsigned char packed[ IMMAC_MAX_UNPACKED_SIZE ]; unsigned char unpacked[ IMMAC_IMAGE_WIDTH ]; unsigned char *pPtr; unsigned short sLine, bit, bitVal; unsigned long byteCount; unsigned int count, oldcount; unsigned short col; int n; int vfbHeight, vfbWidth; int mono_threshold; char message[100]; /* ImInfo message */ TagEntryQValue( TagTableQDirect( tagTable, "image vfb", 0 ), &vfb ); vfbHeight = ImVfbQHeight( vfb ); vfbWidth = ImVfbQWidth( vfb ); BinByteOrder( BINMBF ); /* * Write out the 512 byte (blank) header. */ memset( buf, 0x00, IMMAC_HEADER_SIZE ); if ( ImBinWrite( ioType, fd, fp, buf, UCHAR, 1, IMMAC_HEADER_SIZE ) == -1 ) { ImReturnBinError(); } /* * Output -verbose message */ ImInfo( "Byte Order", "Most Significant Byte First" ); sprintf( message, "%d x %d", IMMAC_IMAGE_WIDTH, IMMAC_IMAGE_HEIGHT ); ImInfo( "Resolution", message ); ImInfo( "Type", "1-bit Monochrome" ); ImInfo( "Compression Type", "Apple Macintosh Packbits" ); /* * Write the VFB out one scanline at a time. If the image is taller * than a MacPaint file allows, clip off the bottom. If smaller, * pad with zeroes. */ if ( vfbWidth > IMMAC_IMAGE_WIDTH ) { ImErrorWarning( "Image too wide for MacPaint format. Image has been clipped.", -1, IMEWIDTH ); vfbWidth = IMMAC_IMAGE_WIDTH; } if ( vfbHeight > IMMAC_IMAGE_HEIGHT ) { ImErrorWarning( "Image too tall for MacPaint format. Image has been clipped.", -1, IMEHEIGHT ); vfbHeight = IMMAC_IMAGE_HEIGHT; } for ( sLine=0; sLine