2321 lines
39 KiB
C
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 */
|
|
|
|
}
|
|
|