jedioutcast/utils/roq2/libim/imeps.c
2013-04-04 13:07:40 -05:00

2321 lines
39 KiB
C

/**
** $Header: /roq/libim/imeps.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/imeps.c 1 11/02/99 4:38p Zaphod $"
/**
** FILE
** imeps.c - Encapsulated PostScript file output
**
** PROJECT
** libim - SDSC image manipulation library
**
** DESCRIPTION
** imeps.c contains a write routine to write Encapsulated PostScript
** files for the image manipulation library.
**
** PUBLIC CONTENTS
** d =defined constant
** f =function
** m =defined macro
** t =typedef/struct/union
** v =variable
** ? =other
**
** ImFileEpsFormat v master format description
**
** PRIVATE CONTENTS
** imEpsNames v format's name and aliases
** imEpsWriteMap v write attributes
** imEpsMagicNumber v magic number
** imEpsMagic v list of magic numbers
**
** imEpsHex v Integer->Hex character conversion table
** imEpsHeader v PostScript header section
** imEpsProlog v PostScript prolog section
** imEpsImageColor v Color printing PostScript procedure
** imEpsImageGray v Grayscale printing PostScript procedure
** imEpsImageMono v Monochrome printing PostScript procedure
** imEpsScript v PostScript page script section
** imEpsData v PostScript data section
** imEpsTrailer v PostScript trailer section
**
** imEpsWrite1 f write a 1-bit monochrome image to a PostScript file
** imEpsWriteGray f write a grayscale image to a PostScript file
** imEpsWrite8 f write an 8-bit index image to a PostScript file
** imEpsWriteRGB f write an RGB image to a PostScript file
**
** HISTORY
** $Log: /roq/libim/imeps.c $
*
* 1 11/02/99 4:38p Zaphod
** Revision 1.12 1995/06/30 21:59:24 bduggan
** replaced long with time_t
**
** Revision 1.11 1995/06/29 00:28:04 bduggan
** updated copyright year
**
** Revision 1.10 1995/06/15 20:18:01 bduggan
** Added some function prototypes.
** Removed {}'s from char[] declaration
**
** Revision 1.9 1995/04/03 21:22:57 bduggan
** took out #ifdef NEWMAGIC
**
** Revision 1.8 1995/01/10 23:21:11 bduggan
** Uncapitilized i's in local functions
**
** Revision 1.7 94/10/03 11:30:04 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.6 92/12/03 01:47:38 nadeau
** Corrected info messages.
**
** Revision 1.5 92/11/04 11:59:57 groening
** put ImFIleFormat info and magic number info
** from imfmt.c into this file.
**
** Revision 1.4 92/10/19 14:15:21 groening
** added ImINfo statements
**
** Revision 1.3 92/09/25 12:38:01 groening
** added lines for ImInfo to printout verbose information
**
** Revision 1.2 92/08/31 17:22:40 vle
** Updated copyright notice.
**
** Revision 1.1 91/10/03 08:49:41 nadeau
** Initial revision
**
** Revision 1.7 91/09/17 20:17:10 nadeau
** Added color PostScript support.
**
** Revision 1.6 91/02/12 10:53:58 nadeau
** Removed the tag table checking and VFB conversion now
** handled by ImFileWrite. Updated to use INDEX8 instead
** of GRAY VFB. Changed 'Creator' comment to include the
** program name from the flags table, if given.
**
** Revision 1.5 90/11/27 16:40:44 mjb
** Removed spaces in between hex bytes (xerox says this will make it
** read much faster). Made 'image' byte string size the same as vfb
** width (ditto above comment)
**
** Revision 1.4 90/07/02 13:21:33 nadeau
** Updated to the new error handling mechanism.
**
** Revision 1.3 90/06/25 14:36:16 nadeau
** Changed ImTag* to Tag* (new names).
**
** Revision 1.2 90/05/16 07:47:03 todd
** Add #include "iminternal.h" to top of file
**
** Revision 1.1 90/05/11 14:28:23 nadeau
** Initial revision
**
**/
#include <time.h>
#include "iminternal.h"
/**
** FORMAT
** eps - Adobe Encapsulated PostScript
**
** AKA
**
** FORMAT REFERENCES
** PostScript Language Reference Manual, second edition, Adobe Systems,
** Addison Wesley, 1990.
**
** Bit-Mapped Graphics, Steve Rimmer, McGraw-Hill, 1990.
**
** Adobe PhotoShop 2.0 EPS File Format, Thomas Knoll, 1990-1991.
**
** CODE CREDITS
** Custom development, Dave Nadeau, San Diego Supercomputer Center, 1990.
**
** Partially based upon ideas and methods provided by Loren "Buck"
** Buchanan, Naval Research Laboratory, Kestrel Associates Inc.
**
** DESCRIPTION
** Adobe's EPS format is used by applications that create graphics or
** imagery for inclusion in another document by another application.
** Those graphics or imagery are described using Adobe's PostScript
** programming language, but augmented with a rigid set of special EPS
** file comments. Those comments help the including application figure
** out what's in the EPS file, how big it is, what it's font requirements
** are, and so on.
**
** Adobe PhotoShop further defines an additional EPS file comment that
** lets PhotoShop find and read in image data stored in an EPS file.
**
** Header
** EPS files begin with a special comment:
**
** %!PS-Adobe-3.0 EPSF-3.0
**
** This line is treated as a magic number by the SDSC Image Tools.
**
** Following the magic number line are a series of header comments
** describing the file's contents and purpose:
**
** %%BoundingBox: lx ly ux uy
** %%Creator: program
** %%For: person
** %%CreationDate: date
** %%Title: filename
** %%Pages: # of pages
** %%EndComments
**
** The %%BoundingBox comment is required of all EPS files and tells the
** reader how much space to leave in the including document for the
** EPS file's contents. Applications may just present the user with a
** square box of this size and let the user move it about to locate
** the included image in the document. Such applications need not read
** or understand the rest of the EPS file.
**
** The rest of the header comments are optional and are just for
** documentation purposes. The header ends with a %%EndComments comment.
**
** PhotoShop Support
** Following this header is PhotoShop's custom "%ImageData" comment:
**
** %ImageData: w h d ch pch block binhex "startline"
**
** This comment is, essentially, a pointer down to the raw image data
** stored later in the file. "w" and "h" are the width and height of
** the EPS image. "d" is it's channel depth (1 or 8 bits). "ch" is
** the number of image channels (1, 3, or 4).
**
** "pch" is the number of pad channels. These are extra channels added
** to the data that aren't to be imaged (PhotoShop uses this for a
** pre-computed grayscale image). "binhex" is a flag indicating if the
** raw image data is binary (1) or hex (2).
**
** The final argument to %ImageData is a copy of the entire PostScript
** line immediately preceeding the raw image data. PhotoShop uses this
** in a pattern match search through the file to find the line before
** the raw data. It then uses the rest of the arguments to figure out
** how to read that data.
**
** The SDSC Image Tools write out this comment so that PhotoShop can
** read in our EPS images.
**
** Preview
** In general, an EPS file need not contain raw image data (though that's
** what the SDSC Image Tools and PhotoShop output). An EPS file may
** contain almost any PostScript algorithm and data to draw anything.
** This presents something of a problem to applications wishing to import
** an EPS file and include it in a document (such as a diagram in a Word
** document). How can that application show something meaningful to the
** user so that the user can move and adjust the imported EPS data? The
** application can't be expected to parse and execute the PostScript code
** of the EPS file. So, now what?
**
** The answer is something called a "Preview Image". Programs that
** generate EPS files are kindly asked to rasterize the file's contents,
** possibly at low res, and always in grayscale, and place that rasterized
** version at the head of the file in a preview image comment. Now,
** applications that include the EPS file can present that low res gray
** image to the user as a crude representation of what's really in the
** EPS file and what will really get printed when the thing is sent to a
** PostScript printer.
**
** The Preview Image is a comment block starting and ending with:
**
** %%BeginPreview: h w d lines
** ...
** %%EndPreview
**
** The %%BeginPreview comment gives the preview image's height, width,
** depth (1, 2, 4, or 8) and number of lines of text preview data that
** follow. Applications that wish to strip out the preview image (such
** as lpr filters) can toss anything between %%BeginPreview and
** %%EndPreview.
**
** Why doesn't PhotoShop use this preview image? First, it's not
** required to be the same resolution as the real image. Second, it's
** always grayscale, even when the real image is color.
**
** The SDSC Image Tools output a Preview Image for those applications
** that need it. The image is always grayscale, and always the same
** resolution as the real image later on in the file.
**
** Prolog
** EPS files next contain a prolog section intended to be used to define
** assorted functions and variables for later use in the file. We use
** the prolog section to define a function "ImEpsImage" to read in and
** image the raw image data onto the page. That function is defined
** differently for monochrome, grayscale, and RGB image data. For RGB
** data, that function figures out if the printer to which the EPS data
** is being sent can handle color. If not, the RGB data is converted to
** grayscale on the fly.
**
** The Prolog is surrounded by:
**
** %%BeingProlog
** ...
** %%EndProlog
**
** Page
** The actual EPS drawing is surrounded by:
**
** %%Page: n m
** ...
** %%PageTrailer
**
** Within this comment structure are the PostScript commands to create
** the EPS image. For us, that means the raster image.
**
** Raster Image
** The EPS spec requests that raster image data be enclosed within
** the comments:
**
** %%BeginData: format
** ...
** %%EndData
**
** Applications wishing to skip this data (such as a PostScript pretty
** printer) use the "format" argument of the %%BeginData line to see
** how much to skip. There are several format types. We use the form
** that lists the number of hex data lines that follow. We intentionally
** use hex, rather than binary, so that our EPS data files can be sent
** to printers over 7-bit ASCII connections.
**
** Immediately following the %%BeginData comment is an invokation of our
** ImEpsImage function defined in the prolog. That function reads in
** the rest of the data and renders the image on to the page. Also note
** that it is this line (the one invoking ImEpsImage) that is referenced
** by the %ImageData comment for PhotoShop found earlier in the file.
** So, PhotoShop can scan down to this line, then read the same raw
** image data that follows as does ImEpsImage when printing.
**
** Note that the ImEpsImage invokation is within the %%BeginData/%%EndData
** comments. As such we need to add one extra line to our hex line count
** on the %%BeginData line.
**
** Trailer
** The whole file is ended with a %%Trailer and %%EOF set of comments.
**
**/
/*
* FUNCTION DECLARATIONS
*/
#ifdef __STDC__
static int imEpsWrite1( ImFileFormatWriteMap *pMap, int ioType, int fd, FILE *fp,
TagTable *flagsTable, TagTable *tagTable );
static int imEpsWriteGray( ImFileFormatWriteMap *pMap, int ioType, int fd, FILE *fp,
TagTable *flagsTable, TagTable *tagTable );
static int imEpsWrite8( ImFileFormatWriteMap *pMap, int ioType, int fd, FILE *fp,
TagTable *flagsTable, TagTable *tagTable );
static int imEpsWriteRGB( ImFileFormatWriteMap *pMap, int ioType, int fd, FILE *fp,
TagTable *flagsTable, TagTable *tagTable );
#else
static int imEpsWrite1( );
static int imEpsWriteGray( );
static int imEpsWrite8( );
static int imEpsWriteRGB( );
#endif
/*
* FORMAT INFORMATION
* imEpsNames - format's name and aliases
* imEpsWriteMap - write attributes
* imEpsMagicNumber - magic number
* imEpsMagic - list of magic numbers
* ImFileEpsFormat - master format description
*/
static char *imEpsNames[ ] = { "eps", "epi", "epsf", "epsi", NULL };
static ImFileFormatWriteMap imEpsWriteMap[ ] =
{
/* in out */
/* VFB type, attr., type,ch,dep, attr., func */
{ IMVFBMONO, 0, IN,1,1, 0, imEpsWrite1 },
{ IMVFBINDEX8, 0, IN,1,8, 0, imEpsWriteGray },
{ IMVFBINDEX8, C, IN,1,8, C, imEpsWrite8 },
{ IMVFBRGB, 0, RGB,3,8, 0, imEpsWriteRGB },
{ -1, 0, -1, 0, NULL },
};
static unsigned char imEpsMagicNumber[ ] = { '!', '%', 'P', 'S', '-',
'A', 'd', 'o', 'b', 'e', '-', '3', '.', '0', ' ',
'E', 'P', 'S', 'F', '-', '3', '.', '0' };
static ImFileMagic imEpsMagic[ ] =
{
{ 0, 23, imEpsMagicNumber },
{ 0, 0, NULL },
};
ImFileFormat ImFileEpsFormat=
{
imEpsNames, /* Names */
"Encapsulated PostScript file", /* Description */
"Adobe", /* Creator */
"None. Encapsulated PostScript files cannot be read!",/* Read support*/
"1-bit monochrome, 8-bit grayscale, 8-bit color index, and 24-bit\n\
RGB color images.", /* Write support*/
imEpsMagic, /* Magic #'s */
IMNOMULTI, IMNOPIPE, /* Read? */
IMNOMULTI, IMPIPE, /* Write? */
NULL, NULL, imEpsWriteMap /* Maps */
};
static char imEpsHex[] = "0123456789abcdef";
/*
* GLOBAL
* imEpsHeader - PostScript header section
*
* DESCRIPTION
* The PostScript file header is a set of special comments conforming
* to the Adobe Document Structuring Conventions (DSC) as specified
* in the Adobe PostScript Language Reference Manual (second edition).
*
* The DSC comments give the document name, creator, and whatnot.
* Most importantly, the DSC also gives the bounding box for the
* document.
*
* After the comment header is the %ImageData comment used by Adobe's
* PhotoShop to locate the raw image data for it to read in.
*
* Note that this string will be sent through printf() to fill in the
* comment arguments. So, we need to escape all % comment characters
* with a second % to insure it gets through to the output.
*/
static char *imEpsHeader = "\
%%!PS-Adobe-3.0 EPSF-3.0\n\
%%%%BoundingBox: 0 0 %d %d\n\
%%%%Creator: %s\n\
%%%%For: %s\n\
%%%%CreationDate: %s\
%%%%Title: %s\n\
%%%%Pages: 0\n\
%%%%EndComments\n\
%%ImageData: %d %d %d %d %d %d %d \"ImEpsImage\"\n\
";
/*
* GLOBALS
* imEpsImageColor - Color printing PostScript procedure
* imEpsImageGray - Grayscale printing PostScript procedure
* imEpsImageMono - Monochrome printing PostScript procedure
*
* DESCRIPTION
* Each of these three globals defines the same function (proc) for the
* PostScript file header. In each case, the ImEpsImage function takes
* hex image data and renders it onto the page. The difference is only
* in the type of data being fed ImEpsImage.
*
* Some parts of this PostScript code were inspired by similar procedures
* designed by Loren "Buck" Buchanan of the Naval Research Lab at
* Kestrel Associates Inc. His ideas are used here with his permission
* and our thanks.
*/
static char *imEpsImageColor = "\
%%BeginProlog\n\
% PROC\n\
% ImEpsImage\n\
%\n\
% DESCRIPTION\n\
% RGB hex image data is read from the current file. If the PostScript\n\
% device can handle color, the RGB image is imaged as is. If not, the\n\
% RGB pixels are converted to grayscale using the NTSC Y equation and\n\
% imaged.\n\
\n\
/ImEpsImage\n\
{\n\
/buffer ImEpsImageW 3 mul string def\n\
/graybuffer ImEpsImageW string def\n\
\n\
ImEpsImageW ImEpsImageH 8\n\
[ 1 0\n\
0 -1\n\
0 ImEpsImageH ]\n\
\n\
% Determine if the PostScript device can handle color by checking if\n\
% the colorimage operator is defined.\n\
systemdict /colorimage known\n\
{\n\
{\n\
currentfile buffer readhexstring pop\n\
} false 3\n\
colorimage\n\
}\n\
{\n\
% The PostScript device cannot do color. Convert to grayscale.\n\
{\n\
% Get the RGB data\n\
currentfile buffer readhexstring pop pop\n\
\n\
% For each pixel...\n\
0 1 ImEpsImageW 1 sub\n\
{\n\
% Compute gray value and store in graybuffer\n\
graybuffer exch\n\
dup 3 mul dup 1 add dup 1 add\n\
buffer exch get 0.114 mul\n\
exch buffer exch get 0.587 mul add\n\
exch buffer exch get 0.299 mul add\n\
cvi\n\
put\n\
} for\n\
graybuffer\n\
}\n\
image\n\
} ifelse\n\
showpage\n\
} bind def\n\
\n\
%%EndProlog\n\
";
static char *imEpsImageGray = "\
%%BeginProlog\n\
% PROC\n\
% ImEpsImage\n\
%\n\
% DESCRIPTION\n\
% Grayscale hex image data is read from the current file and imaged.\n\
\n\
/ImEpsImage\n\
{\n\
/buffer ImEpsImageW string def\n\
\n\
ImEpsImageW ImEpsImageH 8\n\
[ 1 0\n\
0 -1\n\
0 ImEpsImageH ]\n\
{\n\
currentfile buffer readhexstring pop\n\
}\n\
image\n\
showpage\n\
} bind def\n\
\n\
%%EndProlog\n\
";
static char *imEpsImageMono = "\
%%BeginProlog\n\
% PROC\n\
% ImEpsImage\n\
%\n\
% DESCRIPTION\n\
% Grayscale hex image data is read from the current file and imaged.\n\
\n\
/ImEpsImage\n\
{\n\
/buffer ImEpsImageW 7 add 8 idiv string def\n\
\n\
ImEpsImageW ImEpsImageH 1\n\
[ 1 0\n\
0 -1\n\
0 ImEpsImageH ]\n\
{\n\
currentfile buffer readhexstring pop\n\
}\n\
image\n\
showpage\n\
} bind def\n\
\n\
%%EndProlog\n\
";
/*
* GLOBAL
* imEpsData - PostScript data section
*
* DESCRIPTION
* The data section of a PostScript script gives the image data itself.
* In our case it defines the size of the image and invokes the image
* rendering procedure. Following it we dump the image data.
*/
static char *imEpsData = "\
%%%%Page: 1 1\n\
userdict begin\n\
/ImEpsImageW %d def %% Width in pixels\n\
/ImEpsImageH %d def %% Height in pixels\n\
%%%%BeginData: %d Hex Lines\n\
ImEpsImage\n\
";
/*
* GLOBAL
* imEpsTrailer - PostScript trailer section
*
* DESCRIPTION
* The trailer of the page, and file, is just a bunch of DSC keywords.
*/
static char *imEpsTrailer = "\
%%EndData\n\
end\n\
%%PageTrailer\n\
%%Trailer\n\
%%EOF\n\
";
/*
* FUNCTION
* imEpsWrite1 - write a 1-bit monochrome image to a PostScript file
* imEpsWriteGray - write a grayscale image to a PostScript file
* imEpsWrite8 - write an 8-bit index image to a PostScript file
* imEpsWriteRGB - write an RGB image to a PostScript file
*
* DESCRIPTION
* The image is retrieved from the tag table and a PostScript header
* giving the image's dimensions output. The appropriate PostScript
* procedure is dumped (grayscale or color pixel handling), followed
* by standard execution code and the pixels themselves.
*/
static int /* Returns # of entries used */
#ifdef __STDC__
imEpsWrite1( ImFileFormatWriteMap *pMap, int ioType, int fd, FILE *fp,
TagTable *flagsTable, TagTable *tagTable )
#else
imEpsWrite1( pMap, ioType, fd, fp, flagsTable, tagTable )
ImFileFormatWriteMap *pMap; /* Write map entry to adhear to */
int ioType; /* Type of I/O to perform */
int fd; /* Output file descriptor */
FILE *fp; /* Output file pointer */
TagTable *flagsTable; /* Flags */
TagTable *tagTable; /* Table of info to write */
#endif
{
int ipix; /* pixel counter */
ImVfbPtr p; /* VFB pixel pointer */
int pixel; /* Gray pixel color */
int x, y; /* Pixel location */
int xdim; /* # columns */
int ydim; /* # rows */
ImVfb *srcVfb; /* VFB to convert */
time_t clock; /* Clock time */
char message[100]; /* information for ImInfo */
/* Turn fd into fp so we can use fprintf. */
if ( (ioType & IMFILEIOFD) && (fp = fdopen( fd, "rb" )) == NULL )
{
ImErrNo = IMESYS;
return ( -1 );
}
/* Dump the header, prolog, script, and data sections. */
TagEntryQValue( TagTableQDirect( tagTable, "image vfb", 0 ), &srcVfb );
xdim = ImVfbQWidth( srcVfb );
ydim = ImVfbQHeight( srcVfb );
clock = time( NULL );
#ifndef WIN32
fprintf( fp, imEpsHeader,
xdim, ydim, /* BoundingBox: */
ImErrorProgramName, /* Creator: */
getlogin( ), /* For: */
ctime( &clock ), /* CreationDate: */
ImErrorFileName, /* Title: */
/* ImageData: */
xdim, ydim, 1, /* Width, height, depth */
1, 0, /* # channels, pad chan */
(xdim*1+7)/8, /* block size */
2 ); /* hex format */
#else
fprintf( fp, imEpsHeader,
xdim, ydim, /* BoundingBox: */
ImErrorProgramName, /* Creator: */
"Virtual Monty", /* For: */
ctime( &clock ), /* CreationDate: */
ImErrorFileName, /* Title: */
/* ImageData: */
xdim, ydim, 1, /* Width, height, depth */
1, 0, /* # channels, pad chan */
(xdim*1+7)/8, /* block size */
2 ); /* hex format */
#endif
sprintf (message, ImErrorFileName);
ImInfo ("Image Name",message);
sprintf (message, "%d x %d",xdim, ydim);
ImInfo ("Resolution",message);
ImInfo ("Type","1-bit Monochrome");
/*
* Dump the preview. Nearly identical to image data except:
* - 0 = white and 1 = black instead of the usual way.
* - bottom to top instead of top to bottom.
*/
fprintf( fp, "%%%%BeginPreview: %d %d %d %d\n%%", xdim, ydim, 1,
(((xdim + 7) / 8) * 2 * ydim + 71) / 72 );
for ( ipix = 0, y = ydim-1; y >= 0; y-- )
{
p = ImVfbQPtr( srcVfb, 0, y );
for ( pixel = 0, x = 1; x <= xdim; x++, ImVfbSInc( srcVfb, p ) )
{
pixel = (pixel << 1) | ((~ImVfbQMono( srcVfb, p ))&0x1);
if ( (x & 0x7) == 0 )
{
putc( imEpsHex[ ((pixel >> 4) & 0xF) ], fp );
putc( imEpsHex[ (pixel & 0xF) ], fp );
pixel = 0;
if( ++ipix >= 36 )
{
putc( '\n', fp );
putc( '%', fp );
ipix = 0;
}
}
}
if ( (xdim & 0x7) != 0 )
{
pixel <<= 8 - (xdim & 0x7);
putc( imEpsHex[ ((pixel >> 4) & 0xF) ], fp );
putc( imEpsHex[ (pixel & 0xF) ], fp );
if( ++ipix >= 36 )
{
putc( '\n', fp );
putc( '%', fp );
ipix = 0;
}
}
}
fprintf( fp, "\n%%%%EndPreview\n" );
/*
* Dump the data routine.
*
* Compute the number of hex lines of data written out and put
* that in the args of the %%BeginData comment. Note that we
* add 1 extra line for the "ImPsImage" function invokation.
*/
fprintf( fp, "%s", imEpsImageMono );
fprintf( fp, imEpsData,
xdim, /* ImEpsImageWidth */
ydim, /* ImEpsImageHeight */
1 + (((xdim + 7) / 8) * 2 * ydim + 71) / 72 ); /* Lines*/
/* Dump the pixels. */
p = ImVfbQFirst( srcVfb );
for ( ipix = 0, y = ydim - 1; y >= 0; y-- )
{
for ( pixel = 0, x = 1; x <= xdim; x++, ImVfbSInc( srcVfb, p ) )
{
pixel = (pixel << 1) | (ImVfbQMono( srcVfb, p ) & 0x1);
if ( (x & 0x7) == 0 )
{
putc( imEpsHex[ ((pixel >> 4) & 0xF) ], fp );
putc( imEpsHex[ (pixel & 0xF) ], fp );
pixel = 0;
if( ++ipix >= 36 )
{
/* Add a line break every 36*2=72 char*/
putc( '\n', fp );
ipix = 0;
}
}
}
if ( (xdim & 0x7) != 0 )
{
pixel <<= 8 - (xdim & 0x7);
putc( imEpsHex[ ((pixel >> 4) & 0xF) ], fp );
putc( imEpsHex[ (pixel & 0xF) ], fp );
if( ++ipix >= 36 )
{
/* Add a line break every 36*2=72 characters*/
putc( '\n', fp );
ipix = 0;
}
}
}
/* Dump the trailer. */
fprintf( fp, "\n%s", imEpsTrailer );
fflush( fp );
return ( 1 ); /* Used VFB from tag table */
}
static void /* Returns nothing */
#ifdef __STDC__
imEpsWriteGrayPreview( FILE *fp, ImVfb *srcVfb )
#else
imEpsWriteGrayPreview( fp, srcVfb )
FILE *fp; /* File to write to */
ImVfb *srcVfb; /* VFB to write out */
#endif
{
int ipix; /* pixel counter */
ImVfbPtr p; /* VFB pixel pointer */
int pixel; /* Gray pixel color */
ImVfb *grayVfb; /* Grayscale VFB */
int x, y; /* Pixel location */
int xdim; /* # columns */
int ydim; /* # rows */
xdim = ImVfbQWidth( srcVfb );
ydim = ImVfbQHeight( srcVfb );
if ( (ImVfbQFields( srcVfb ) & IMVFBINDEX8) == 0 ||
ImVfbQClt( srcVfb ) != IMCLTNULL )
{
/* Not a grayscale VFB. Make one first. */
grayVfb = ImVfbToGray( srcVfb, IMVFBNEW );
}
else
grayVfb = srcVfb;
/* Write out a grayscale preview image. */
fprintf( fp, "%%%%BeginPreview: %d %d %d %d\n%%", xdim, ydim, 8,
(xdim * 2 * ydim + 71) / 72);
for ( ipix = 0, y = ydim-1; y >= 0; y-- )
{
p = ImVfbQPtr( grayVfb, 0, y );
for ( x = 0; x < xdim; x++, ImVfbSInc( grayVfb, p ) )
{
pixel = ImVfbQGray( grayVfb, p );
putc( imEpsHex[ (pixel>>4) & 0xf ], fp );
putc( imEpsHex[ pixel & 0xf ], fp );
if( ++ipix >= 36 )
{
/* Add a line break every 36*2=72 characters*/
putc( '\n', fp );
putc( '%', fp );
ipix = 0;
}
}
}
fprintf( fp, "\n%%%%EndPreview\n" );
if ( grayVfb != srcVfb )
ImVfbFree( grayVfb );
}
static int /* Returns # of entries used */
#ifdef __STDC__
imEpsWriteGray( ImFileFormatWriteMap *pMap, int ioType, int fd, FILE *fp,
TagTable *flagsTable, TagTable *tagTable )
#else
imEpsWriteGray( pMap, ioType, fd, fp, flagsTable, tagTable )
ImFileFormatWriteMap *pMap; /* Write map entry to adhear to */
int ioType; /* Type of I/O to perform */
int fd; /* Output file descriptor */
FILE *fp; /* Output file pointer */
TagTable *flagsTable; /* Flags */
TagTable *tagTable; /* Table of info to write */
#endif
{
int ipix; /* pixel counter */
ImVfbPtr p; /* VFB pixel pointer */
int pixel; /* Gray pixel color */
ImVfbPtr last; /* Last pixel in VFB */
int xdim; /* # columns */
int ydim; /* # rows */
ImVfb *srcVfb; /* VFB to convert */
time_t clock; /* Clock time */
char message[100]; /* information for ImInfo */
/* Turn fd into fp so we can use fprintf. */
if ( (ioType & IMFILEIOFD) && (fp = fdopen( fd, "rb" )) == NULL )
{
ImErrNo = IMESYS;
return ( -1 );
}
/* Dump the header. */
TagEntryQValue( TagTableQDirect( tagTable, "image vfb", 0 ), &srcVfb );
xdim = ImVfbQWidth( srcVfb );
ydim = ImVfbQHeight( srcVfb );
clock = time( NULL );
#ifndef WIN32
fprintf( fp, imEpsHeader,
xdim, ydim, /* BoundingBox: */
ImErrorProgramName, /* Creator: */
getlogin( ), /* For: */
ctime( &clock ), /* CreationDate: */
ImErrorFileName, /* Title: */
/* ImageData: */
xdim, ydim, 8, /* Width, height, depth */
1, 0, /* # channels, pad chan */
(xdim*1+7)/8, /* block size */
2 ); /* hex format */
#else
fprintf( fp, imEpsHeader,
xdim, ydim, /* BoundingBox: */
ImErrorProgramName, /* Creator: */
"Virtual Monty", /* For: */
ctime( &clock ), /* CreationDate: */
ImErrorFileName, /* Title: */
/* ImageData: */
xdim, ydim, 8, /* Width, height, depth */
1, 0, /* # channels, pad chan */
(xdim*1+7)/8, /* block size */
2 ); /* hex format */
#endif
sprintf (message, ImErrorFileName);
ImInfo ("Image Name",message);
sprintf (message, "%d x %d",xdim, ydim);
ImInfo ("Resolution",message);
ImInfo ("Type","8-bit Grayscale");
/*
* Dump the Preview data. Identical to grayscale data except
* bottom up.
*/
imEpsWriteGrayPreview( fp, srcVfb );
/*
* Dump the data routine.
*
* Compute the number of hex lines of data written out and put
* that in the args of the %%BeginData comment. Note that we
* add 1 extra line for the "ImPsImage" function invokation.
*/
fprintf( fp, "%s", imEpsImageGray );
fprintf( fp, imEpsData,
xdim, /* ImEpsImageWidth */
ydim, /* ImEpsImageHeight */
1 + (xdim * 2 * ydim + 71) / 72 ); /* # of lines */
/* Dump the pixels. */
p = ImVfbQFirst( srcVfb );
last = ImVfbQLast( srcVfb );
for ( ipix = 0; p <= last; ImVfbSInc( srcVfb, p ) )
{
pixel = ImVfbQGray( srcVfb, p );
putc( imEpsHex[ (pixel>>4) & 0xf ], fp );
putc( imEpsHex[ pixel & 0xf ], fp );
if( ++ipix >= 36 )
{
/* Add a line break every 36*2=72 characters */
putc( '\n', fp );
ipix = 0;
}
}
/* Dump the trailer. */
fprintf( fp, "\n%s", imEpsTrailer );
fflush( fp );
return ( 1 ); /* Used VFB from tag table */
}
static int /* Returns # of entries used */
#ifdef __STDC__
imEpsWrite8( ImFileFormatWriteMap *pMap, int ioType, int fd, FILE *fp,
TagTable *flagsTable, TagTable *tagTable )
#else
imEpsWrite8( pMap, ioType, fd, fp, flagsTable, tagTable )
ImFileFormatWriteMap *pMap; /* Write map entry to adhear to */
int ioType; /* Type of I/O to perform */
int fd; /* Output file descriptor */
FILE *fp; /* Output file pointer */
TagTable *flagsTable; /* Flags */
TagTable *tagTable; /* Table of info to write */
#endif
{
int ipix; /* pixel counter */
ImVfbPtr p; /* VFB pixel pointer */
int value; /* CLT value */
ImVfbPtr last; /* Last pixel in VFB */
int pixel; /* Gray pixel color */
ImClt *clt; /* VFB's color lookup table */
ImCltPtr c; /* CLT entry pointer */
int xdim; /* # columns */
int ydim; /* # rows */
ImVfb *srcVfb; /* VFB to convert */
time_t clock; /* Clock time */
char message[100]; /* information for ImInfo */
/* Turn fd into fp so we can use fprintf. */
if ( (ioType & IMFILEIOFD) && (fp = fdopen( fd, "rb" )) == NULL )
{
ImErrNo = IMESYS;
return ( -1 );
}
/* Dump the header. */
TagEntryQValue( TagTableQDirect( tagTable, "image vfb", 0 ), &srcVfb );
xdim = ImVfbQWidth( srcVfb );
ydim = ImVfbQHeight( srcVfb );
clock = time( NULL );
#ifndef WIN32
fprintf( fp, imEpsHeader,
xdim, ydim, /* BoundingBox: */
ImErrorProgramName, /* Creator: */
getlogin( ), /* For: */
ctime( &clock ), /* CreationDate: */
ImErrorFileName, /* Title: */
/* ImageData: */
xdim, ydim, 8, /* Width, height, depth */
3, 0, /* # channels, pad chan */
1, /* block size (interleaved)*/
2 ); /* hex format */
#else
fprintf( fp, imEpsHeader,
xdim, ydim, /* BoundingBox: */
ImErrorProgramName, /* Creator: */
"Virtual Monty", /* For: */
ctime( &clock ), /* CreationDate: */
ImErrorFileName, /* Title: */
/* ImageData: */
xdim, ydim, 8, /* Width, height, depth */
3, 0, /* # channels, pad chan */
1, /* block size (interleaved)*/
2 ); /* hex format */
#endif
sprintf (message, ImErrorFileName);
ImInfo ("Image Name",message);
sprintf (message, "%d x %d",xdim, ydim);
ImInfo ("Resolution",message);
ImInfo ("Type","8-bit Color Indexed");
ImInfo ("Color Table","256 Entries");
/* Dump the preview image as 8-bit grayscale, bottom to top. */
imEpsWriteGrayPreview( fp, srcVfb );
/*
* Dump the data routine.
*
* Compute the number of hex lines of data written out and put
* that in the args of the %%BeginData comment. Note that we
* add 1 extra line for the "ImPsImage" function invokation.
*/
fprintf( fp, "%s", imEpsImageColor );
fprintf( fp, imEpsData,
xdim, /* ImEpsImageWidth */
ydim, /* ImEpsImageHeight */
1 + (xdim * 6 * ydim + 71) / 72 ); /* # of lines */
/*
* Dump the pixels. RGBRGBRGB...
*/
p = ImVfbQFirst( srcVfb );
last = ImVfbQLast( srcVfb );
clt = ImVfbQClt( srcVfb );
for ( ipix = 0; p <= last; ImVfbSInc( srcVfb, p ) )
{
pixel = ImVfbQIndex8( srcVfb, p );
c = ImCltQPtr( clt, pixel );
value = ImCltQRed( c );
putc( imEpsHex[ (value>>4) & 0xf ], fp );
putc( imEpsHex[ value & 0xf ], fp );
value = ImCltQGreen( c );
putc( imEpsHex[ (value>>4) & 0xf ], fp );
putc( imEpsHex[ value & 0xf ], fp );
value = ImCltQBlue( c );
putc( imEpsHex[ (value>>4) & 0xf ], fp );
putc( imEpsHex[ value & 0xf ], fp );
if( ++ipix >= 12 )
{
/* Add a line break every 12*3*2=72 characters */
putc( '\n', fp );
ipix = 0;
}
}
/* Dump the trailer. */
fprintf( fp, "\n%s", imEpsTrailer );
fflush( fp );
return ( 2 ); /* Used VFB & CLT from tag table */
}
static int /* Returns # of entries used */
#ifdef __STDC__
imEpsWriteRGB( ImFileFormatWriteMap *pMap, int ioType, int fd, FILE *fp,
TagTable *flagsTable, TagTable *tagTable )
#else
imEpsWriteRGB( pMap, ioType, fd, fp, flagsTable, tagTable )
ImFileFormatWriteMap *pMap; /* Write map entry to adhear to */
int ioType; /* Type of I/O to perform */
int fd; /* Output file descriptor */
FILE *fp; /* Output file pointer */
TagTable *flagsTable; /* Flags */
TagTable *tagTable; /* Table of info to write */
#endif
{
int ipix; /* pixel counter */
ImVfbPtr p; /* VFB pixel pointer */
int pixel; /* RGB pixel color */
ImVfbPtr last; /* Last pixel in VFB */
int xdim; /* # columns */
int ydim; /* # rows */
ImVfb *srcVfb; /* VFB to convert */
time_t clock; /* Clock time */
char message[100]; /* information for ImInfo */
/* Turn fd into fp so we can use fprintf. */
if ( (ioType & IMFILEIOFD) && (fp = fdopen( fd, "rb" )) == NULL )
{
ImErrNo = IMESYS;
return ( -1 );
}
/* Dump the header. */
TagEntryQValue( TagTableQDirect( tagTable, "image vfb", 0 ), &srcVfb );
xdim = ImVfbQWidth( srcVfb );
ydim = ImVfbQHeight( srcVfb );
clock = time( NULL );
#ifndef WIN32
fprintf( fp, imEpsHeader,
xdim, ydim, /* BoundingBox: */
ImErrorProgramName, /* Creator: */
getlogin( ), /* For: */
ctime( &clock ), /* CreationDate: */
ImErrorFileName, /* Title: */
/* ImageData: */
xdim, ydim, 8, /* Width, height, depth */
3, 0, /* # channels, pad chan */
1, /* block size (interleaved)*/
2 ); /* hex format */
#else
fprintf( fp, imEpsHeader,
xdim, ydim, /* BoundingBox: */
ImErrorProgramName, /* Creator: */
"Virtual Monty", /* For: */
ctime( &clock ), /* CreationDate: */
ImErrorFileName, /* Title: */
/* ImageData: */
xdim, ydim, 8, /* Width, height, depth */
3, 0, /* # channels, pad chan */
1, /* block size (interleaved)*/
2 ); /* hex format */
#endif
sprintf (message, ImErrorFileName);
ImInfo ("Image Name",message);
sprintf (message, "%d x %d",xdim, ydim);
ImInfo ("Resolution",message);
ImInfo ("Type","24-bit RGB");
/* Dump the preview image as 8-bit grayscale, bottom to top. */
imEpsWriteGrayPreview( fp, srcVfb );
/*
* Dump the data routine.
*
* Compute the number of hex lines of data written out and put
* that in the args of the %%BeginData comment. Note that we
* add 1 extra line for the "ImPsImage" function invokation.
*/
fprintf( fp, "%s", imEpsImageColor );
fprintf( fp, imEpsData,
xdim, /* ImEpsImageWidth */
ydim, /* ImEpsImageHeight */
1 + (xdim * 6 * ydim + 71) / 72 ); /* # of lines */
/*
* Dump the pixels. RGBRGBRGB...
*/
p = ImVfbQFirst( srcVfb );
last = ImVfbQLast( srcVfb );
for ( ipix = 0; p <= last; ImVfbSInc( srcVfb, p ) )
{
pixel = ImVfbQRed( srcVfb, p );
putc( imEpsHex[ (pixel>>4) & 0xf ], fp );
putc( imEpsHex[ pixel & 0xf ], fp );
pixel = ImVfbQGreen( srcVfb, p );
putc( imEpsHex[ (pixel>>4) & 0xf ], fp );
putc( imEpsHex[ pixel & 0xf ], fp );
pixel = ImVfbQBlue( srcVfb, p );
putc( imEpsHex[ (pixel>>4) & 0xf ], fp );
putc( imEpsHex[ pixel & 0xf ], fp );
if ( ++ipix >= 12 )
{
/* Add a line break every 12*3*2=72 characters */
putc( '\n', fp );
ipix = 0;
}
}
/* Dump the trailer. */
fprintf( fp, "\n%s", imEpsTrailer );
fflush( fp );
return ( 1 ); /* Used VFB from tag table */
}