007 1633 030

User Manual: 007-1633-030

Open the PDF directly: View PDF PDF.
Page Count: 308

Download007-1633-030
Open PDF In BrowserView PDF
Impressario™ Programming Guide

Document Number 007-1633-030

CONTRIBUTORS
Written by David Graves
Edited by Nancy Schweiger and Christina Cary
Cover design and illustration by Rob Aguilar, Rikk Carey, Dean Hodgkinson,
Erik Lindholm, and Kay Maitz
Production by Lorrie Williams and Gloria Ackley
Engineering contributions by Roger Chickering, Ken Kershner, Baron Roberts,
David Story, and Craig Upson
© Copyright 1992–1994, Silicon Graphics, Inc.— All Rights Reserved
This document contains proprietary and confidential information of Silicon
Graphics, Inc. The contents of this document may not be disclosed to third parties,
copied, or duplicated in any form, in whole or in part, without the prior written
permission of Silicon Graphics, Inc.
RESTRICTED RIGHTS LEGEND
Use, duplication, or disclosure of the technical data contained in this document by
the Government is subject to restrictions as set forth in subdivision (c) (1) (ii) of the
Rights in Technical Data and Computer Software clause at DFARS 52.227-7013 and/
or in similar or successor clauses in the FAR, or in the DOD or NASA FAR
Supplement. Unpublished rights reserved under the Copyright Laws of the United
States. Contractor/manufacturer is Silicon Graphics, Inc., 2011 N. Shoreline Blvd.,
Mountain View, CA 94039-7311.
Silicon Graphics and IRIS are registered trademarks and Impressario, IRIX, Personal
IRIS, Indigo, Magic, and WorkSpace are trademarks of Silicon Graphics, Inc.
PostScript and TranScript are registered trademarks of Adobe Systems, Inc. TIFF is a
trademark of Aldus Corporation. Apple, LaserWriter, Plus, II, IINT, IINTX, IIf, IIg,
and NTX are registered trademarks of Apple Computer, Inc. AT&T System V is a
registered trademark and Documenter’s Workbench is a trademark of AT&T. BSD is
a trademark of Berkeley Software Distribution. Centronics is a registered trademark
of Centronics Data Computer Corporation. GIFand Graphics Interchange Format are
trademarks of CompuServe Incorporated. Hewlett Packard, HP, LaserJet, IIP, IIP+,
III, IIIP, 4, 4P, 4L, DesignJet 650C, HP-GL, 7550A, DeskJet, 500C, 550C, 1200C, ScanJet,
and PaintJet XL300 are registered trademarks of the Hewlett-Packard Company.
PhotoCD s a trademark of the Eastman Kodak Company. X Window System is a
trademark of the Massachusetts Institute of Technology. OSF, Motif, Motif widget,
and OSF/Motif are trademarks of Open Software Foundation. Tektronix, Tektronix
Phaser, Tektronix Phaser II SX, and Tektronix Phaser II PXi are trademarks of
Tektronix, Inc. UNIX is a registered trademark of UNIX System Laboratories.
Versatec is a registered trademark of Versatec Corporation.
Impressario™ Programming Guide
Document Number 007-1633-030

Contents

Introduction xvii
Audience xviii
New Features xix
How to Use This Guide xix
Style Conventions xx
Document Overview xxi
Related Publications xxiii
Online Books xxiii
Online Release Notes xxiii
Online Man Pages xxiv
Release Identification Information
1.

2.

xxiv

Impressario Architecture 1
Overview 2
Impressario Printing Architecture 3
Compliance for Printer Driver Developers 4
Printing Application Programming Interfaces
Printing Application Development 10
Impressario Scanning Architecture 11
Scanner Driver Development 13
Scanner Application Development 13

6

Installing Impressario Software 17
Impressario Subsystems 18
Installation Software Prerequisites 20
Disk Space Requirements 20
Installation Method 20
Installing Impressario Software 21

iii

Contents

Connecting the Printer or Scanner 21
Configuring the Impressario Software 22
Software Compatibility 23

iv

3.

Printer Drivers 27
Overview 27
Printer Driver Processing 28
Printer Driver Example 29
Program Invocation 29
Program Processing 30
Filter/Driver Specification 32
Required Options 33
Reserved Options 33
Unreserved Options 35

4.

Printer Model Files 39
Overview 40
Command-Line Arguments 40
Template Model File Execution 41
Variable Declaration 42
Convenience Functions 42
Process Command-Line Arguments 43
Banner Page 43
File Processing 44
Cleanup and Exit 44
Printer-Specific Options 45
Vendor-Supplied Model File Additions 47
Printer Name 47
Device Interface 48
Printer Type 48
GUI Class 48
Printer-Specific Filter/Driver 49
Debug Routine 49

Cleanup Routine 49
Printer-Specific Banner Page 49
Printer-Specific Filtering Options
Fast Path for Text 50

50

5.

Printer Graphical Options Panel 53
Overview 54
Graphical Options Panel Layout 54
Options Handling 56
Graphical Options Panel Development 56
Graphical Options Panel Naming 57
Graphical Options Panel Installation 57
Invocation by the PrintBox Widget 58
Standalone Invocation for Testing 59
Termination by the PrintBox Widget 59
Additional Information 59

6.

Printing Libraries 63
The libspool Library 64
Compiling Programs with libspool 64
libspool Library Functions 65
The libprintui Library 67
Example Widget Configurations 68
Compiling Programs with libprintui 70
Library Functions Listed by Purpose 71
Example Program 71
The libpod Library 73
POD Files 73
Standard and Local libpod Functions 74
Compiling Programs with libpod 75
Debugging with libpod 75
Network Communications 75
Library Functions Listed by Purpose 76

v

Contents

7.

Scanner Drivers 79
Driver Template 80
Header Files 80
Data Structures 81
SCANINFO Data Structure 81
SCANPARAMS Data Structure 83
Functions You Must Write 86
Events 95
Installation 97
Testing 98

8.

Scanner-Specific Options 101
Overview 101
Options Program and the Scanner Driver Interface
Scanner Driver's Perspective 103
Options Program's Perspective 105
Installation and Testing 108

9.

vi

Generic Scanner Interface 111
Overview 112
Coordinate System for Scanning 112
Data Structures 113
SCANNER Data Structure 113
SCDATATYPE Data Structure 113
Data Type Conventions 114
Functions 116
Diagnostic Functions 116
Application/Driver Rendezvous Functions
Scanning Resolution Functions 120
Scanning Area Functions 121
Scanning Functions 121
Document Feeder Functions 125
Events 128

102

117

10.

Testing for Impressario Compatibility 133
Testing Impressario Printing Compatibility 134
Testing an Impressario Printer 134
Testing an Impressario Printer Software Installation

11.

Packaging Your Impressario Product 139
Overview 139
Making a Software Distribution 140
Packaging Impressario Printing Software 141
Packaging Impressario Scanning Software 144

12.

Enhancing Impressario with Plug-Ins 149
How the Impressario File Conversion Pipeline Works
File Type Rules 150
Runtime File Type Recognition Utility 150
File Conversion Utility 151
Adding a New Filetype to Impressario 152
Writing a New Filter 152
Writing an FTR 152
Adding a CONVERT Rule 152
Installation and Testing 153
Using an Alternate PostScript RIP 156
Making the Command line Compatible 156
Writing a Dummy TYPE 157
Testing the Alternate RIP 157
Packaging the Files 158

A.

136

150

Stream TIFF Data Format 161
Library Description 162
Library Access 162
Library Functions 163
Example Usage 164

vii

Contents

Printing-Specific STIFF 166
Generic STIFF File Structure 167

viii

B.

Silicon Graphics Image File Format API 175
Library Description 175
Library Access 176
Library Functions 176
IMPImage Structure 179
Image Access Functions 181
Data Packing Functions 183
Error Handling Functions 184
Image I/O Functions 185
Color Space Conversion Functions 188
Math Operation Functions 194
Zooming Functions 196

C.

Printer Object Database (POD) File Formats 205
Overview 206
Printer Configuration File 206
Printer Status File 207
Printer Log File 207
General Syntax 208
Character Set 208
Field Format 208
Input Parsing Rules for libpod Files 209
Printer Configuration File Format 210
General Format 210
Config File Options 211
Printer Status File Format 220
General Format 220
Printer Status File Entries 220
Printer Log File Format 224

D.

Transition Notes 227
Impressario 1.1 to 1.2 228
Notes for Application Developers 228
Notes for Filter/Driver Developers 228
Impressario 1.0 to 1.2 229
Notes for Application Developers 229
Notes for Filter/Driver Developers 229
General Changes from IRIX 4 to IRIX 5 231

E.

Scanner Driver Architecture 235
Overview 236
Driver Structure 236
Scanner Functions 238
Required Scanner Functions 238
Type Conversion Macros 244
Zooming and Type Conversion Functions 244
Queues and Multi-Threaded Scanner Drivers 247
Queue Manipulating Functions 249

F.

Man Pages 253
Glossary 257
Index 265

ix

Figures

Figure 1-1
Figure 1-2
Figure 1-3
Figure 1-4
Figure 1-5
Figure 1-6
Figure 1-7
Figure 3-1
Figure 5-1
Figure 6-1
Figure 6-2
Figure 6-3
Figure 6-4
Figure 7-1
Figure 7-2
Figure A-1
Figure B-1
Figure B-2
Figure B-3
Figure B-4
Figure B-5
Figure B-6
Figure B-7
Figure E-1

Impressario Printing Architecture 3
Printer Driver Development Flowchart 4
General Filter/Driver Architecture 7
System V Spooling System Interface 9
BSD Spooling System Interface 9
Scanner Run-Time Components 11
Interprocess Scanner Communication 12
Printer Driver Processing Overview 28
Graphical Printer Options Panel 55
PrintBox Widget – Default Configuration 68
PrintBox Widget – No Filename Entry Box 69
PrintBox Widget – No Options Box 69
PrintBox Widget – With a Child 70
Scanner Install Tool 97
gscan Panel 98
Generic STIFF File Structure 168
W Conversions 188
K Conversions 189
CMY Conversions 189
YIQ Conversions 190
YUV Conversions 190
YCbCr Conversions 191
CMYK Conversions 192
Scanner Driver Architecture 248

xi

Tables

Table 1-1
Table 4-1
Table 4-2
Table 4-3
Table 5-1
Table 6-1
Table 6-2
Table 6-3
Table 7-1
Table 9-1
Table 9-2
Table 9-3
Table 9-4
Table 9-5
Table 11-1
Table 11-2
Table 12-1
Table 12-2
Table A-1
Table A-2
Table A-3
Table A-4
Table A-5
Table A-6
Table A-7
Table B-1
Table B-2

Printing Application Programming Interfaces 8
Convenience Functions 42
Reserved Option Names 45
Printer Type Specifications 48
Command-Line Arguments 58
Summary of libspool Functions 65
Summary of libprintui Functions 71
Summary of libpod Functions 76
Functions to Be Written by the Driver Developer 86
Diagnostic Functions 116
Application/Driver Rendezvous Functions 117
Scanning Functions 122
Document Feeder Functions 125
Event Functions 128
Typical Printing Product Files 142
Typical Scanning Product Files 145
New Filetype Pathnames 155
Alternative RIP Pathnames 158
STIFF Generic Functions 163
STIFF Printing-Specific Functions 164
CMYK Data Format 169
CMY Data Format 169
YMC Data Format 170
YMCK Data Format 170
KCMY Data Format 171
Silicon Graphics Image Format File Functions 176
Format-Independent File Functions 177

xiii

Tables

Table B-3
Table C-1
Table C-2
Table E-1
Table E-2
Table E-3
Table E-4
Table F-1
Table F-2
Table F-3

xiv

Filter Functions 199
Config File Options 211
Printer Status File Entries 221
Scanner Driver Functions 238
Type Conversion Macros 244
Zooming and Type Conversion Functions
Queue Manipulating Functions 249
General Interest Man Pages 253
Printing Developers Man Pages 254
Scanning Developers Man Pages 254

245

Introduction

Introduction

The Impressario Programming Guide is
written for the following users:
•

Printer driver developers

•

Scanner driver developers

•

Application program developers
who need to print or scan from their
applications

Introduction

Impressario™ is a printing and scanning environment for Silicon Graphics®
IRIS® workstations. The Impressario Developer’s Kit provides solutions for
a wide range of UNIX® audiences: printer and scanner driver developers,
application program developers, and end users.
The goal of Impressario is to provide an intuitive, friendly, and reliable
interface for end users, while increasing system capability and performance
for driver and application developers. Users can simply drag and drop a file
onto a printer icon to print the file. Other graphical tools in the end-user’s
environment provide information on the capabilities and status of any
accessible printer or scanner.
The Impressario printing environment provides two main end-user
enhancements:
•

Support for a wide range of printers from high-quality color printers to
high-speed black-and-white printers

•

Graphical printing tools that allow a user to submit a print job and
monitor the status of the job and the printer

Impressario enables developers of printer drivers and scanner drivers to
showcase each product’s special features and capabilities and present them
to the user via a graphical dialog box. Application programmers can greatly
reduce the development time required to support printing and scanning
functions.
Note: The Impressario Release Notes contain the most recent information
about the product. Release notes are provided online and can be read using
grelnotes(1) or relnotes(1). In addition, the directory /usr/impressario contains
information of interest to both application developers and end users.

xvii

Introduction

The Impressario printing environment is built on top of the AT&T System V®
printer spooling interface. Model files, filters, and printer drivers are
provided to convert a wide variety of file types (ISO text files, Silicon
Graphics Image files, PostScript® files, and so forth) to formats for both
raster printers and PostScript printers. Using the Impressario host-based
PostScript interpreter, it is possible to print PostScript documents to raster
printers with performance that greatly surpasses printer-based PostScript
interpreters. Impressario also includes the PrintBox Motif widget™, a
graphical user interface (GUI) for printing.
Impressario server software contains filters and drivers for sending jobs to a
printer connected directly to a host workstation. In addition, all Impressario
printer drivers maintain status information in a globally available printer
object database.
The Impressario scanning environment provides generic scanner support.
Impressario scanner application programs and Impressario scanner drivers
run as separate executables, enabling any scanning application to interact
with all scanner drivers.
Impressario gives application developers a number of valuable resources,
including:
•

libspool, a printer spooling system abstraction library that enables
complex printing functions to be defined with only a few lines of code

•

Application programming interfaces for easy access to the end-user’s
scanning environment

•

A network-transparent version of the printer object database library
routines to inquire directly about printer configuration and status

Audience
The Impressario Programming Guide is written for the following users:

xviii

•

Printer driver developers

•

Scanner driver developers

•

Application program developers who need to print or scan from their
applications

New Features

New Features
The 1.2 release of Impressario contains the following new features:
•

Networked scanner support; scan from scanners not directly attached
to your machine

•

Support for large color prints (the newly added HP DesignJet 650C®
supports color plots up to 36” x 44”)

•

Support for 48-bit color scanners; true 16-bits/channel color image
support

•

Inclusion of the Silicon Graphics Image format library (libimp), an
ANSI-compliant, clean, and optimized library that supports all 8-bit to
48-bit Silicon Graphics Image formats

•

More image file formats; automatically views and prints TIFF™, GIF™,
PBM, PGM, PPM, Silicon Graphics Image RGB, FIT, PhotoCD™, and
JPEG formats. Rotate, mirror, gamma-adjust and resize any of these
image types. Drag-and-drop them all onto your printers
Note: Be sure your server is running 1.2.

•

Complete backward compatibility with IRIX™ 4.0.5 Impressario 1.1.
Support for IRIX 4.0.5 clients with IRIX 5.2 servers, IRIX 5.2 clients with
IRIX 4.0.5 servers

How to Use This Guide
Since this guide has four separate audiences, the list provided below gives
the areas of most interest to each user:
•

Printer driver developers should read chapters 1–6, 10, 11, and 12.

•

Printer application program developers should read chapters 1, 6,
and 12.

•

Scanner driver developers should read chapters 1, 2, 7–9, 11, and 12.

•

Scanner application program developers should read chapters 1, 2, 9,
and 12.

xix

Introduction

Style Conventions
The followings conventions are intended to help make information easy to
access and understand:
italic

Used for arguments in a command line that you replace
with a valid value. In text it indicates an argument, button,
command, document title, filename, function, glossary
item, new term, or variable. For example:
The phandler program is an example driver.
The NAME variable identifies the printer name.

bold

Used for constants in text. For example:
The SC_PROGFEED bit should be set.

Helvetica

Used for callouts in a figure.

Helvetica Bold Used for callouts in a figure, labels, and notes.
Courier

Used for code examples and screen displays. For instance,
the following is a code example:
int
AdvanceFeeder(SCANINFO *scan)
{
drverr = SCENOFEEDER;
return -1;
}

Courier bold Used for nonprinting keys and user input. For example:
vstiff /usr/tmp/sample.blastfile

<>

The less-than and greater-than symbols are used to enclose
arguments, parameters, and nonprinting characters (see
above).

[]

Brackets enclose optional command arguments. Do not
enter the brackets. Example:
[optional_entry]

xx

Document Overview

Document Overview
Chapter 1, “Impressario Architecture,” discusses Impressario’s printing and
scanning architectures and defines Impressario compliance for printer
driver and scanner driver developers.
Chapter 2, “Installing Impressario Software,” explains how to install the
Impressario software. It includes product-specific information that is
supplemental to the IRIS Software Installation Guide.
Chapter 3, “Printer Drivers,” provides an overview of printer driver
processing, plus a detailed analysis and discussion of an example printer
driver. The required printer filter/driver options are also covered.
Chapter 4, “Printer Model Files,” discusses the printer model files and
describes the modifications to be made by printer vendors to the printer
model file template.
Chapter 5, “Printer Graphical Options Panel,” discusses the graphical
options panel that visually showcases a printer’s features. The major topics
discussed are options handling, panel layout, development, naming,
installation, invocation, and termination.
Chapter 6, “Printing Libraries,” describes the libraries used by printer
drivers, filters, and applications. The libraries described are the libspool
library, the libprintui library, and the libpod library.
Chapter 7, “Scanner Drivers,” explains how to write a scanner driver. It
provides a detailed analysis of the template scanner driver. The major topics
are the driver template, header files, data structures, functions and macros,
and installation and testing.
Chapter 8, “Scanner-Specific Options,” discusses how to implement
scanner-specific options for a scanner driver. The major topics are options,
the scanner driver interface, perspectives, and installation and testing.
Chapter 9, “Generic Scanner Interface,” describes a generic interface
between a scanner driver and an application program. The major topics are
the coordinate system for scanning, data structures, and data type
conventions.

xxi

Introduction

Chapter 10, “Testing for Impressario Compatibility,” explains how to use the
programs that test printing compatibility with the Impressario environment.
It explains how to test Impressario printing compatibility, an Impressario
printer, and an Impressario printer software installation.
Chapter 11, “Packaging Your Impressario Product,” explains how to
package the Impressario software product that you have created.
Chapter 12, “Enhancing Impressario with Plug-Ins,” explains how to add
new features to the Impressario open architecture. The major topics are how
the Impressario file conversion pipeline works, how to add a new filetype to
Impressario, and how to use an alternate PostScript RIP.
Appendix A, “Stream TIFF Data Format,” describes the Stream TIFF file
format, the primary interchange file format between printer filters and
drivers, and libstiff, a C-language application programming interface used to
read and write Stream TIFF files. Stream TIFF is also used by gscan(1) to store
images in TIFF files and to scan to the screen (in conjunction with vstiff(1)).
Appendix B, “Silicon Graphics Image File Format API,” describes libimp, the
C-language API for reading and writing Silicon Graphics Image format files.
The image processing features of libimp are also described.
Appendix C, “Printer Object Database (POD) File Formats,” defines the file
formats for printer configuration, status, and log files in the POD. The major
topics are general syntax, input parsing rules for libpod files, printer
configuration file format, and printer status file format.
Appendix D, “Transition Notes,” explains how migrate from Impressario 1.1
software to 1.2 and from Impressario 1.0 software to 1.2. It also explains how
Impressario application developers and filter/driver developers can take
advantage of the new features in Impressario 1.2.
Appendix E, “Scanner Driver Architecture,” describes the architecture of a
scanner driver and discusses the template scanner driver, required and
optional functions, and queues and multi-threaded scanner drivers.
Appendix F, “Man Pages,” lists all Impressario online man pages: general
interest, printer developers, and scanner developers.

xxii

Related Publications

Related Publications
Online Books
The following books, available online through Silicon Graphics, contain
information related to Impressario:
•

IRIX Programming Guide, Volumes I and II, Silicon Graphics, Inc.

•

IRIS Indigo Magic Integration Guide, Silicon Graphics, Inc

•

IRIS Advanced Site and Server Administration Guide, Silicon Graphics, Inc.

•

IRIX Device Drivers Programming Guide, Silicon Graphics, Inc.

•

IRIX Device Drivers Reference Pages, Silicon Graphics, Inc.

•

X Library Programming Guide, Volume I, O’Reilly & Associates

•

X Window™ System, Volume 4, O’Reilly & Associates

•

Motif™ Programmer’s Guide, Prentice-Hall, Inc.

•

Motif Reference Manual, Prentice-Hall, Inc.

•

Motif Style Guide, Prentice-Hall, Inc.

•

Impressario Programming Guide, Silicon Graphics, Inc.

•

Impressario User’s Guide, Silicon Graphics, Inc.

Online Release Notes
After installing online documentation, you can view the Impressario Release
Notes. If you have a graphics system, select “Release Notes” from the Tools
submenu of the Toolchest to display the grelnotes graphical browser. Refer to
the grelnotes(1) man page for information on options to this command. If you
do not have a graphics system, you can use the relnotes command. Refer to
the relnotes(1) man page for accessing the online release notes.

xxiii

Introduction

Adding the product name to the relnotes command displays the table of
contents for that product’s release notes. For example:
% relnotes Impressario
The chapters for the “Impressario” product’s release notes are:
chap title
1 Introduction
2 Installation Information
3 Changes and Additions
4 Bug Fixes
5 Known Problems and Workarounds
6 Documentation Errors
Use “/usr/sbin/relnotes productname chapter” to view a chapter

Online Man Pages
Appendix F lists the man pages provided online with Impressario. To access
the online man pages, type:
man page-name

Release Identification Information
The Impressario release identification information is listed below:

xxiv

•

Version number: 1.2

•

Product code Impressario Server: SC4-IMPS-1.2 CD

•

Product code Impressario Developer’s Kit: SC4-IMPD-1.2 CD

•

Additional printer copy of Impressario Programming Guide:
M4-IMPD-1.2

•

System software requirements: IRIX 5.2 or later

Chapter 1

Impressario Architecture

This chapter gives an overview of
Impressario’s printing and scanning
architectures. It also explains how to
write Impressario compliant printer
drivers and scanner drivers. By
complying with Impressario guidelines,
you make your job easier, ensure a
consistent end-user experience, and
greatly improve the chances of effortless
transitions to future Impressario
releases.

Chapter 1

1.

Impressario Architecture

This chapter discusses the Impressario printing and scanning architectures
and defines Impressario compliance for printer driver and scanner driver
developers. By complying with Impressario guidelines, you make your job
easier, you ensure a consistent end-user experience, and you greatly improve
the chances of effortless transitions to future releases of Impressario.
The topics discussed in this chapter are:
•

“Impressario Printing Architecture” on page 3

•

“Compliance for Printer Driver Developers” on page 4

•

“Printing Application Programming Interfaces” on page 6

•

“Printing Application Development” on page 10

•

“Impressario Scanning Architecture” on page 11

•

“Scanner Driver Development” on page 13

•

“Scanner Application Development” on page 13

1

Impressario Architecture

Overview
Impressario allows files of different types to be printed on any installed
printer and images to be scanned from a scanner, an IRIS screen, or a Silicon
Graphics Image file. A visual end-user environment makes it easy for users
to add new devices and for applications to take advantage of those devices
by providing graphical interfaces for:
•

Installing printers (printers)

•

Modifying printer settings (PrintPanel or printers)

•

Checking printer status (PrintStatus)

•

Submitting print jobs from applications (PrintBox widget)

•

Installing scanners (scanners)

•

Using scanners (gscan)

To maintain a consistent, reliable, and easy-to-use environment, Impressario
provides the following libraries for application developers:
•

libspool—a C-language application programming interface (API) to the
UNIX printer spooling system

•

libprintui—a C-language graphical user interface (GUI) library for
printing that is compatible with Motif

•

libpod—a C-language application programming interface to the Printer
Object Database (POD)

•

libscan—a C-language application programming interface to the
Impressario scanning system

•

libstiff—a C-language application programming interface for reading
and writing Stream TIFF (STIFF) files

•

libimp—a C-language application programming interface for reading
and writing Silicon Graphics Image files

The following final, crucial elements must be provided by driver developers:

2

•

For printers—a compliant printer driver that reports printer status
through libpod and, optionally, a graphical options panel

•

For scanners—a scanner driver for the driver side of the generic
scanner interface and, optionally, a scanner-specific options panel

Impressario Printing Architecture

Impressario Printing Architecture
This section describes the steps that developers of printer drivers and
printing applications must take to comply with Impressario specifications.
Figure 1-1 is an overview of Impressario printing components. A more
detailed version of this diagram is available online in /usr/impressario/doc.
End-User
Workstation (Client)

Printing Host (Server)

End-User Printing
Environment

Spooler Interface File
Printer Filter/Driver

Printer Installer
(printers)

device query

device status events

Printer Status
Panel
(PrintStatus)

job
status Spooling
System
(SVR 3)
print
job

Print Request
Panel
(PrintPanel)

device
config
(libpod)

print
job

job
status

print
job

Device and Job
Status Database
(libpod)
ASCII
Text

Line Printer
Emulator

Bitmap
Images

Image File
Interpreter

PostScript

Display
PostScript

job
status

Application
Printing API
(libspool)
Printing GUI
(libprintui)

Figure 1-1

Device Configuration Database
(libpod)

device characteristics

printer-specific
communication
protocol
Physical
Printing Device

Impressario Printing Architecture

The following sections detail the steps that should be followed to achieve
Impressario compliance for printer drivers and printing applications.

3

Impressario Architecture

Compliance for Printer Driver Developers
Follow the steps shown in Figure 1-2 and discussed after the flowchart to
develop and integrate a printer driver for Impressario.

step 1

Develop
printer driver
(required)

step 2

Provide
POD files
(required)

See Appendix C, “Printer Object Database
(POD) File Formats,” for detailed information.

step 3

Create
model file
(required)

See Chapter 4, “Printer Model Files,” for detailed
information and instructions.

step 4

Provide data
filters
(as needed)

step 5

Create graphical
options panel
(recommended)

step 6

Package software
for distribution
(required)

See Chapter 11, “Packaging Your Impressario Product,”
for detailed information.

step 7

Verify product
on server
(required)

See Chapter 10, “Testing for Impressario Compatibility,”
for detailed information.

Figure 1-2

See Chapter 3, “Printer Drivers,”
for detailed instructions.

See “Filter/Driver Specification” in Chapter 3
for more information.

See Chapter 5, “Printer Graphical Options Panel,”
for detailed information.

Printer Driver Development Flowchart

Step 1 – Develop Printer Driver (Required)

Your printer driver must comply with the Impressario Filter/Driver
Specification (see “Filter/Driver Specification” in Chapter 3) so that a model
file that is Impressario compliant will execute the driver correctly. This
specification describes standard driver behavior and the command-line
arguments that must be processed. See /usr/impressario/src/drivers and

4

Impressario Printing Architecture

Chapter 3 for the source code and an example driver. The driver must
update the POD files through calls to “local” functions of the library libpod.
(See Chapter 6, “Printing Libraries.”) The formats of the POD files are
described in Appendix C, “Printer Object Database (POD) File Formats.”
Step 2 – Provide POD Files (Required)

A set of POD files consists of a configuration file, a printer log file, and a
printer status file. Each POD file has the same base name as the printer
model file. The extensions on these files are: .config, .log, and .status,
respectively. To create these files, start with the example set of POD files in
the directory /usr/impressario/src/data. The POD files you create must be
installed in the directory /usr/lib/print/data when you install your software.
See Chapter 11, “Packaging Your Impressario Product,” for more
information.
Step 3 – Create Model File (Required)

Your model file must conform to the Impressario model file specification.
This is done by starting with the template model file provided with
Impressario and adding the vendor-specific processing. Model files must be
installed in /var/spool/lp/model. Follow the Impressario model file template to
create a model file that properly updates the desktop printer status icon and
interacts properly with Impressario subsystems. (See Chapter 4, “Printer
Model Files,” for more information on model files.)
Step 4 – Provide Data Filters (As Needed)

Filters must conform to the filter/driver specification. (See “Filter/Driver
Specification” in Chapter 3 for more information.) Filter programs must be
installed in /usr/lib/print. It is recommended that any data filtering be
performed directly by the driver. (Filters are programs that change the
format of a data file; drivers communicate bidirectionally with the printer.)
See chapter 12 for step-by-step instructions on adding new file conversion
filters.

5

Impressario Architecture

Step 5 – Create Graphical Options Panel (Recommended)

This step is optional, but it is strongly recommended that you showcase the
features of your printer by providing a graphical options panel program.
(See Chapter 5, “Printer Graphical Options Panel,” for details.)
Step 6 – Package Software for Distribution (Required)

Package your Impressario software product for distribution. See Chapter 11
for detailed information.
Step 7 – Verify Product on Server (Required)

Check that your product media will install the printer support files you have
developed on an Impressario server. Run the Impressario test programs
testipr(1) and testiconfig(1) to assist in verifying the installation. See
Chapter 10 for detailed information.

Printing Application Programming Interfaces
To print a document on UNIX systems, you must submit a print job to one
of the available spooling systems: the BSD spooling system (lpr command)
or the System V spooling system (lp command). The System V spooling
system is the default spooling system on all SGI workstations. Figure 1-3
shows the general Impressario spooling architecture for the lp spooler. Note
that only one of the two paths shown below (PostScript printer or raster
printer) would apply. That is, the output is either to a PostScript printer or a
raster printer.

6

Impressario Printing Architecture

PostScript, Silicon Graphics Image,
GIF, TIFF, ISO text, PBM, PGM,
PPM, RGB, FIT, PhotoCD, JPEG

printerspecific
options

lp
command

handle printerspecific options

stiff2ps, sgi2ps
and lptops filters

stiff2ps, sgi2ps, lptops,
and psrip filters
STIFF
data

PostScript
data
PostScript
driver

PostScript
printer

Figure 1-3

POD
status
database

Raster
driver

Raster
printer

General Filter/Driver Architecture

Before Impressario, a true application programming interface to the BSD
and System V spooling systems was not available. Programmers had to
create their own application programming interface or execute the lp or lpr
command from their application.

7

Impressario Architecture

Impressario provides the application programming interfaces listed in
Table 1-1 and described below.
Printing Application Programming Interfaces

Table 1-1
API

Interfaces to

Function

libspool

System V, BSD Allows submittal of a file or buffer to a printer.

libprintui System V only Provides a Motif PrintBox widget for printing from your
application.
libpod

System V, BSD Gets status information on the printers currently
available.

libspool API

In its simplest form, libspool allows you to submit a file or buffer to a printer.
It also gives you control of spooling system options and printer-specific
options.
libprintui API

The API libprintui is built on top of libspool. The libprintui library contains a
widget, compatible with Motif, that you can incorporate directly into your
application. If your Motif application needs printing capabilities, libprintui
will provide you with all of the basic functionality for submitting a print job
as well as access to setting and saving printer-specific options. As mentioned
earlier, libprintui interfaces only with the System V spooling system.
libpod API

The libpod library is built on top of libspool and an ancillary system daemon,
podd. The libpod library allows you to obtain detailed information about the
capabilities of the printers currently available on the system. You can also get
detailed status information about the printers. Most applications will not
need to use libpod; however, for those that do, libpod provides a very
powerful, network-transparent interface.
Figure 1-4 shows the relationship between an application program, the
Impressario APIs, and the System V spooling system.

8

Impressario Printing Architecture

Application

glp

libpod

libprintui

libspool

System V (lp command)

Figure 1-4

System V Spooling System Interface

Figure 1-5 shows the relationship between an application program, the
Impressario libspool API, and the BSD spooling system.

Application

libspool

BSD (lpr command)

Figure 1-5

BSD Spooling System Interface

glp (PrintPanel)

The “print” subsystem available with the IRIX operating system contains the
program glp, a graphical standalone print job submittal tool. While not a true
API, glp can be used by your application to submit print jobs. It is a
standalone wrapper around the PrintBox Motif widget in libprintui.

9

Impressario Architecture

Printing Application Development
The following Impressario application printing solutions are available:
•

Perform non-graphical print functions via libspool
Use libspool, the spooling system abstraction library, for all
non-graphical interaction with the BSD or System V spooling system.
The libspool library functions perform a large amount of work to ensure
successful spooling system interaction, work that a developer may not
wish to reproduce.

•

Perform graphical print functions via libprintui
Use the PrintBox Motif widget provided by the libprintui library for
graphical print job submittal. The widget provides a consistent job
submittal dialog across all applications and greatly reduces the amount
of development effort required. If you use this library, you don’t need
to use libspool directly. libprintui encapsulates those calls.

•

Obtain printer status via libpod (optional)
Use libpod library calls to get printer status, configuration, and log
information. Status queries must be made through libpod calls; attempts
to obtain this information through other means has unpredictable
results. In most cases, application developers should use the
“standard” forms of the libpod functions (the “local” forms of the
functions are for use by printer driver developers and are not
network-transparent).

•

Submit graphical print jobs via glp
If you are not using Motif, you may use glp to graphical submit print
jobs from your application. If you use this method, you should have a
prerequisite on the print software package (shipped with IRIX 5.2 and
later). While this method works, it is not recommended, as it is likely to
be less efficient than using libprintui.

10

Impressario Scanning Architecture

Impressario Scanning Architecture
This section describes the steps you must follow to comply with the
Impressario specifications for scanner driver developers and scanner
application developers.
Figure 1-6 illustrates the run-time components of the Impressario scanner
architecture. Note that scanner applications, scanner-specific options
programs, and scanner drivers all link with libscan.a, which has separate
modules for scanner applications and for scanner drivers.

Scanner
application

Generic
scanner
API

libscan
Scanner
application
modules

Scanner
IPC
calls

Scannerspecific
options

Interprocess
communication
Scanner
driver API
libscan
Scanner
driver
modules

Main (IPC)
module
Callback
functions

Scannerspecific
module

Figure 1-6

Scanner Run-Time Components

The main and scanner-specific modules of a scanner driver both register
callback functions with libscan.

11

Impressario Architecture

Figure 1-7 shows the interprocess communication of the Impressario
scanner architecture.

Scan commands and results
UNIX domain socketpair

Pass file descriptors
UNIX domain socketpair
Scanner
Application

Scan data is written by the scanner
driver to the file descriptor passed
to it by the application

Scanner
Driver

Shared Memory Area
• Access control semaphores
• Scanning status area
• Status change notification

Figure 1-7

Interprocess Scanner Communication

The following sections describe the steps that should be followed to achieve
Impressario compliance for scanner drivers and applications.

12

Impressario Scanning Architecture

Scanner Driver Development
Follow these steps to develop and integrate a scanner driver that complies
with Impressario:
1.

Develop the scanner driver. See Chapter 7, “Scanner Drivers,” and
Chapter 8, “Scanner-Specific Options,” for detailed instructions.

2.

Create a graphical options panel. This step is optional, but it is
recommended that you showcase the features of your scanner through
this mechanism. See Chapter 8, “Scanner-Specific Options,” for detailed
instructions.

3.

Create distribution media that will install the driver on an Impressario
client. Be sure to check that the media will install the scanner support
files you have developed on an Impressario client. See Chapter 11 for
detailed information.

Scanner Application Development
There are two ways to interact with the scanning system: through libscan, the
scanning system abstraction library, or by using gscan as a “plug-in” module
from an application.
When given the -p option, gscan writes STIFF data to its standard output.
Using libstiff, your application can obtain scanned data by reading the
standard output of gscan. (See Appendix A for more information about
STIFF.)

13

Chapter 2

Installing Impressario Software

This chapter explains how to install the
Impressario Developer’s Kit software. It
gives product-specific information that
supplements the IRIS Software
Installation Guide.

Chapter 2

2.

Installing Impressario Software

This chapter explains how to install the Impressario Developer’s Kit
software. It gives product-specific information that supplements the IRIS
Software Installation Guide. This chapter should be used in conjunction with
the IRIS Software Installation Guide to install the Impressario software.
The topics discussed in this chapter are:
•

“Impressario Subsystems” on page 18

•

“Installation Software Prerequisites” on page 20

•

“Disk Space Requirements” on page 20

•

“Installation Method” on page 20

•

“Software Compatibility” on page 23

Note: See the Impressario Release Notes for the most up-to-date information
on installing the Impressario software.

17

Installing Impressario Software

Impressario Subsystems
Impressario consists of two software products: a server and a developer’s
kit. One or more of the subsystems listed below are on your distribution
media.
The Impressario server includes the following subsystems:

18

impr_base.man.relnotes

Release notes for Impressario 1.2.

impr_base.man.impr

Manual pages for the base Impressario
software.

impr_base.books.user

Impressario online User’s Guide.

impr_base.sw.impr

Impressario base software. Contains
general utilities used by both client and
server.

impr_base.sw.il_image

PhotoCD, TIFF, and FIT image support.

impr_fonts.sw.adobe22

Additional 22 Adobe Type 1 fonts.

impr_fonts.man.gifts

Manual pages for font installation tools.

impr_fonts.sw.gifts

Unsupported font installation tools.

impr_scan.man.impr

Manual pages for the scanner software.

impr_scan.sw.impr

Impressario scanner software. Contains
end-user utilities for installing and using
scanners.

impr_scan.sw.epson

Scanner driver for the Epson GT-6000®.

impr_scan.sw.hp

Scanner driver for the HP ScanJet IIc® and
IIcx®.

impr_scan.sw.ricoh

Scanner driver for the Ricoh FS1®.

impr_scan.sw.sharpscsi

Scanner driver for the Sharp JX 320®.

impr_scan.sw.utek

Scanner driver for the MicroTek ScanMaker
600ZS®.

impr_server.man.impr

Manual pages for the server software.

impr_server.sw.impr

Software that must be installed on the
server.

Impressario Subsystems

impr_server.sw.laserwriter

Driver for the Apple LaserWriter® printers.

impr_rip.man.impr

Manual pages for the PostScript interpreter.

impr_rip.sw.impr

PostScript interpreter software and support
files.

impr_rip_printers.man.designjet Manual pages for the HP DesignJet 650C
printer.
impr_rip_printers.man.deskjet

Manual pages for the HP DeskJet® and
PaintJet® printers.

impr_rip_printers.man.laserjet

Manual pages for the HP LaserJet®
printers.

impr_rip_printers.sw.designjet

Driver for the HP DesignJet 650C printer.

impr_rip_printers.sw.deskjet

Driver for the HP DeskJet and PaintJet
printers.

impr_rip_printers.sw.laserjet

Driver for the HP LaserJet printers.

The Impressario Developer’s Kit includes all of the subsystems found on the
Impressario server plus these subsystems:
impr_dev.books.developer Online Impressario Programming Guide.
impr_dev.man.impr

Manual pages for the developer’s kit.

impr_dev.man.print

Manual pages for the printer-specific portions of
the developer’s kit.

impr_dev.man.scan

Manual pages for the scanner-specific portions of
the developer’s kit.

impr_dev.man.scan

Manual pages for the scanner-specific portions of
the developer’s kit.

impr_dev.sw.impr

Base developer’s kit software.

impr_dev.sw.print

Printer developer’s kit software.

impr_dev.sw.scan

Scanner developer’s kit software.

impr_dev.sw.tests

Developer test programs.

19

Installing Impressario Software

Installation Software Prerequisites
Your workstation must be running IRIX 5.2 or later with the Indigo Magic™
desktop to use release 1.2 of Impressario. To determine the IRIX system
release, enter the command:
uname -a

impr_base.sw.il_images requires part of the il_eoe system. See the Impressario
Release Notes for a complete list of Impressario prerequisites.
Note: The dps_eoe subsystem is provided to new Silicon Graphics customers

in the IRIX system software release. Upgrade customers might need to
obtain the Display PostScript executable option (product code SC4-DPS-1.0
for CD-ROM or ST4-DPS-1.0 for tape).

Disk Space Requirements
See the Impressario Release Notes for current disk space requirements.
If you are installing Impressario for the first time, the subsystems marked
“default” are those that are installed if you use the go command. To install a
different set of subsystems, use the install, remove, keep, and step commands
in inst to customize the list of subsystems to be installed, then select the go
command.

Installation Method
To install Impressario, do the following:

20

1.

Install the Impressario software on your system.

2.

Connect the printer or scanner to the system.

3.

Configure the Impressario software for use with the printer or scanner.

Installation Method

Installing Impressario Software
All of the subsystems for Impressario can be installed using IRIX on a
running system. You do not need to use the miniroot. Refer to the IRIS
Software Installation Guide for complete installation instructions.
If you have Impressario 1.0.1 and PhaserPrint for Impressario 1.0 installed,
you must explicitly load the products impr_rip and impr_fonts on your
Impressario server system. These products are not installed by default.

Connecting the Printer or Scanner
To physically connect your printer or scanner, follow the instructions
provided by the manufacturer.
Printer Support

Impressario 1.2 includes support for the following printers:
•

Apple LaserWriter Plus®, II®, IINT®, IINTX®, IIf®, and IIg®

•

Hewlett-Packard DesignJet 650C

•

Hewlett-Packard DeskJet 500C, 550C, 1200C®

•

Hewlett-Packard PaintJet XL300®

•

Hewlett-Packard LaserJet IIP®, IIP+®, III®, IIIP®, 4®, 4P®, and 4L®

Note: All Apple LaserWriter printers must be connected to the system using
a serial port. All Hewlett-Packard printers must be connected to the system
using a parallel port.

21

Installing Impressario Software

Scanner Support

Impressario includes support for the following scanners:
•

Hewlett-Packard ScanJet IIc and IIcx

•

Ricoh FS1

•

MicroTek ScanMaker 600 ZS

•

Sharp JX 320

•

Epson GT 6000

See the Impressario Release Notes for additional information on specific
hardware installation limitations.

Configuring the Impressario Software
Printer Configuration

Impressario printer software is configured using the Printer Manager tool
that comes with the IRIS System Manager. Printer Manager can be accessed
from the Toolchest System menu. See the Personal System Administration
Guide for details on installing printers.
Note: All existing printers, including networked printers, must be deleted

and reinstalled using the Printer Manager.
Networked printers can no longer be accessed via multiple levels of
indirection. When using the Printer Manager to add a networked printer,
only the printers directly connected to the specified host machine are
displayed.
Scanner Configuration

Impressario scanner software is configured using the Scanner Manager tool
that comes with Impressario. The Scanner Manager can be accessed from
either the System Manager or a shell. See the Impressario User’s Guide for
details on installing scanners.

22

Software Compatibility

Software Compatibility
Impressario is not compatible with TranScript™ printer model files,
although you may continue to use enscript(1) to format text files to be
submitted for printing. Impressario 1.2 includes a replacement for enscript(1)
called imprint(1). We recommend you remove TranScript before installing
Impressario by typing:
versions remove trans

The Apple LaserWriter drivers included with TranScript do not comply with
the Impressario system and do not return status information about the
printer. In addition, installing Impressario moves the TranScript model file
psinterface to the directory /var/spool/lp/model/OBSOLETE, thereby removing
it from use by the Printer Manager. LaserWriters using the TranScript drivers
must be deleted with the Printer Manager and reinstalled using the
appropriate Impressario driver.

23

Chapter 3

Printer Drivers

This chapter provides an overview of
printer driver processing, followed by a
detailed analysis and discussion of an
example printer driver. The required
printer filter/driver options are also
covered.

Chapter 3

3.

Printer Drivers

This chapter provides an overview of printer driver processing, followed by
a detailed analysis and discussion of an example printer driver. The required
printer filter/driver options and the reserved and unreserved printer
filter/driver options are also covered.
The topics discussed in this chapter are:
•

“Printer Driver Processing” on page 28

•

“Printer Driver Example” on page 29

•

“Filter/Driver Specification” on page 32

Note: Printer application developers need not read chapters 3 through 5, but
can skip to chapter 6.

Overview
A printer driver must perform the following tasks:
1.

Receive and process an input file.

2.

Send formatted data to the printer.

3.

Query and receive printer status information.

4.

Read and write the printer object database (POD) files.

All printer drivers must read the POD files to determine printer-specific
defaults and to maintain the active status file of the POD so that other clients
can determine printer status. Chapter 6, “Printing Libraries,” describes
libpod, the library that provides an API to the POD. Appendix C, “Printer
Object Database (POD) File Formats,” defines the file formats for the printer
configuration file, the printer status file, and the printer log file in the POD.

27

Printer Drivers

Printer Driver Processing
Figure 3-1 is an overview of printer driver processing. Note that this is a
simplified overview; the actual steps might be more complex.

Start

Report empty
input data error

yes

Read and parse
command-line
options

Update status
to Busy

Verify input file
or input stream

Read
input data

Input
file/stream
empty?

Convert data to
printer-specific
format

no
Exit

Connect to
printer, check
printer status

Do necessary
cleanup tasks

Start sending
data to printer

yes

Printing
done?
no

Update printer
status to Idle

Printer
fault?
yes

Exit

Figure 3-1

28

Report printer
fault

Printer Driver Processing Overview

no

Printer Driver Example

Printer Driver Example
Two example printer drivers are provided: laserjet for HP LaserJet printers
and phandler for generic parallel printers. The source code files for laserjet are
in the directory /usr/impressario/src/drivers/laserjet and the source code files
for phandler are in the directory /usr/impressario/src/drivers/phandler. Both
drivers follow the steps shown in Figure 3-1, but the laserjet driver is more
complex because it also performs data compression. Since this added
complexity is not necessary for our examples, we will focus on the phandler
driver example in this session.
The example printer driver phandler checks the status of the parallel port
while passing data through to the printer. It treats the input as a byte stream
and updates the printer status database at various stages of processing.
Among the include files in this program is pod.h, which contains printer
status error codes and other defines related to printing. The include file plp.h
contains information related to the parallel port.

Program Invocation
The command-line interface for phandler is:
phandler -P printer_name [-e] [-s] [-w] [-D...] [-L logfile]
[-R][-B bufsize] [filename]
Arguments:

-P printer_name Name of the installed printer (required).
-e

Exit immediately on error. The default is not to exit on error.

-s

Update printer status only and return.

-w

Suppress warning messages.

-D

Enable debugging. -D is the lowest level of detail, -D -D is
the second level, and -D -D -D is the highest level of detail.
The debugging information is written to the log file.

-L logfile

Specify the log file for debugging information and errors.
The default log file is standard error, which is redirected to
the spooler log file by the SVR3 lp spooler.

29

Printer Drivers

-R

Reset the parallel port before sending data.

-B bufsize

Set the byte size of the internal transfer buffer. The default
is 1024 bytes. Larger buffers enable more page buffering,
which may free upstream filters to do more processing
while data is being sent to the printer.

filename

Specify the name of the file sent to the printer. The default is
to read the data from standard input.

Program Processing
This section is a detailed discussion of the phandler driver. A more detailed
example driver is supplied in the /usr/impressario/src/drivers/laserjet directory.
Note: The Impressario guidelines strictly require drivers to retry errors.

Error exits are to be avoided whenever possible so that print jobs do not
disappear before the user has a chance to fix the error condition.
Initial Processing

1.

Parse the command-line arguments with getopts.

2.

Read the printer status file. If phandler cannot open the status file, it
exits with an error message.

3.

Write the active status defaults to the printer status file.

Open Printer Port

30

1.

Open the port. If there is an error and you requested exit on error when
invoking phandler, then the program writes an error message and exits.
Otherwise, when an error occurs, the program will continue trying to
open the port. It checks every n seconds (where n is the value of
error_retry_wait) and writes an error message to the .log file after each
failed attempt to open the port.

2.

If phandler successfully opens the port, it updates the current printer
status to “Busy” in the printer active status file. If the command line
contained the -s option (status only), then phandler exits after updating
the status. (The kernel closes the port when it exits the program.)

Printer Driver Example

Reset Port If Requested

1.

If the command line contained the -R option (reset the parallel port
before sending data), then reset the parallel port.

2.

If any level of debugging information was requested, write the message
“Resetting parallel port...” to errfile along with the program name.

3.

If an error occurs, and if exit on error was requested with the -e option,
then the program writes an error message and exits. Otherwise, the
program prints the message “Could not reset the parallel port” to errfile,
along with the program name, and waits for error_retry_wait seconds
before retrying.

Allocate and Set Up Buffer

Allocate and set up the buffer. If phandler cannot allocate the buffer, the
program exits with an error message. (We exit only because memory
allocation errors are very rarely recoverable.)
Update libpod Status

Use the fork(2) system call to create a child that updates the printer status.
Read, Process, and Send Data to Printer

1.

Read status from the printer.

2.

Update the printer status configuration file.

3.

Begin reading from the input and sending data to the parallel port.

Your driver will probably need to process the input data into an appropriate
printable format before sending the data to the printer.
4.

If an unrecoverable error occurs while writing to the parallel port, write
an error message to the log, write the faulted state to the printer status
configuration file, and exit.

5.

If the input file is empty or unreadable, write an error message to the
log, update the status file, and exit.

31

Printer Drivers

The driver uses signal handling to ensure that it is not interrupted in “critical
regions,” during which an interrupt could destroy vital files or the printer
state.
Cleanup and Exit

When printing is complete, update the printer status configuration file to
“Idle,” terminate the child status process, and exit.

Filter/Driver Specification
The command-line options listed in this section must be implemented as
specified for any printing filter or driver to be compatible with Impressario.
Switch letters have been chosen to maximize the intuitive correlation with
function. Additional functionality beyond that listed here must use
unreserved switch settings. Please note the following points:
•

All switches are case sensitive. That is, -P does not have the same
meaning as -p.

•

Printer drivers must accept and ignore all reserved options that are not
supported.

•

Printer drivers must conform to getopts conventions. (See getopts(2) for
more information.)

•

Multiple options on a single line have right-to-left precedence. For
example:
-n 1 -n 2

has the same effect as
-n 2

32

•

Drivers must accept and parse command-line options when included
as part of the STIFF image header. See the laserjet example driver and
Appendix A, “Stream TIFF Data Format,” for more details.

•

A good example is the header containing a number-of-copies command,
such as would be generated by a PostScript #copies command.

Filter/Driver Specification

Required Options
These switches must be supported by all drivers:
-e

Exit immediately on fault without waiting for faults to clear.
The default behavior is to wait indefinitely for faults to
clear, polling the device at the error-retry intervals specified
in the POD config file. This option is used when only a quick
query should be done.

-s

Update the status file. Exit only after successfully updating
the status file. This switch has the highest precedence. If the
-e switch is given, exit after one try at reading status.

-w

Do not report warnings in the status file. Report errors only.

-D

Enable debugging information. Optionally, more -D
switches increase the level of debugging detail. For
example, entering
-D -D

enables a second level of debugging detail. At least one
level of debugging must be supported.
-P string

The value of string defines the printer name. The printer
name is used to find the POD. The printer name is the name
given to the printer at installation time. See the libpod(3)
man page for more information. This option is also a
required option whenever the driver is invoked.

Impressario printer drivers must read the libpod printer object database to:
1.

Determine defaults.

2.

Maintain the active status portion of the POD database.

3.

Enable other clients to determine printer status.

Reserved Options
The following switches are reserved and are to be implemented by drivers
whose hardware supports them, or by inline filters that process the options
before the driver is invoked. You need not implement all options, but every
driver must accept or ignore any unimplemented options on this list.

33

Printer Drivers

Raster-specific options include:
-f

Flip the image, as if in a mirror. The image is rotated
horizontally about the y-axis. Useful for transparencies or
decals.

-p int

Scale the image as if it were being printed on a device with
the designated resolution specified in pixels per inch. This
is a convenience switch, since the same effect can be
obtained by computing the appropriate scale factor for the
image size and destination resolution.

-r int

Rotate the image counter-clockwise by an angle specified in
degrees. Values outside the range 0..359 should be accepted
and modulo converted to a value between 0..359.

-z float

Zoom the image using proportional scaling, where the
floating-point argument is nonnegative. Some values are:
0.0 – do not zoom the image
0.5 – fill half of one page
1.0 – fill one page
Note that the image aspect ratio must be preserved. Future
implementations may extend this to multiple pages. For
example, 2.0 would fill a 2-by-2 page array.

Engine-specific options include:

34

-q int

Quality mode. Set the engine-specific quality mode. This
should be a nonnegative integer, with greater values
indicating higher quality.

-n int

The number of copies to be printed, a positive integer.

-t

Generate a test print. The test print should confirm that all
marking media are present and functional.

-m int

Manual feed request. Wait MediaWaitTimeout seconds for
manual feed. Give up after MediaWaitTimeout seconds and
print anyway on the available media. See the POD for these
values. Giving up is important for shared printers.

-o int

Request a specific output media type:
0 = paper or a reflective media
1 = transparency media

Filter/Driver Specification

Other media types may be supported; see the libpod(4) man
pages.
Output-specific options include:
-L filename

Log errors to filename instead of standard error. The file
specified should be opened in append mode. If the file
cannot be opened, errors should be reported to standard
error instead.

-O filename

Output data to filename instead of the device port or standard
output. The file specified should be opened. If the file cannot
be opened, data should instead be written to the device or
standard output, as appropriate. If this option is used, all
status reporting is disabled, since the printer driver is not
communicating with the actual device.

Unreserved Options
The switches listed below are not reserved and can be used for
device-specific options:
•

Lowercase:

a, b, c, d, g, h, i, j, k, l, u, v, x, y

•

Uppercase:

A, B, C, E, F, G, H, I, J, K, M, N, Q, R, S, T, U, V, W, X, Y, Z

35

Chapter 4

Printer Model Files

This chapter discusses the printer model
files and describes the modifications that
must be made by printer vendors to the
printer model file template.

Chapter 4

4.

Printer Model Files

This chapter discusses the printer model files and describes the
modifications to be made by printer vendors to the printer model file
template.
The major topics discussed in this chapter are:
•

“Overview” on page 40

•

“Command-Line Arguments” on page 40

•

“Template Model File Execution” on page 41

•

“Printer-Specific Options” on page 45

•

“Vendor-Supplied Model File Additions” on page 47

39

Printer Model Files

Overview
Model files are Bourne shell scripts that form an interface between the
System VR 3 spooling system and the printer. Each printer has its own model
file, which is customized by the printer installation tools when the printer is
installed. The customized copy of the printer model file is called the interface
file. The interface file is invoked by the System VR3 spooling scheduler
lpsched(1M) when the printer is ready to accept a new print job. The interface
file sets up printer-specific options, calls filters, and invokes the printer
driver.
System V model files differ greatly from BSD /etc/printcap entries. The reader
unfamiliar with System V spooling should refer to the IRIX Advanced Site and
Server Administration Guide for more information.

Command-Line Arguments
The model file expects the following command-line arguments from lpsched
in the order listed:
1

Job sequence ID number

2

User login name

3

Job title

4

Number of copies to be printed

5

-o options (printer options)

6-n

Name(s) of file(s) to be printed

The end user does not invoke the model file manually; it is invoked only
through lpsched. If you want to check for gross syntax errors, this can be done
quickly by running the model file with dummy arguments; for example:
laserjet_model a b c d e

Not all errors can be found this way, since the model file does not run to
completion, but this does provide a quick test for gross syntax errors. If
errors are found, putting the -x flag at the end of the first line in the model
file may help debug the error. See the sh(1) man pages for more details on
debugging Bourne shell scripts.

40

Template Model File Execution

Template Model File Execution
This section explains how the Impressario model files work.
The source code for the template laserjet_model file is located in the directory
/usr/impressario/src/models. The main steps in the template model file are
shown below and described in more detail in the following sections:
1.

Define global and external variables and convenience functions.

2.

Interpret and store the command-line options.

3.

Verify that the prerequisites are in place.

4.

Invoke the driver to update the POD status file with the current printer
state and the current job setting. This is important; all filters use the
status file to determine what parameters to use. The driver must ensure
that the POD status file is absolutely up to date before the first filter is
run, or a change in printer status between jobs could compromise the
next job.

5.

Start the active icon tagging subprocess.

6.

If pages stack face down, print a banner page if requested.

7.

Use filters to convert the submitted file to the data type required by the
printer driver.

8.

Invoke the printer driver with the converted data.

9.

Repeat steps 7 and 8 for each file to be printed and report any errors
encountered to stderr.

10. If pages stack face up, print a banner page if requested.
11. Clean up after the job and exit with an appropriate exit code.

41

Printer Model Files

Variable Declaration
Note that variable names are in all uppercase letters. Those variables are
exported for use by the filters invoked when converting input files into
printable data. See the fileconvert(1) man page for more information.
1.

Define NAME and TYPE. If the type is not defined, then the model file
writes an error message and exits.

2.

Append all filter and driver standard error output to the spooler log
file.

3.

Define file and directory paths and Boolean flags used in the model file.

4.

Define locations and options for all filters. (The model file checks to
make sure that the printer-specific driver exists and that the spooler log
file is writable. If not, the model file writes an error message and exits.)

Convenience Functions
The next portion of the model file contains various convenience functions
used within the model file. The convenience functions listed in Table 4-1 are
routines contained within the model file. These routines are used for parsing
the -o options and for various utility functions.
Table 4-1

42

Convenience Functions

Function Name

Description

BeginTagging

Sets up the tagging job that begins monitoring the printer
status.

CleanUpAfterJob

Does any cleanup needed at end of job.

EndTagging

Ends tagging of the printer.

ParseOptions

Parses the -o command-line options and sets appropriate
variables. Expects the command-line options string as
argument 1.

PrintBannerPage

Prints a banner page.

PrintMessage

Prints its arguments as text on the printer. Used to report
errors to the user. Accepts any number of arguments.

Template Model File Execution

Table 4-1 (continued)

Convenience Functions

Function Name

Description

ReportBadFile

Reports unknown file type to the printer and to the
spooler log. Expects the filename as argument 1 and the
file type as argument 2.

ReportUnknownOption Reports an error message when an unknown option is
parsed. Expects the unknown option as argument 1.
SetCancelTrap

Sets up the trap command for the signals SIGHUP,

SIGINT, and SIGTERM.
SetDebug

Turns on debug mode for all filters and drivers.

TestExitStatus

Interprets exit status from last command and sends error
message to both the spooler log and the printer if needed.
Expects the exit code of the last command as argument 1,
a string describing the last command as argument 2, and
the file in question as argument 3.

Process Command-Line Arguments
1.

Retrieve the command-line arguments.

2.

Parse the options passed with the -o switch.

3.

Call the printer status and communications driver to update the status
database before job filtering begins.

4.

Set up the cancellation signal handler to handle SIGHUP, SIGINT, and
SIGTERM. This allows use to cater the job cancellation signal sent by
the spooler and clean up.

5.

If the verbose switch is set, send a message to the spooler log that the
job has begun filtering.

6.

Start the tagging subprocess to tag the printer’s workspace icon with
the appropriate print-engine type and status.

Banner Page
A banner page is printed if the banner switch is set. (The banner page may be
printed last for faceup stacking printers.)

43

Printer Model Files

File Processing
1.

fileconvert(1) automatically determines the file type of each file using the
Indigo Magic file typing rule database. (See ftr(1) and fileconvert(1).) If a
fast text path exists, and the user has not requested options that require
the slower path, then the file is converted using the fast text path.
Otherwise, the normal fileconvert path is used. See the template model
file for specifics.

2.

fileconvert produces a shell command string that, when executed,
produces the requested data type on standard output.

3.

If the file could not be converted, ReportBadFile is called, otherwise the
fileconvert shell program is excluded and the output piped to the printer
driver.

4.

TestExitStatus is called to test whether the driver reported an error.

Cleanup and Exit

44

1.

After printing is complete, any additional cleanup needed is
performed.

2.

End the tagging subprocess.

3.

Append an ending message to the log file if the debug switch is set.

4.

If there were unsupported file types in the list of files to be processed,
the model file exits with a well-known error code.

Printer-Specific Options

Printer-Specific Options
The -o option to the spooler allows model files to accept a variety of
non-spooler options. These are the options specified with -o on the lp(1)
command line. It is these options that are produced by the graphical printer
options panel.
Impressario defines a number of general file filtering options for the
convenience of the end user, and reserves those option names.
The reserved options are listed in Table 4-2 in alphabetical order. Their
meanings may not be changed by vendors. Vendors should choose short but
understandable option names for any additional options. These options may
be seen by end users, so they should not be too verbose.
Table 4-2

Reserved Option Names

Name

Description

banner

Prints a banner page.

bestfit

Uses the best fit orientation for image files (defaults to “on”).

bottommargin Sets the bottom margin size for text.
columns

Sets the number of columns on the page for text.

debug

Causes filters to report debug information (defaults to “off”).

flip

Flips the image, producing a mirror image.

fontname

Uses a specified font name for text.

fontsize

Uses a specified font size for text.

gamma

Uses a specified value for image gamma correction.

gaudy

Uses a fancy page header for formatted text.

landscape

Uses landscape page orientation for text.

leftmargin

Sets the left margin size for text.

nobanner

Sets the “do not print a banner page” option.

nogaudy

Sets the “do not use fancy page header for formatted text” option.

45

Printer Model Files

Table 4-2 (continued)

Reserved Option Names

Name

Description

noverbose

Sets the “do not print verbose messages in the spooler log file”
option (same as the -h option).

numberpages

Sets the number of text pages.

papersize

Selects the paper size.

portrait

Uses portrait page orientation for text.

ppi

Scales the final image size to match the specified original image
resolution, in pixels per inch.

psevenpage

Prints even pages only (PostScript).

psoddpage

Prints odd pages only (PostScript).

pspagerange

Prints the specified page range (PostScript).

psreversepage Reverses the PostScript page order.

46

resolution

Sets x and y resolutions (for resolution-switchable printers).

reversepages

Reverses text document page order (that is, print last page first).

rightmargin

Sets right margin size for text.

rotate

Rotates the image clockwise an integer number of degrees.

topmargin

Sets the top margin size for text.

verbose

Records debug messages in the spooler log file.

zoom

Scales the image to fit the page (defaults to 1.0 scale).

Vendor-Supplied Model File Additions

Vendor-Supplied Model File Additions
Printer vendors must customize the model file template supplied by Silicon
Graphics to the specifications of their printers. The template model is located
in the file /usr/impressario/src/models/template_model. This code is the same as
the code in the laserjet_model file so that developers will have a working,
debugged example from which to begin.
The following ten items must be specified by the vendor. They are listed and
explained in the order in which they appear in the model file template.
1.

Printer name.

2.

Device interface.

3.

Printer type.

4.

GUI class.

5.

Printer-specific filter/driver.

6.

Debug routine.

7.

Cleanup routine.

8.

Printer-specific banner page.

9.

Printer-specific filtering options.

10. Fast path for text.
Note: All items that must be modified by the vendor have been marked with
an “#XXX” in the model file. Search for and remove these markers as you
progress to be sure all necessary modifications have been made.

Printer Name
The NAME variable identifies the real printer name, such as “HP DeskJet
500C.” It appears twice in each model file: once in the comments parsed by
the printer install tools and once in the actual interface program code. We
refer here only to the first, comment instance of NAME. The NAME is the
string that is presented to the end user in the Printer Manager’s graphical
printer install tool. Multiple NAME variables are allowed on separate lines
if the model file can support more than one printer.

47

Printer Model Files

Device Interface
The DEVICE variable identifies the hardware interface where the printer is
attached. The value is used by the printer install tool to present models by
connection type. Multiple connections are supported. (Use multiple lines for
multiple devices; that is, simply repeat the line for each different device.) The
values currently allowed are SERIAL, CENTRONICS, SCSI, and
REMOTE. Obsolete types that should not be used are VERSATEC and TEK.

Printer Type
The TYPE variable identifies the printer type. This information is used by the
Print Manger, routeprint, libspool functions, and other system software,
including the active icons subsystem. Table 4-3 shows the values allowed for
the TYPE variable. Obsolete types are: Dumb, Color, and PostScript.
Table 4-3

Printer Type Specifications

TYPE

Data Types Accepted

Printer Examples

Raster

At least text, SGI, PostScript

HP LaserJet

ColorRaster

At least text, SGI, PostScript

Tektronix Phaser II SX

Plotter

HP-GL only

HP 7550A

ColorPostScript

At least text, SGI, PostScript

Tektronix Phaser II PXi

MonoPostScript

At least text, SGI, PostScript

LaserWriter II NTX

GUI Class
The value of this variable is the name of the resource file for the graphical
options panel. This value must match the GUI_CLASS define in the options
panel gui_class.h. If an options panel is not provided, do not specify a value
for this variable.

48

Vendor-Supplied Model File Additions

Printer-Specific Filter/Driver
The file laserjet.c contains an example of a complete printer driver. This
driver is used in the /usr/impressario/src/models/laserjet_model file. Also, see
the /usr/impressario/src/models/template_model.README file for comments
about the model file.

Debug Routine
To turn on debugging on vendor-supplied filters, modify SetDebug() to turn
on the debug switch (-D) for each vendor-supplied filter.

Cleanup Routine
Some vendors may need to perform some cleanup at the end of each job. If
needed, add this cleanup to the routine CleanUpAfterJob() in the model file.
The use of temporary or intermediate files is strongly discouraged.

Printer-Specific Banner Page
It is recommended that you do not modify this routine. However, to create a
customized banner page that uses printer features such as page counts or
graphics, modify PrintBannerPage() as required. The banner page should not
unduly slow down the printing process, and customized banner pages
should include at least as much job-specific information as the default
banner page: job ID, user name, job title, date and time, and the filename(s).
If your printer is unlikely to be shared, or has high per-page costs, you may
want to turn off banner pages by default. In this case, set the variable banner
to zero (0). However, users can still choose to print a banner page.
Printers that stack pages face down should print the banner page before any
files, while those that stack pages face up should print the banner page last.
This is handled automatically if the faceup variable is set appropriately.

49

Printer Model Files

Printer-Specific Filtering Options
The ParseOptions() routine parses the -o command-line options and sets
appropriate global variables. This routine contains many general options,
and vendor-specific options can be added if required. However, Silicon
Graphics reserved words must not be duplicated by vendor-supplied
options. See “Printer-Specific Options” on page 45 for a complete,
alphabetized list of existing options.
It is recommended that any vendor-specific options be full-word names to
improve the readability of the stored settings files and to reduce name-space
conflicts. This also aids users who use command-line interfaces to printing.
However, option names should be kept brief.

Fast Path for Text
You should modify the path in the file filtering section of the model file to
use native text support if your printer supports native text printing that is
faster than using PostScript. Users, however, must still have access to all
PostScript formatting options. Do not disable the slower PostScript path.

50

Chapter 5

Printer Graphical Options Panel

This chapter explains how to implement
a graphical options panel that visually
showcases your printer’s features and
improves its usability.

Chapter 5

5.

Printer Graphical Options Panel

This chapter discusses the graphical options panel that visually showcases a
printer’s features.
The major topics discussed in this chapter are:
•

“Graphical Options Panel Layout” on page 54

•

“Options Handling” on page 56

•

“Graphical Options Panel Development” on page 56

•

“Graphical Options Panel Naming” on page 57

•

“Graphical Options Panel Installation” on page 57

•

“Invocation by the PrintBox Widget” on page 58

•

“Standalone Invocation for Testing” on page 59

•

“Termination by the PrintBox Widget” on page 59

53

Printer Graphical Options Panel

Overview
The Impressario PrintBox widget is provided for submitting print jobs from
a Motif application. This widget is contained in the library libprintui(3X). The
PrintBox widget is used by glp (PrintPanel) and a number of other
applications to provide their printing capability. In addition to providing
graphical selection of System V print job submittal options, PrintBox
provides a mechanism for graphical selection of printer-specific options.1
This mechanism is the graphical options panel.
A graphical options panel allows the printer vendor and driver developer to
showcase the unique features of a printer in an intuitive graphical panel. The
graphical options panel program is invoked by the PrintBox widget in
applications, by the end user via glp (PrintPanel), and by the Printer
Manager. The Graphical Options Panel Specification located in the
/usr/impressario/doc directory provides the information necessary to create
and integrate a graphical options panel. Graphical options panels are
standalone executable programs. They are stored in a standard directory
known to the Impressario printing tools; therefore, the graphical options
panels are automatically available to users of Impressario printing tools. The
rules for developing a graphical options panel are straightforward and do
not require any interprocess communication or similar complex procedures.
In fact, we strongly discourage any network dependencies as not every
Impressario printer is on a network.

Graphical Options Panel Layout
A graphical options panel almost always consists of a single window. This
window usually contains two main sections, an options section and an
action area. We strongly recommend that vendors keep options panels
simple to avoid both complex code and complicated documentation.
The options section contains all printer-specific option controls. This area is
often divided into groups of option controls, where each group represents a
specific input file type. Most options sections contain controls for text files,

1

54

The Printer Manager also provides access to the graphical option panel.

Graphical Options Panel Layout

bitmap image files, and PostScript files. The options section also contains a
general options section. Because there are often a large number of controls in
the options section, you should use a scrolled window to keep the graphical
options panel window to a reasonable size. Figure 5-1 shows an example of
a graphical printer options panel.

Figure 5-1

Graphical Printer Options Panel

The action area is located at the bottom of the graphical options panel
window and consists of a number of push buttons:
•

OK—output option string to stdout and terminate program (required)

•

Apply—output option string to stdout but do not terminate program
(required)

•

Cancel—terminate program without any option string output (required)

•

Help—provide printer-specific options help (may be included at your
discretion)

55

Printer Graphical Options Panel

Group buttons together on the right side of the action area. The width of all
buttons should be equal. The leftmost button should be OK followed by
Apply, Cancel, and Help. Place any additional buttons between the Apply and
Cancel buttons. Note that the supplied template makes this happen
automatically.
Note: Do not include the action area inside the scrollable options area. The

action buttons must be available to the user at all times.

Options Handling
If printer-specific options have been passed to the graphical options panel on
the command line, the program must interpret these options and initialize
its options section controls to reflect the command-line options. Those
options not recognized by the graphical options panel must be preserved
and prepended to the output option string.
When the OK or Apply button is activated, the graphical options panel
program must form a valid System V printer option string based on its GUI
settings and print this string to its standard output (stdout).

Graphical Options Panel Development
The directory /usr/impressario/src/gui_models contains example source code
for a graphical options panel. Begin with this code and add your
printer-specific options. Do not start from scratch! You will waste valuable
development time and create consistency issues. Benefit from our experience
and at least begin with the template.
Create the graphical options panel with the OSF/Motif UI™ toolkit. Starting
with Impressario 1.2, your graphical model file can have its own application
resource file. While the resource file can be given any name, it is highly
recommended that the name represent the printer model name and have its
first letter capitalized. For example, the application resource file for the HP
LaserJet graphical model file is called LaserJet. The name chosen for the
resource file must be specified in the gui_class.h header file and must also be
specified in the printer model file as the value of the GUI_CLASS variable.

56

Graphical Options Panel Naming

The resource file must be installed by your installation media in the directory
/usr/lib/X11/app-defaults.
To match the look and feel of the PrintPanel program (glp) and other
graphical options panels, the application resource file should include the
following resources:
*useSchemes:

all

*schemeFileList:

SgiSpec

*sgiMode:

True

To facilitate localization of the options panel for international customers, all
label strings and messages should be placed in the application resource file
rather than being hard-coded into the program.
The graphical model file must consist of a single executable program and its
application resource file. The graphical model files are restricted to a single
executable and resource file because the printer installation tools install only
these two files during network printer installation.

Graphical Options Panel Naming
The graphical options panel must be given the exact same name as its
printer's model file, followed by the suffix .gui. For example, if the printer
model file for an HP DeskJet 500C printer is called deskjet_model, then the
graphical options panel must be given the name deskjet_model.gui. If the
graphical options panel is given a name that differs from the model file
name, it will not be installed by the printer install tools when a new printer
is installed on a system.

Graphical Options Panel Installation
All graphical options panel programs must be installed by your installation
media in the directory /var/spool/lp/gui_model or /var/spool/lp/gui_model/ELF.
These directories are where the printer installation software searches for the
programs. COFF-executables must be installed in the directory
/usr/spool/lp/gui_model, and ELF-executables must be installed in

57

Printer Graphical Options Panel

/usr/spool/lp/gui_model/ELF.1 The executable should be owned by lp and
should be a member of the group lp. The file permissions of the executable
should be set to 0755.

Invocation by the PrintBox Widget
The graphical options panel is invoked by the PrintBox widget or the Printer
Manager. The graphical options panel is always invoked with the
command-line arguments listed in Table 5-1. Note that the options are
almost identical to those passed to your spooler model file.
Table 5-1

Command-Line Arguments

Argument

Description

argv[0]

Printer name

argv[1]

User name

argv[2]

Filename(s) string

argv[3]

Printer-specific option string (optional)

argv[4-n]

Xt options (optional)

Note that any Xt options may be specified as argv[4] or greater. If there are
no printer-specific options for argv[3], the empty string ("") is passed as
argv[3]. If no filenames are specified, the empty string is also passed as
argv[2].

1

58

All programs compiled on systems running IRIX 5.0 or greater are ELF executables.

Standalone Invocation for Testing

Standalone Invocation for Testing
To test a graphical options panel during development, it may be run as a
standalone executable from the UNIX command line. Invoke the graphical
options panel by entering:
[executable name] [any valid user name] ""

For example, if the executable program is called deskjet_model.gui, and “joe”
is a valid user name on the system, then the program can be executed from
the command line by typing:
deskjet500_model.gui joe ""

While debugging, it is often helpful to invoke the graphical options panel
from the shell, repeatedly testing the options string that is generated when
the Apply button is pushed. Once the options string is properly generated,
test for proper performance of input options parsing by invoking the
graphical options panel with various options strings, especially the strings
output by your panel. Be especially sure that all widgets are set properly
upon panel startup when passed a string that sets options to non-default
values.

Termination by the PrintBox Widget
Applications will terminate the graphical options panel using a SIGHUP
signal. The graphical options panel should exit promptly upon receipt of this
signal.

Additional Information
For additional information, please read the online specification found in
/usr/impressario/doc/gui_model.spec.
These panels should be very easy to create when you start from the template.
If you find them difficult, take another look at the template documentation
and the convenience routines in the support files. You may have overlooked
something we have already solved for you.

59

Chapter 6

Printing Libraries

This chapter describes the printing
libraries used by Impressario printer
drivers, filters, and applications.

Chapter 6

6.

Printing Libraries

This chapter describes the printing libraries used by Impressario printer
drivers, filters, and applications.
The three printing libraries are described in this chapter:
•

“The libspool Library” on page 64 is a C-language application
programming interface (API) to the UNIX printer spooling systems.

•

“The libprintui Library” on page 67 is a C-language API to the PrintBox
widget that is compatible with Motif.

•

“The libpod Library” on page 73 is a C-language API to the printer
object database (POD).

In addition to the above libraries, there are two libraries described in the
appendices that are also used by printer drivers and filters:
•

Appendix A, “Stream TIFF Data Format,” describes libstiff, a
C-language API for reading and writing the STIFF (Stream TIFF) data
file format.

•

Appendix B, “Silicon Graphics Image File Format API,” describes
libimp, a C-language API for reading and writing Silicon Graphics
Image format files.

63

Printing Libraries

The libspool Library
The libspool Library is a C-language application programming interface
(API) to the UNIX printer spooling systems. There are two common UNIX
printer spooling systems, System V and Berkeley Software Distribution
(BSD). While both of these spooling systems provide essentially the same
capabilities, each has its own command set and neither provides a
C-language API. The libspool library provides a single, common API to both
spooling systems. The functions provided by libspool include submittal and
cancellation of print jobs and control and reading of print queues.

Compiling Programs with libspool
Programs that call libspool functions must include spool.h, the header file in
the /usr/include directory. The programs must also link with the libspool.a
library located in /usr/lib. Use the following include directive:
#include 

Here is an example of the complete cc compiler command line:
cc -o myprog myprog.c -lspool

64

The libspool Library

libspool Library Functions
Table 6-1 lists the libspool functions by purpose.
Table 6-1

Summary of libspool Functions

Purpose

Function Name

Spooling System Selection
Set the default spooling system

SLSetSpooler

Get the default spooling system and available
systems

SLGetSpooler

Printer Information
Get the list of registered printers

SLGetPrinterList

Return information about a single printer

SLGetPrinterInfo

Get the name of the default printer

SLGetDefPrinterName

Get spooler and printer settings information

SLGetPrinterSettings

Option Management
Get System V spooler options

SLSysVGetSpoolerOptions

Get System V printer options

SLSysVGetPrinterOptions

Save System V spooler options

SLSysVSaveSpoolerOptions

Save System V printer options

SLSysVSavePrinterOptions

Print Job Submittal
Submit a print job

SLSubmitJob

Submit the contents of the file specified by a file
descriptor for printing

SLSubmitJobFd

Submit the contents of the specified buffer for
printing

SLSubmitJobBuf

Submit a print job using default values for all
printing options

SLSubmitJobSimple

65

Printing Libraries

Table 6-1

Summary of libspool Functions

Purpose

Function Name

Print Job Cancellation
Cancel a queued printer job

SLCancelJob

Printer Queue Information
Report the printer queue contents

SLGetQueue

Printer Queue Control
Set the spooling system printing and queueing
state

SLSetSpoolerState

Get the spooling system printing and queueing
state

SLGetSpoolerState

Execution Error Handling

66

Print a libspool execution error message to
standard error

SLPerror

Obtain a libspool execution error message

SLErrorString

Get spooling system error information

SLGetSpoolerError

The libprintui Library

The libprintui Library
The libprintui library is library implementing a graphical user interface (GUI)
for printing. This library provides PrintBox, a complete print job submittal
solution in a single widget that is compatible with Motif, for application
developers. This eliminates the need for application developers to develop a
unique printing solution for each application, thereby saving considerable
time and effort and making it easier to provide a robust and complete
printing interface for application data.
Using the PrintBox widget in an application benefits the end user in several
ways. First, PrintBox provides a consistent interface to the printer spooling
system across the variety of applications on Silicon Graphics systems.
Second, users can set print job options, such as number of copies, through a
graphical interface, rather than through obscure command-line option flags.
Finally, PrintBox uses the printer graphical options panel to provide a
mechanism for the setting and saving of printer-specific options.
The PrintBox widget can be used in a number of different configurations and
can accept a child manager widget to allow the display of applicationspecific options. The widget provides built-in System V print job submittal
via the libspool library. (See “The libspool Library” on page 64 for more
information.) The developer can also perform application-specific
processing before a job is submitted to the printing system. A variety of
callback lists provide user and spooling system feedback. A print job can be
submitted as a filename, as a file descriptor, or as a pointer to the buffer. The
default form of PrintBox includes the following items:
•

A print file entry text field (for file-based jobs)

•

A scrolling list of available printers

•

Print option controls

•

The following action-area push buttons:
Print

Submits the specified file or buffer for printing by the
spooling system.

More Options ... Accesses the graphical options panel for the currently
selected printer.
Save Options ... Saves printer and spooling system options.

67

Printing Libraries

Cancel

Normally used to pop down the PrintBox widget when
the widget is used as a pop-up dialog.

Help

Calls the functions on the helpCallback list.

There are also four unmanaged buttons, User1 through User4, positioned
between the Print and More Options ... buttons. These buttons are invisible by
default; the buttons become visible when explicitly managed. The PrintBox
widget also accepts one child as a work area. This area can be used for
application-specific printing controls such as page range.

Example Widget Configurations
Figure 6-1 through Figure 6-4 illustrate four widget configurations:
•

Default configuration

•

No filename entry

•

No options

•

With a child

Figure 6-1

68

PrintBox Widget – Default Configuration

The libprintui Library

Figure 6-2

PrintBox Widget – No Filename Entry Box

Figure 6-3

PrintBox Widget – No Options Box

69

Printing Libraries

Figure 6-4

PrintBox Widget – With a Child

Compiling Programs with libprintui
Programs that call the libprintui functions must include the header file
/usr/include/Sgm/PrintBox.h and must link with the following libraries in the
order shown:
... -lprintui -lspool -lXm -lXt -lXll -lgen ...

The link order is important for proper link-time name resolution.
Note: Programs that subclass off the PrintBox widget must also include

/usr/include/Sgm/PrintBoxP.h.

70

The libprintui Library

Library Functions Listed by Purpose
The libprintui functions are listed in Table 6-2. The PuiPrintBox(3X) man
pages provide detailed information on the PrintBox widget.
Table 6-2

Summary of libprintui Functions

Function Name

Purpose

Widget Instantiation
PuiCreatePrintBox

Create a PrintBox widget

PuiCreatePrintDialog

Create a PrintBox dialog

Widget Component Access
PuiPrintBoxGetChild

Access a PrintBox widget component

Widget Action Functions
PuiPrintBoxDoPrint

Invoke PrintBox printing

Example Program
The example program, printbox, simply instantiates a PrintBox widget. The
directory /usr/impressario/src/examples/libprintui contains the source code for
this program, while the directory /usr/impressario/bin/examples/libprintui
contains the executable version.
To invoke the example program, type:
printbox

Initial Program Processing

The printbox program begins by setting the program instance name and
initializing the X Window System™ applications connection. Next, the
program creates the PrintBox widget with a call to the libprintui library
function PuiCreatePrintBox. This widget is then added to the parent’s
managed set.

71

Printing Libraries

Add Callbacks

The program now adds the following callbacks:
•

The Cancel button exit routine

•

A help dialog display

•

A routine to print job information and the job ID to standard output
and terminate the program

•

A display of error messages from the PrintBox widget (this uses the
function SLGetSpoolerError from the libspool library)

Realize All Widgets

A call to XtRealizeWidget now realizes the parent widget from the earlier call
to PuiCreatePrintBox and all child widgets.
Process Events

The program now begins an event loop. It obtains the next event from the X
event queue then dispatches the event. If an early error has occurred, the
error is handled and the loop continues until the application exits.
Additional Examples

Refer to the directory /usr/impressario/src/examples/libprintui for additional
sample program source code.

72

The libpod Library

The libpod Library
The libpod library provides printer driver developers with an API to create
and maintain a Printer Object Database (POD) and provides application
developers with the means to acquire detailed information about a printer,
even across the network. A POD contains information on the current printer
configuration, status, and job history of a single printer. Each printer
physically installed on a system maintains its own POD on that system. All
interaction with a printer’s POD must be done through the libpod API. Do
not modify the POD files directly. To create an initial set of POD files, refer to
Appendix C, “Printer Object Database (POD) File Formats,” and the
examples provided in /usr/impressario/src/data.

POD Files
A POD consists of three separate ASCII text files. The name of each POD file
is formed from the printer name, followed by one of these suffixes: .config,
.status, or .log. The name and contents of each file are as follows:
[printer_name].config

The configuration file contains detailed information
on the printer’s capabilities. Examples include the
supported paper sizes and available fonts. The initial
version of this file is manually created by the printer
driver developer, and a copy is installed when the
printer is added to the system. The contents of this
file are maintained by the system administrator
using the printer administration tools. Normally this
file is never changed.

[printer_name].status

The status file contains information about the current
operational status of the printer. The information in
this file indicates whether the printer is busy, the type
of printing media installed, detailed error codes (if
errors have occurred), and so on. The contents of this
file change during the course of every print job.

[printer_name].log

The log file contains the print job history for the
printer. Information for old jobs as well as the current
print job is maintained. Typically, printer filters and
drivers append information to the log file while
general applications treat the file as read-only.

73

Printing Libraries

The global variable PDpod_path indicates the location of the POD files. The
default location for POD files is /var/spool/lp/pod. If POD files are to be located
in a directory other than the default, set PDpod_path to the pathname of the
new location. PDpod_path is declared in the header file pod.h.1
See Appendix C, “Printer Object Database (POD) File Formats,” for detailed
information on libpod file formats.

Standard and Local libpod Functions
The POD files reside on the system to which the printer is physically
connected. This system is referred to as the printer host. Therefore, to
provide information about a printer located on another system, libpod must
be able to communicate across the network. The “standard” form of the
libpod functions automatically determines whether the specified printer is
located on the user’s system (a local printer) or on a remote system (a remote
printer). After determining where the printer is located, the standard libpod
functions access the POD files on the appropriate system. Typically, user
application programs such as printer status tools use the standard form of
the libpod functions, since it is likely that these programs need to work with
remote printers.
Since network communication carries a certain amount of performance
overhead, libpod also provides the “local” functions for use by programs that
are guaranteed to be run on the printer host. These functions include the
word “Local” in the function name (for example, PDLocalReadInfo,
PDLocalWriteStatus). A printer driver is an example of a program that should
use local libpod functions.
Functions that write to POD files are available only in local form. Only
printer drivers will need to write to the POD files, and printer drivers are
always located on the printer host. Thus there is no need to provide writing
capabilities to the standard libpod functions that are designed for use from
remote machines.

1

74

The maximum string length for PDpod_path is PD_STR_MAX. This length includes the terminating NULL
character.

The libpod Library

There are several advantages to using the local libpod functions for programs
that will always be run on the printer host. The local libpod functions have no
networking overhead; they always go directly to the POD files on the local
machine. This reduces the size and overhead of the resulting executable.

Compiling Programs with libpod
Programs that call libpod functions must include the header file pod.h, which
is located in the directory /usr/include. The programs must also link with the
library libpod.a located in /usr/lib. In addition, programs that use the standard
libpod functions must link with libspool.a. Programs that use only the local
libpod functions need not link with this additional library.
The compile line for the standard case is:
cc -o myprog myprog.c -lpod -lspool

The compile line for the local case is:
cc -o myprog myprog.c -lpod

Debugging with libpod
If the global variable PDdebug is set to a nonzero value, libpod functions will
print debugging information to standard error during execution. The global
variable PDdebug is declared in the header file pod.h.

Network Communications
To provide remote printer POD information, libpod communicates over the
network with the podd(1M) daemon on the remote machine. Since the
network or remote machine may be unreachable when a libpod function is
executed, a time-out may occur and the function will return an appropriate
error code. The time-out period can be specified by setting the global
variable PDnet_timeout to a value in seconds. The default time-out period is
shown in the header file pod.h. While a larger time-out period is appropriate
when reading printer status, a much smaller time-out may be appropriate
for browsing printer configurations. For more information on the daemon,
refer to the podd(1M) man page.

75

Printing Libraries

Library Functions Listed by Purpose
The libpod functions are listed in Table 6-3. Note that a number of libpod
functions have only a single version, which is used for both standard and
local cases.
Table 6-3

Summary of libpod Functions

Task

Standard Function

Local Function

Detailed Information Retrieval PDReadInfo

PDLocalReadInfo
PDLocalWriteInfo

Status File Manipulation

PDLocalReadStatus
PDLocalWriteStatus
PDLocalReadOpStatus

PDReadStatus
PDReadOpStatus

Log File Manipulation
Convenience Functions

PDReadLog

PDLocalReadLog
PDLocalWriteLog

PDMakeMessage

n/a
n/a
n/a
n/a
n/a

PDFindPageSize
PDGetSizeCodeByName
PDGetNameBySizeCode

PDGetCurrentResolution n/a
Execution Error Handling

76

PDError

n/a

PDErrorString

n/a

Chapter 7

Scanner Drivers

This chapter discusses scanner driver
development. It provides a detailed
analysis of the template scanner driver.

Chapter 7

7.

Scanner Drivers

This chapter discusses scanner driver development. It provides a detailed
analysis of the template scanner driver.
The following major topics are discussed:
•

“Driver Template” on page 80

•

“Header Files” on page 80

•

“Data Structures” on page 81

•

“Functions You Must Write” on page 86

•

“Events” on page 95

•

“Installation” on page 97

•

“Testing” on page 98

The information presented in this chapter should be enough to write a
scanner driver. However, if you wish to know more, Appendix E, “Scanner
Driver Architecture,” is an in-depth discussion of the architecture of a
scanner driver.

79

Scanner Drivers

Driver Template
The source code files for the template scanner driver are in the directory
/usr/impressario/src/scan/template_driver. This template has code to handle all
the interprocess communication necessary for well-behaved scanner drivers
(see Chapter 9, “Generic Scanner Interface”).
To develop a new scanner driver, start by copying the template files to the
directory where you will be developing the driver. The ONLY files that you
need to modify are scan.c and Makefile; DO NOT modify any of the other files
unless you are familiar with the information in Appendix E.
This document refers to the main.c module, which implements the
interprocess communication part of a scanner driver and should not be
modified, and scan.c, which you should modify to support the scanner for
which you are writing a driver.

Header Files
There are four header files in /usr/include that scanner driver developers will
find useful:

80

scanner.h

Defines the interface used by application programmers to
communicate with scanner drivers. Contains typedefs and
#defines needed to communicate with the application.

scandrv.h

Contains the dispatch loop interface, some error messages,
and the queue utility routines.

scanipc.h

Contains #defines for command numbers and the types of
arguments and results.

scanconv.h

Contains prototypes for functions that convert between
data types and functions that do replicative zooming on
rows of image data.

Data Structures

Data Structures
The following data structures are used to communicate between scanner
driver template modules. Understanding each field is key to understanding
what your part of the driver (the code in scan.c) must do. These data
structures are defined in /usr/impressario/src/scan/template_driver/scan.h.

SCANINFO Data Structure
The SCANINFO data structure is used to store static information about a
scanner. The scan.c module uses SCANINFO to communicate with the main.c
module. The SCANINFO data structure is defined as follows:
typedef struct tag_scaninfo {
int metric;
float pagex, pagey, pagewidth, pageheight;
float minxres, maxxres, minyres, maxyres;
float *xres, *yres;
int nres;
int canZoom;
SCDATATYPE *types;
int ntypes;
SCANFUNC *options;
int noptions;
void *priv;
SCFEEDERFLAGS feederFlags;
} SCANINFO;

/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*

metric for res, page size*/
page size */
resolution bounds */
resolution arrays */
size of arrays */
1 if scanner can zoom */
supported types */
number of types */
scanner-specific options */
number of options */
private member */
feeder flags */

Field definitions:

metric

Set metric to SC_INCHES or SC_CENTIM, depending on
whether it is more convenient to have measurements and
resolutions expressed in terms of inches or centimeters.

pagex, pagey, pagewidth, pageheight
pagex and pagey are the coordinates of the upper left corner
of the scannable area (almost always 0 and 0). pagewidth and
pageheight are the width and height of the scannable area,
respectively. All four fields are expressed in the units
defined by the metric field.

81

Scanner Drivers

minxres, maxxres, minyres, maxyres
minxres is the smallest supported horizontal resolution,
maxxres is the largest supported horizontal resolution,
minyres is the smallest supported vertical resolution, and
maxyres is the largest supported vertical resolution. These
are all expressed in pixels per the unit expressed by the
metric field.
xres, yres, nres

For scanners that support discrete resolutions (as opposed
to scanners that support ALL resolutions with equal quality,
within the bounds given above), xres and yres are arrays of
the supported resolutions in the horizontal and vertical
directions. nres is the number of elements in each of these
arrays.
For scanners that support arbitrary resolutions (that is,
scanners that do their own scaling), nres is 0. The main.c
module takes nres == 0 to signify that it doesn't need to do
any scaling of scan data to satisfy preview requests from
the scanning application.

canZoom

This parameter specifies whether or not the scanner can
support resolutions other than those specified in the xres
and yres arrays when nres is nonzero. In this case, the
resolutions in the xres and yres arrays represent preferred
resolutions that results in superior image quality.
If nres is 0, the main.c module assumes that the scanner
itself can do zooming, regardless of the canZoom flag.

types, ntypes

types is an array of SCDATATYPE structures (see Chapter 9,
“Generic Scanner Interface”), and ntypes is the number of
types supported by the scanner.

options, noptions
This array of functions implements scanner-specific options
for this scanner (see Chapter 8, “Scanner-Specific Options”),
and noptions is the number of such options.
priv

82

This parameter is used by the scan.c module (the one you
write) to store a pointer to whatever state information is
necessary to identify a particular scanner once it's been
opened. This is provided so that you can avoid the use of
global variables in the scan.c module.

Data Structures

feederFlags

These flags indicate the presence of an automatic document
feeder. The SC_HASFEEDER bit (see /usr/include/scanner.h)
of this flag should be set if a feeder is attached to the scanner
being supported. The SC_AUTOFEED flag should be set if
each call to DoScan automatically results in the next sheet of
paper being fed. If the scanner can feed on demand, the
SC_PROGFEED bit should be set. It is not an error to have
the SC_AUTOFEED flag and the SC_PROGFEED flag both
set.
If the scanner being supported does not have a document
feeder, this member can be safely ignored and the main.c
module will not try to call any of the document feeder
functions (see below).

SCANPARAMS Data Structure
The SCANPARAMS data structure contains dynamic values used to specify
the parameters of a scanning operation, and also some administrative
details. The SCANPARAMS data structure is defined as follows:
typedef struct tag_scanparams {
float xres, yres;
float x, y, width, height;
SCDATATYPE type;
int preview;
SCQUEUE *scanq, *sfreeq;
int xpixels, ylines, xbytes;
void (*convert)(void *from, int fromx, void *to, int tox, int *zmap);
int maxmem; /* maximum amount of memory to allocate */
int readlines;
SCANINFO *s;
} SCANPARAMS;

The fields of the SCANPARAMS data structure are defined as follows:
xres, yres

The scanning resolution to be used for a particular scan. The
main.c module will always ensure that these resolutions are
among those advertised in the xres and yres fields of the
SCANINFO struct, unless the canZoom field of the

83

Scanner Drivers

SCANINFO struct is nonzero or the nres field is 0. In any
case, xres and yres are always within the resolution bounds
specified in the SCANINFO struct.
xres and yres are expressed in dots per the unit specified in
the metric field of the SCANINFO struct.
x, y, width, height
The horizontal (x) and vertical (y) coordinates of the upper
left corner of the window to be scanned and its width and
height. The main.c module ensures that this image falls
within the bounds of the pagex, pagey, pagewidth, and
pageheight fields of the SCANINFO struct.
x, y, width, and height are expressed in the units specified in
the metric field of the SCANINFO struct.
type

The type of scan data expected. The main.c module ensures
that it is one of the types specified in the types field of the
SCANINFO struct.

preview

This field is set to 1 if this is a preview scan, and 0 otherwise.

scanq, sfreeq

sfreeq is a queue whose elements are free buffers to put
scanned data into, and scanq is a queue whose elements are
buffers that have scanned data in them. DoScan, which you
will write (see below), removes buffers from sfreeq, scans the
data into them, then adds them to scanq. The main.c module
is responsible for taking buffers from scanq, disposing of the
data appropriately, and putting them back on sfreeq.

xpixels, ylines, xbytes
The number of pixels in a scan line, the number of scan lines
in the scan, and the number of bytes in a scan line. The scan.c
module is responsible for calculating these values in
SetupScan, which you will write (see below).
void (*convert)(void *from, int fromx, void *to, int tox, int *zmap)
This function converts data from a type that the scanner
supports to the requested data type. If the scanner directly
supports all the data types that are being advertised to the
scanning application (the types field of the SCANINFO
struct), the scan.c module can ignore this field.

84

Data Structures

For example, this function can be used for color scanners
that return the red, green, and blue components of each
scan line separately; that is, a line of five pixels would have
the following layout:
RRRRRGGGGGBBBBB

This needs to be converted to “chunky” data, as shown
below:
RGBRGBRGBRGBRGB

To do this, simply set the convert field to
SCBandRGB8ToPixelRGB8 in SetupScan (see below). The
following functions are available in libscan for converting:
SCBandRGB8ToPixelRGB8
SCGrey8ToMono
SCBandRGB8ToMono

maxmem

The maximum amount of memory that should be allocated
for storing scan data. This field is to be taken into account in
the calculation of readlines in SetupScan (see below).

readlines

The number of lines to read at a time. readlines is the
maxmem field divided by the xbytes field if scanning is
benefited by scanning in large chunks. If there is no benefit,
the number is 1.
The problem with maxmem/xbytes is that when maxmem is
large, interactive feedback to the user of the scanning
application is limited. Ideally, the scanner buffers data
internally, so you can scan perhaps an inch at a time
without the scan head pausing. That way, the scanning
application can consume the scan data while the scan head
gets the rest of the data.

s

A pointer to the SCANINFO struct that OpenScanner
returned (see below).

85

Scanner Drivers

Functions You Must Write
After copying the template to your build area, you must edit the file scan.c
and implement the functions listed in Table 7-1.
These functions are described in detail in the following sections.
Table 7-1

Functions to Be Written by the Driver Developer

Function Name

Description

OpenScanner

Opens the scanner

SetupScan

Called before a scanning operation

DoScan

Gets data from the scanner

SetFeederFlags

Called when the scanner application calls SCFeederSetFlags(3)

AdvanceFeeder

Advances feeder to next document

FeederReady

Tests whether the feeder is ready to feed another document

PrintID

Prints a string describing the type of scanning supported

FindScanners

Prints device for supported scanners

InstallScanner

Installs a new scanner

DeleteScanner

Deletes a scanner

OpenScanner Function

This function is called when the driver is first invoked.
Example:
SCANINFO *
OpenScanner(char *dev)
{
static SCANINFO scan;
/*
Your code here!
*/

86

Functions You Must Write

if (something goes wrong) {
drverr = appropriate error code;
return NULL;
}
*/
return &scan;
}

dev is the name of the device (usually a device special file in /dev/scsi for SCSI
devices) to open in order to communicate with the scanner. The task of the
OpenScanner function is to “open” dev, make sure that it corresponds to a
device that scan.c knows how to talk to, get it into some reasonable initial
state, and fill in a SCANINFO structure for the scanner. If all goes well, a
pointer to the SCANINFO structure is returned.
If anything goes wrong, OpenScanner should set the global variable drverr
and return NULL. The value for drverr should be chosen from those in
/usr/include/sys/errno.h or /usr/include/scanner.h; that value is communicated
back to the scanning application, which can use the SCPerror or
SCErrorString functions in libscan.a to get a human-readable error message
that explains why OpenScanner failed.
Caution: If you are writing a driver for a SCSI scanner, and you are using
dslib(3X), make sure that you pass the O_EXCL flag defined in
/usr/include/fcntl.h to dsopen:
dsreq_t *dsp = dsopen(dev, O_RDONLY | O_EXCL);

If you pass the O_EXCL flag, the open will fail with errno set to EBUSY if dev
is the /dev/scsi device of a mounted disk; otherwise, the open can succeed and
you could really screw up the disk!
In addition, it is recommended that before issuing any other SCSI commands
you perform an inquiry command, and verify that the device is a scanner by
examining the Device Type code of the inquiry buffer (this field should be
set to 6. You can use the INV_SCANNER #define from /usr/include/invent.h).
It is also recommended that you examine the vendor and product identifiers
to make sure the device is a scanner of the type for which this driver is being
written.

87

Scanner Drivers

SetupScan Function

This function is called with a pointer to a SCANPARAMS struct to prepare
for a scanning operation.
Example:
int
SetupScan(SCANPARAMS *params)
{
/*
Your code to tell the scanner the resolution, scanning window,
and data type.
*/
/*
Your code to find out from the scanner how many pixels are in a scan
line, how many scan lines are in the scan, and how many bytes are
in a scan line.
*/
/*
Your code to figure out what readlines should be, taking into
consideration maxmem and xbytes.
*/
if (anything went wrong) {
drverr = an appropriate error code;
return -1; /* indicates failure */
}
return 0; /* indicates success */
}

SetupScan performs the following operations:

88

1.

SetupScan does whatever is necessary to anticipate the scan defined by
the fields xres, yres, x, y, width, height, and type.

2.

If type is not supported directly by the scanning device, then the convert
field should be set to a function that converts data returned from the
scanner to the appropriate type.

Functions You Must Write

3.

SetupScan queries the scanning device or does some calculations to
determine the number of pixels in a scan line, the number of scan lines
in the scan, and the number of bytes in a scan line. The xpixels, ylines,
and xbytes fields of params are set appropriately.

4.

SetupScan sets the readlines field of params to the number of lines that it
expects to scan at a time, taking maxmem and xbytes into account.

5.

If at any point something goes wrong, set drverr to a value from
/usr/include/sys/errno.h or /usr/include/scanner.h and return -1 to indicate
a failure. If all goes well, return 0 to indicate success.

DoScan Function

This function actually gets the data from the scanner.
Example:
void
DoScan(SCANPARAMS *params)
{
SCANINFO *s = params->s;
void *buf;
int row, toread, curline;
prctl(PR_TERMCHILD);
for (curline = 0; curline < params->ylines;
curline += params->readlines) {
toread = MIN(params->readlines,
params->ylines - curline);
buf = SCDequeue(params->sfreeq);
/*
* Get the scan data here!
*/
/*
* Chop the buffer up into scan line sized chunks
*/
while (toread--) {
SCEnqueue(params->scanq, buf);
buf = (char *)buf + params->xbytes;

89

Scanner Drivers

}
}
exit(0);
}

DoScan executes as its own process, sharing its address space with its parent,
which is the process that communicates with the scanning application. (See
the sproc(2) man page. DoScan is the entry parameter to sproc.)
Before entering the while loop, do whatever else is necessary to initialize the
scanner if there's unfinished business from SetupScan. Note the use of
params->readlines, which you set in SetupScan. In the body of the loop, the
following things happen:
1.

DoScan computes how many scan lines to read this time through the
loop. This is either readlines, which we set in SetupScan, or the number
of lines remaining to scan:
toread = MIN(params->readlines,
params->ylines - curline);

2.

DoScan gets a buffer from the free queue into which the data is scanned:
buf = SCDequeue(params->sfreeq);

3.

DoScan transfers toread lines of data from the scanning device to buf.
This is the interesting part, that you have to write specifically for your
scanner.

4.

DoScan puts the lines just scanned onto the scan queue. This involves
chopping up the buffer into chunks the size of a scan line. Don't worry,
main.c knows how to put the buffers back together before putting them
back on the free queue!
while (toread--) {
SCEnqueue(params->scanq, buf);
buf = (char *)buf + params->xbytes;
}

Since DoScan is its own process, it calls the exit(2) function instead of
returning when it finishes scanning. If everything goes OK, DoScan calls exit
with a status of 0. If anything goes wrong, DoScan sets the global variable
drverr to an appropriate value from sys/errno.h or scanner.h and calls exit with
a status of 1. (See the exit(2) man page.)

90

Functions You Must Write

SetFeederFlags Function

The SetFeederFlags function gets called when the scanner application calls
SCFeederSetFlags(3) to specify whether automatic (SC_AUTOFEED) or
programmatic (SC_PROGFEED) feeding is desired. This only happens if
the feederFlags member of the SCANINFO struct returned by OpenScanner
has all three of the SC_HASFEEDER, SC_AUTOFEED, and
SC_PROGFEED bits set.
Example:
int
SetFeederFlags(SCANINFO *scan, SCFEEDERFLAGS flags)
{
drverr = SCENOFEEDER;
return -1;
}

The template version of this function sets drverr to indicate that no feeder is
present; if a feeder is present, SetFeederFlags must set a flag so that it knows
whether to automatically feed the next document in the next call to DoScan.
AdvanceFeeder Function

The AdvanceFeeder function is called only if the SC_PROGFEED bit is set in
the feederFlags member of the SCANINFO struct returned by OpenScanner.
This function should advance the feeder to the next document. If the feeder
is empty or jammed, return -1 and set drverr to an appropriate error code
from /usr/include/scanner.h or /usr/include/sys/errno.h.
Example:
int
AdvanceFeeder(SCANINFO *scan)
{
drverr = SCENOFEEDER;
return -1;
}

FeederReady Function

This function is called only if the SC_HASFEEDER bit of the feederFlags field
of the SCANINFO struct returned by OpenScanner is set.

91

Scanner Drivers

Example:
int
FeederReady(SCANINFO *scan)
{
drverr = SCENOFEEDER;
return -1;
}

FeederReady should return 0 if there is a document in the feeder; that is, if the
next call to AdvanceFeeder should succeed. If the feeder is empty, FeederReady
should return -1 and set drverr to SCEFEEDEREMPTY.
PrintID Function

The PrintID function is used by the -query option that all scanner drivers
support. It should print a string that identifies the type of scanner supported
by this scanner driver, and one or more interface types supported.
scanners(1M), the scanner install tool, uses this information to help the end
user choose the driver that best suits a particular scanner.
Example:
void
PrintID(FILE *fp)
{
fprintf(fp, "Your Scanner Name\n"); /* String describing scanner */
fprintf(fp, "SCSI Serial Parallel\n"); /* Device type; can be list */
}

FindScanners Function

The FindScanners function is also used to implement the -query option.
Example:
void
FindScanners(FILE *fp)
{
inventory_t *inv;
char device[100];
dsreq_t *dsp;
/* int because it must be word aligned. */
int inqbuf[(sizeof(INQDATA) + 3)/sizeof(int)];

92

Functions You Must Write

INQDATA *inq = (INQDATA *)inqbuf;
/*
* This example looks for SCSI scanners; do whatever is necessary
* to find other types of scanner here.
*/
setinvent();
while ((inv = getinvent()) != NULL) {
if (inv->inv_class == INV_SCSI && inv->inv_type == INV_SCANNER) {
sprintf(device, "/dev/scsi/sc%dd%dl0", inv->inv_controller,
inv->inv_unit);
if ((dsp = dsopen(device, O_RDONLY)) == NULL) {
continue;
}
if (inquiry12(dsp, (char *)inq, sizeof *inq, 0) == 0
&& strncmp((char *)inq->vid, "Your vendor", 11) == 0 &&
strncmp((char *)inq->pid, "Your product", 12) == 0) {
fprintf(fp, "SCSI %s\n", device);
}
dsclose(dsp);
}
}
endinvent();
}

FindScanners should search the system for scanners that this driver is capable
of supporting, and for each such scanner it prints the type of device (SCSI,
Serial, Parallel, GPIB, EISA, or Other), a space, and the pathname that should
be passed to OpenScanner in order to access that scanner.
This gives scanners(1M) more information that it can use to help the end user
pick a driver for a particular scanner. It is by no means required that
FindScanners find all scanners that it is capable of supporting; it is OK to do
nothing at all here, especially if there is no hope of finding a scanner you
support in a reasonable amount of time. This is important; scanners(1M)
invokes EVERY scanner driver installed with the -query option when the
user adds a scanner, so this function should be fast!

93

Scanner Drivers

InstallScanner Function

This function is called when the scanner driver is invoked with the -install
option. InstallScanner is used by scanners(1M) when the user tries to install a
new scanner.
Example:
int
InstallScanner(char *dev)
{
printf("The template driver doesn't support %s\n", dev);
return -1;
}

The purpose of this entry point is verify that dev corresponds to a scanning
device that this driver knows how to support, and to do any scanner-specific
installation that is necessary.
The following example implementation calls OpenScanner to verify that dev
corresponds to a valid scanning device, and then changes the permissions of
dev so that users other than root can access the scanner. This is important,
since scanner drivers should not normally be setuid root programs, and users
other than root want to use scanners. When InstallScanner is called by
scanners(1M), the driver will have root permissions, which enables it to call
chmod(2) on dev or create any auxiliary files or other resources that it needs:
int
InstallScanner(char *dev)
{
SCANINFO *scan;
scan = OpenScanner(dev);
if (!scan) {
printf("Can't access %s: %s\n", dev,
SCErrorString(drverr));
return -1;
}
chmod(dev, 0666);
return 0;
}

94

Events

If an error occurs, InstallScanner should print an error message to stdout and
return -1. The main.c module exits with a nonzero exit status if InstallScanner
returns -1, and scanners(1M) reads the driver’s standard output and displays
it to the user if the main.c exits with a nonzero status. That way, the exact
cause of the error is propagated to the user.
DeleteScanner Function

The DeleteScanner function is called when the driver is invoked with the
-delete option by scanners(1M). This gives the driver the opportunity to do
any scanner-specific deletion required. This can be useful if auxiliary files
specific to this scanner were created in InstallScanner.
Example:
int
DeleteScanner(char *dev)
{
return 0;
}

If an error occurs, DeleteScanner prints an error message to stdout and returns
-1. In this case, scanners(1M) displays this error message to the user and
refuses to delete the scanner, so in most cases DeleteScanner should return 0.

Events
Impressario scanner drivers can send events to scanner applications.
Currently, the only type of event supported is an event to notify the scanner
application that the resolutions, page size, data types, or feeder flags
supported by the scanner driver have changed.
This typically happens when the user selects a new input media option from
the scanner specific options program (see chapter 8). For example, some
scanners have transparency units, and when scanning transparencies the
scanning page size is different than when scanning normal paper. So when
the user selects the option to scan a transparency, the scanner driver needs
to inform the scanning application that it must query to find out the new
page size.

95

Scanner Drivers

Events are sent to the scanner application by filling in an SCEVENT structure
and calling SCDriverSendEvent. The SCEVENT structure is defined as
follows:
typedef struct tag_infoChange {
unsigned int pageSizeChanged : 1;
unsigned int resolutionChanged : 1;
unsigned int dataTypesChanged : 1;
unsigned int feederFlagsChanged : 1;
} SCINFOCHANGE;
#define SCEVENT_INFOCHANGE 1
typedef struct tag_scevent {
unsigned int eventType;
union {
SCINFOCHANGE infoChange;
event;
} SCEVENT;

The SCDriverSendEvent function has the following prototype:
int SCDriverSendEvent(SCEVENT *event)

To inform the scanner application that it needs to query the new page size,
the driver would execute the following code:
SCEVENT event;
event.eventType = SCEVENT_INFOCHANGE;
event.event.infoChange.pageSizeChanged = 1;
event.event.infoChange.resolutionChanged = 0;
event.event.infoChange.dataTypesChanged = 0;
event.event.infoChange.feederFlagsChanged = 0;
if (SCDriverSendEvent(&event) == -1) {
handle error;
}

96

Installation

Installation
After the driver is built, make sure that the -query option works, then copy it
to /usr/lib/scan/drv and run scanners(1M), the scanner install tool. See
Figure 7-1.

Figure 7-1

Scanner Install Tool

When the scanners panel comes up, use the “Install...” item on the Scanner
menu to bring up the “Install New Scanner” dialog box. If you implemented
PrintID correctly, you see your scanner driver's ID string in the list. If you
implemented FindScanners, clicking on your scanner driver type should fill
in the “Device” field. Otherwise, type in the device that corresponds to your
scanner.

97

Scanner Drivers

Testing
Give the scanner a name and click OK, then run gscan(1). See Figure 7-2.

Figure 7-2

gscan Panel

You can either provide your scanner's name on the command line or use the
“Setup” menu to choose your scanner as the scanning source.
Severe scanner driver malfunctions can cause gscan to hang. If this happens,
open a shell and type:
/etc/killall gscan

98

Chapter 8

Scanner-specific Options

This chapter explains how to implement
a scanner-specific graphical options
panel. Doing so allows you to showcase
your scanner’s features and enhance the
overall usability and visual appeal of
your product.

Chapter 8

8.

Scanner-Specific Options

This chapter describes the implementation of scanner-specific graphical
options panels.
The major topics discussed are:
•

“Options Program and the Scanner Driver Interface” on page 102

•

“Scanner Driver's Perspective” on page 103

•

“Options Program's Perspective” on page 105

•

“Installation and Testing” on page 108

Overview
Most scanners have capabilities that would not be available to application
programs through the Generic Scanner API alone. A scanner-specific
graphical options panel program can be developed to provide access to these
capabilities.
A scanner-specific options program is run by a scanner application and
communicates directly with a scanner driver, bypassing the Generic Scanner
API. It should provide user interface elements (using Motif or a similar
toolkit) for the scanner features it supports that are not supported by the
Generic Scanner API. It should also communicate appropriate settings to the
scanner driver.
The scanner driver, in turn, must respond to commands from its
corresponding scanner-specific options program.

101

Scanner-Specific Options

Options Program and the Scanner Driver Interface
The options program executes driver commands by writing a command
number and the arguments to that command onto a pipe. The scanner driver
reads the command and arguments from the pipe, then calls the options
function for that command. After the options function returns, the driver
writes the results of the function back to the options program.
Developers of new scanner drivers and options programs need not worry
about the low-level communication between these programs; this is all taken
care of in libscan.a. They DO need to ensure that the scanner drivers and
options programs interpret commands and arguments consistently. This is
most easily accomplished by providing a common header file that the driver
and the scanner options program share. This header file should contain
#defines for the scanner-specific commands and typedefs for the arguments,
and return values of these commands. sclopt.h, for example, is included by
both the HP ScanJet scanner driver and the HP ScanJet options panel:
/*
* sclopt.h
* Stuff for scl scanner-specific options
*/
#define SCL_GETOPTS (SCN_SCANSPECIFIC + 0)
#define SCL_SETOPTS (SCN_SCANSPECIFIC + 1)
#define
#define
#define
#define

DITH_COURSE 0
DITH_FINE 1
DITH_BAYER 2
DITH_VERTICAL 3

typedef struct tag_sclopt {
int intensity;
int minIntensity, maxIntensity;
int contrast;
int minContrast, maxContrast;
int bwDither;
int bwDitherPattern;
} SCLOPT;

102

/*
/*
/*
/*
/*
/*
/*
/*
/*
/*

Intensity of image */
Intensity bounds; used */
in GETOPTS only */
Image contrast */
Contrast bounds; used */
in GETOPTS only */
if nonzero, dither */
black and white data */
specify black & white */
dither pattern */

Scanner Driver's Perspective

sclopt.h defines two HP ScanJet-specific commands: SCL_GETOPTS and
SCL_SETOPTS. Scanner-specific commands MUST be numbered
consecutively, starting with SCN_SCANSPECIFIC and increasing
monotomically from there. SCN_SCANSPECIFIC is #defined in
/usr/include/scanipc.h.
The SCLOPT structure is used to pass information between the HP ScanJet
scanner driver and the HP ScanJet options panel. This structure is the return
type of the SCL_GETOPTS command and the argument type of the
SCL_SETOPTS command.
“Scanner Driver's Perspective” below describes how the scanner driver uses
these #defines and typedefs. “Options Program's Perspective” on page 105
describes how the scanner-specific options program uses them.

Scanner Driver's Perspective
The scanner driver implements scanner-specific options by providing a table
of functions to the main.c module. In OpenScanner, the scan.c module should
set the options field of the SCANINFO struct to an array of functions
implementing the scanner-specific options, and the noptions field to the
number of such options. The order of the functions in the options table must
correspond to the numerical order of the commands implemented (the cmd
argument, below).
Each function in this array must have the following prototype:
void optionfunc(int cmd, SCARG *arg, SCRES *res);

cmd is the command number for this scanner-specific option. SCARG is
defined in the file /usr/include/scandrv.h as follows:
typedef struct tag_scarg {
void *data;
int len;
} SCARG;

arg->data points to the arguments passed in by the scanner-specific options
program, and arg->len is the number of bytes pointed to by arg->data.
SCRES is defined in the file /usr/include/scandrv.h as follows:

103

Scanner-Specific Options

typedef struct tag_scres {
void *data;
int len;
void *freeparam;
void (*free)(void *param, void *data);
int errno;
char *errmsg;
} SCRES;

res->data should be set to point to the results of the scanner-specific option,
and res->len should be set to point to the number of bytes in res->data. If an
error occurs, res->errno should be set to one of the values from sys/errno.h or
scanner.h. If res->free is nonzero, it is called with res->freeparam as its first
argument and res->data as its second argument, after res->data has been
transferred to the scanner-specific options program. This can be used to free
memory that was dynamically allocated to temporarily hold the results.
For example, here is the code from the ScanJet driver that implements the HP
ScanJet options:
static SCLOPT scanOptions;
static void
GetOptions(int cmd, SCARG *arg, SCRES *res)
{
res->data = &scanOptions;
res->len = sizeof scanOptions;
}
static void
SetOptions(int cmd, SCARG *arg, SCRES *res)
{
scanOptions = *(SCLOPT *)arg->data;
}
SCANFUNC opttable[] = {
GetOptions,
SetOptions,
};

In OpenScanner, the options member of the SCANINFO struct is set to opttable,
and the noptions member is set to 2. Note that the order of the functions in
opttable corresponds to the numerical order of the commands they
implement.

104

Options Program's Perspective

SCANFUNC is a typedef from /usr/include/scandrv.h:
typedef void (*SCANFUNC)(int cmd, SCARG *arg, SCRES *res);

Note: The actual code in the ScanJet driver is slightly more complex; error
checking has been eliminated from this example code so as not to obscure
the basic functionality.

The SetOptions function should verify that the options passed to it are valid
and set res->errno to a value from the /usr/include/sys/errno.h directory or
/usr/include/scanner.h if they are not. Also, the ScanJet function SetOptions
will fail if the scanner is currently scanning, because verifying that the
options are valid would interrupt the scan. So, in this case, SetOptions should
set res->errno to SCEBUSY and return.

Options Program's Perspective
The scanner-specific options program is executed by libscan.a when the
scanner application calls the function SCOptions(3). The program is executed
with command-line arguments that, when passed to the libscan.a function
SCGetScanOpt(3), enable a connection to be established with the scanner
driver.
One of the first things that a scanner-specific options program must do, then,
is call SCGetScanOpt. This function has the following prototype (from
/usr/include/scanipc.h):
SCANOPT * SCGetScanOpt(int *argc, char *argv[]);

The scanner-specific options program communicates with the scanner
driver by making calls to the function SCScanOpt(3), which has the following
prototype (from /usr/include/scanipc.h):
int SCScanOpt(SCANOPT *s, int cmd, void *args, int arglen,
void *res, int reslen);

The first argument to SCScanOpt(3) is the pointer returned by
SCGetScanOpt(3), above. The cmd argument is one of the command #defines
from the common header file shared with the scanner driver. args is a pointer
to the arguments to this command, and arglen is the number of bytes pointed

105

Scanner-Specific Options

to by args. This corresponds to arg->data and arg->len in the scanner driver
option function for cmd.
res points to space for receiving the results of the command, and reslen is the
maximum number of bytes to copy into res. The data copied into res
corresponds to res->data in the scanner driver option function for cmd.
The following example code was distilled from the ScanJet options program.
The ScanJet options program is a Motif program; please refer to the X and Xt
Motif documentation set (see “Related Publications,” in the “Introduction”
section of this manual for the full names and order numbers) for information
about the non-scanning portions of the code below.
static
static
static
static

Widget toplevel;
SCANOPT *scan;
SCLOPT scanOptions;
XtAppContext appContext;

int
main(int argc, char *argv[])
{
toplevel = XtAppInitialize(&appContext, "SJIIcOpt", NULL, 0,
(unsigned int *)&argc, argv, fallBackResources,
NULL, 0);
scan = SCGetScanOpt(&argc, argv);
if (!scan) {
InitError(toplevel, appContext,SCErrorString(SCerrno));
}
if (SCScanOpt(scan, SCL_GETOPTS, NULL, 0,
&scanOptions, sizeof scanOptions) < 0) {
InitError(toplevel, appContext, SCErrorString(SCerrno));
}
/* ... create widgets corresponding to options ... */
XtRealizeWidget(toplevel);
XtAppMainLoop(appContext);
return 0;
}

106

Options Program's Perspective

main calls XtAppInitialize(3Xt) to initialize the X toolkit, and then calls
SCGetScanOpt(3) to get the connection to the scanner driver. Then it calls
SCScanOpt(3) to get the current options settings from the scanner driver.
If anything goes wrong, main calls a function (not shown here, but part of the
ScanJet options program) called InitError, which transforms the application
into a message dialog containing the error message passed as the third
argument.
The ScanJet options program has an OK button that the user presses after
setting up the options desired. Below is an excerpt from the callback function
for that OK button.
static void
OKCallback(Widget w, XtPointer client,
XmAnyCallbackStruct *cb)
{
/* ... get settings from widgets,
put them into scanOptions
... */
if (SCScanOpt(scan, SCL_SETOPTS, &scanOptions,
sizeof scanOptions, NULL, 0) < 0) {
PostError(toplevel, SCErrorString(SCerrno), 0);
return;
}
exit(0);
}

Again note the error check; PostError is another function from the ScanJet
options program, which displays a message dialog containing an error
message.
Also note that we call exit(2) if the call to SCScanOpt succeeds. This is because
the scanner options program appears to the user to be a dialog box
associated with the scanning application that executed it. The ScanJet
options program also provides an Apply button for changing
scanner-specific settings without dismissing the scanner-specific options
program.

107

Scanner-Specific Options

Installation and Testing
After you have written your scanner driver and scanner options program,
copy your scanner driver to the directory /usr/lib/scan/drv, and the options
program to the directory /usr/lib/scan/opt. The driver and options program
must have the same base name in order for scanners(1M), the scanner
installation tool, to recognize that they go together.
Next, run scanners(1M) to install your scanner. If it was already installed
before you copied your options program to /usr/lib/scan/opt, you must delete
the scanner first (using the “Delete...” command on the “Scanner” menu).
Now you can run gscan(1) to test your driver and options program. The
“Scanner Specific Options...” command on the “Parameters” menu should
bring up your options program.

108

Chapter 9

Generic Scanner Interface

This chapter describes the interface
between a scanner driver and an
application program. Applications that
use this interface can access any scanner
that conforms to the Impressario
interface.

Chapter 9

9.

Generic Scanner Interface

This chapter describes the interface between a scanner driver and an
application program.
The major topics discussed are:
•

“Coordinate System for Scanning” on page 112

•

“Data Structures” on page 113

•

“Data Type Conventions” on page 114

•

“Functions” on page 116

111

Generic Scanner Interface

Overview
The generic interface between a scanner driver and an application program
is flexible enough to accommodate a wide range of scanners and application
programs. Application programs that use this interface can use any scanner
that has a driver that supports this interface. Providing a driver for a
particular scanner allows it to be accessed by any program written to use this
interface.
The interface is implemented by a run-time library and a driver program. All
drivers must provide the entry points necessary for the run-time library to
provide the interface described in this document. In order to provide access
to scanner-specific capabilities, scanner drivers are free to expand the
interface, which is then accessed by scanner-specific programs that have
standard ways of being invoked by application programs. (See Chapter 8,
“Scanner-Specific Options.”)
For more details on the functions described in this chapter, see the online
manual pages.

Coordinate System for Scanning
When describing an area to be scanned, a coordinate system with the origin
(0,0) in the upper left corner of the scannable area is used. The x-coordinate
increases from left to right, and the y-coordinate increases from top to
bottom.
Note that this is the upper left corner of the document being scanned; in the
case of a flatbed scanner where the document is placed face down in the bed,
this is the upper right corner or lower left corner of the bed.
When functions in the interface specify measurements along the horizontal
and vertical axes of the scan area, the following units can be used to specify
distance:

112

•

SC_INCHES—measurements specified in inches

•

SC_CENTIM—measurements specified in centimeters

•

SC_PIXELS—measurements specified in pixels

Data Structures

Data Structures
This section describes the generic scanner interface data structures.

SCANNER Data Structure
typedef struct tag_scanner {
...
} SCANNER;

The application maintains a pointer to a SCANNER data structure (obtained
from SCOpen) to specify the scanner to which operations should be applied.

SCDATATYPE Data Structure
Scanners support a variety of output data types. The SCDATATYPE struct
encapsulates the common output data types produced by scanners.
typedef struct tag_scdatatype {
unsigned int packing : 4;
unsigned int channels : 4;
unsigned int type : 8;
unsigned int bpp : 8;
} SCDATATYPE;
Arguments:

packing

The packing field can take on the following values:
SC_PACKPIX

All the data for each pixel is stored
together; for example., a line of 24-bit
color is stored as RGBRGBRGB.

SC_PACKBAND Each line of data is decomposed into its
channels; for example, a line of 24-bit
color is stored as RRRGGGBBB.
SC_PACKPLANE All the data for a channel is stored
separately from other channels. A page
of color data is split into three pages of
data; one for red, one for blue, and one
for green.

113

Generic Scanner Interface

channel

Number of components per pixel. Legal values are 1, 3, and
4. See type below.

type

Type of data. This parameter indicates how the data in the
various channels is to be interpreted:
SC_MONO Monochrome: 1 channel and 1 bit per pixel.
SC_GREY

Greyscale: 1 channel.

SC_RGB

Red, green, and blue: 3 channels.

SC_CMY

Cyan, magenta, and yellow: 3 channels.

SC_CMYK Cyan, magenta, yellow, and black: 4 channels.
bpp

Bits Per Pixel (per channel). The number of bits per pixel in
each channel. For monochrome data, there is 1 bit per pixel.
For 24-bit RGB color, there are 8-bits per pixel (* 3 channels
== 24-bits).

Data Type Conventions
Generic scanner applications need not be written to support any particular
data type. There are four basic data types that are typically used:
1.

2.

114

Monochrome. ALL scanner drivers MUST support the following
monochrome format:
•

packing == SC_PACKPIX

•

channels == 1

•

type == SC_MONO

•

bpp == 1

8-bit greyscale. All scanner drivers that support any type of greyscale or
color output MUST support the following 8-bit greyscale format:
•

packing == SC_PACKPIX

•

channels == 1

•

type == SC_GREY

•

bpp == 8

Data Type Conventions

3.

4.

Planar 24-bit RGB color. The red, green, and blue channels are scanned
in three separate passes; in this case, the data type for is:
•

packing == SC_PACKPLANE

•

channels == 3

•

type == SC_RGB

•

bpp == 8

Packed 24-bit RGB color. This applies to a one-pass color scanner that
gets all of the data in one pass. The data type for color data from this
kind of scanner is:
•

packing == SC_PACKPIX

•

channels == 3

•

type == SC_RGB

•

bpp == 8

A scanning application that is prepared to deal with these four data types
should be able to interact well with any well-behaved scanner driver.

115

Generic Scanner Interface

Functions
Diagnostic Functions
Many of the functions specified here return 0 upon success and -1 in the
event of a failure. If a function's return value indicates failure, the reason for
the failure can be determined by examining the value of the global variable
SCerrno. SCerrno will be between 0 and LASTERRNO (defined in
/usr/include/sys/errno.h) if the failure was due to a failed system call, and
between SCEBASE and SCELAST (defined in scanner.h) if the failure was
for some other reason. #defines for the values between SCEBASE and
SCELAST can be found in /usr/include/scanner.h.
Table 9-1 lists the diagnostic functions.
Table 9-1

Diagnostic Functions

Function

Description

SCPerror

Prints an error string.

SCErrorString Returns a character string containing an error message.

SCPerror Function
void SCPerror(char *ident)

This function prints the value of ident, a colon, and a string of text
corresponding to the current value of SCerrno.
SCErrorString Function
char *SCErrorString(int err)

This function returns a character string containing a useful message
describing the error condition represented by err. If err is not in the range 0
to LASTERRNO or SCEBASE to SCELAST, SCErrorString returns a text
string containing the words “Error code err,” where err is the value passed to
SCErrorString.

116

Functions

Application/Driver Rendezvous Functions
Users refer to scanners by names given to them at install time. The installer
uses scanners(1M), which adds entries to a mapping from scanner names to
(driver, device, options) tuples. The mapping is contained in the file
/var/scan/scanners. The driver and device components are used to start the
right driver on the device to access the scanner given by name, and options is
the scanner-specific options program. scanners(1M) allows the specification
of a default scanner.
The application/driver Rendezvous functions are listed in Table 9-2 and
described below.
Table 9-2

Application/Driver Rendezvous Functions

Function

Description

SCOpen

Prepares to perform operations on the scanner named by
name.

SCOpenScreen

Calls the screen scanner driver to scan from the specified
screen.

SCOpenFile

Calls the file scanner driver to scan from the specified
file.

SCClose

Breaks the connection between the application and the
driver.

SCSetScanEnt

Opens the scanner configuration file and returns a
pointer.

SCGetScanEnt

Gets a SCANENT structure for each installed scanner.

SCEndScanEnt

Frees the resources used to enumerate scanners.

SCScannerName

Returns the name associated with the scanner at
installation.

SCScannerEnt

Returns the SCANENT structure of an open scanner.

SCDefaultScannerName Gets the default scanner name, if any.

117

Generic Scanner Interface

SCOpen Function
SCANNER *SCOpen(char *name)

The SCOpen function prepares to perform operations on the scanner named
by name by starting the appropriate driver on the appropriate device.
SCOpen performs the lookup in the name -> (driver, device, options) mapping.
If name is NULL, the default scanner is used.
SCOpen returns a pointer to a SCANNER struct if successful, or NULL if
there is an error. If name is NULL and no default scanner has been set,
SCOpen opens the first scanner found in /usr/lib/scan/scanners.
SCOpenScreen Function
SCANNER *SCOpenScreen(char *screen)

This function invokes the screen scanner driver to scan from the specified
screen. It returns a pointer to a SCANNER struct if successful, NULL if there
is an error.
SCOpenFile Function
SCANNER *SCOpenFile(char *file)

This function invokes the file scanner driver to scan from the specified file.
It returns a pointer to a SCANNER struct if successful, NULL if there is an
error.
SCClose Function
int SCClose(SCANNER *s)

This function breaks the connection between the application and the driver
program. It returns 0 on success, -1 if there is an error.
SCSetScanEnt Function
FILE *SCSetScanEnt(void)

This function opens the scanner configuration file. It returns a pointer to the
open FILE structure on success, NULL if there is an error.

118

Functions

SCGetScanEnt Function
typedef struct tag_scanent {
char *name;
char *driver;
char *device;
char *options;
} SCANENT;
SCANENT *SCGetScanEnt(FILE *fp)

To get a SCANENT structure for each scanner installed on the system, this
function should be called repeatedly until it returns NULL. The contents of
the memory pointed to by the return value of SCGetScanEnt are undefined
after any subsequent calls to this function, so copy the return value if you
need to preserve it across calls to SCGetScanEnt.
SCEndScanEnt Function
int SCEndScanEnt(FILE *fp)

This function frees the resources used to enumerate scanners. It returns 0 on
success, -1 if there is an error.
SCScannerName Function
char *SCScannerName(SCANNER *s)

This function returns the name associated with the scanner at installation.
Applications can use this to get at the name of the default scanner being used
if SCOpen was called with NULL. It returns a pointer to a character string on
success, NULL if there is an error. The memory pointed to by the return
value of SCScannerName belongs to libscan and should not be modified or
freed.
SCScannerEnt Function
SCANENT *SCScannerEnt(SCANNER *s)

This function returns the a SCANENT structure describing an open scanner.
The memory pointed to by the returned value of SCScannerEnt belongs to
libscan and should not be modified or freed.

119

Generic Scanner Interface

SCDefaultScannerName Function
char *SCDefaultScannerName(void)

This function gets the default scanner name, if any. It returns the name of the
default scanner, or NULL if no default scanner has been set. The memory
pointed to by the returned value of SCDefaultScannerName belongs to libscan
and should not be modified or freed.

Scanning Resolution Functions
Scanners typically support a range of resolutions (pixels per inch). Scanner
drivers should support any resolution between the minimum and maximum
resolutions supported by the scanner, decimating or replicating pixels as
necessary to support the requested resolution. This gives the application the
opportunity to preview the scanning area in an arbitrarily sized window.
It is not the scanner driver's responsibility to perform higher quality scaling
of the image data. SCGetScannerRes can be used by the scanner application
to determine which resolutions are supported directly by the scanner
without decimation or replication by the driver.
SCGetScannerRes Function
int SCGetScannerRes(SCANNER *s, int metric,
float **xres, float **yres, int *nres)

This function returns arrays of hardware-supported resolutions. The xres
and yres arrays specify supported horizontal and vertical resolutions. metric
should be one of SC_INCHES or SC_CENTIM. nres sets the number of
resolution pairs in the xres and yres arrays. SCGetScannerRes returns 0 if
successful, -1 if there is an error.
SCGetMinMaxRes Function
int SCGetMinMaxRes(SCANNER *s, int metric,
float *minx, float *miny, float *maxx, float *maxy);

This function determines the resolution bounds; that is, the minimum and
maximum horizontal and vertical resolutions that the scanner supports. It is

120

Functions

an error to call SCGetMinMaxRes with “metric == SC_PIXELS.”
SCGetMinMaxRes returns 0 if successful, -1 if there is an error.

Scanning Area Functions
A scan may be limited by the application to a subset of the scannable area
supported by the scanner. SCGetPageSize is provided so that applications can
determine the size of the scannable area supported by the scanner.
SCGetPageSize Function
int SCGetPageSize(SCANNER *s, int metric, float *x, float *y,
float *width, float *height)

This function gets the entire scannable area. It is an error to call it with
“metric == SC_PIXELS.” SCGetPageSize returns 0 if successful, -1 if there is
an error.
SCGetDataTypes Function
int SCGetDataTypes(SCANNER *s, SCDATATYPE **dt, int *ntypes)

This function sets *dt to point to an array of the data types supported by the
scanner driver. ntypes gets the number of data types supported. The memory
pointed to by *dt belongs to libscan and should not be modified or freed. It
should also not be expected to retain its values after subsequent calls to
SCGetDataTypes.

Scanning Functions
After SCOpen has been called, the scanner is idle. In order to initiate a scan,
the functions SCSetup and SCScan are called. Characteristics of the data to be
scanned can be determined with SCGetScanSize. A scan in progress can be
aborted at any time with the function SCAbort. The scanner status can be
determined by calling the function SCGetStatus.

121

Generic Scanner Interface

Table 9-3 lists the available scanning functions.
Table 9-3

Scanning Functions

Function

Description

SCSetup

Prepares the scanner for a scan.

SCGetScanSize

Determines the width, height, and number of bytes per scan
line.

SCScan

Starts scanning.

SCGetScanLine

Retrieves scan line data.

SCDataReady

Determines whether any data is available.

SCGetFD

Returns the file descriptor for scan data.

SCScanFD

Starts scanning (alternative call).

SCAbort

Aborts the current scan.

SCGetStatus

Gets the status of the scanner.

SCGetStatusFD

Returns a file descriptor for scan status.

SCSetup Function
SCSetup(SCANNER *s, int preview, SCDATATYPE *type,
int rmetric, float xres, float yres,
int wmetric, float x, float y, float width,
float height)

This function is used to prepare the scanner for a scan. The type of data, the
resolution, and the scanning area are specified. preview is nonzero if this is a
“preview” scan; that is, when the driver is faced with a trade-off between
speed and image quality, it should choose speed since this is not the “real”
scan. After calling SCSetup, SCScan is called to actually initiate scanning.
SCSetup returns 0 if successful, -1 if there is an error.

122

Functions

SCGetScanSize Function
int SCGetScanSize(SCANNER *s, int *width, int *height,
int *bytesPerLine)

This function is called after SCSetup to determine the width, height, and
number of bytes per scan line that will be returned by the driver. It returns 0
if successful, -1 if there is an error.
SCScan Function
int SCScan(SCANNER *s)

This function tells the driver to start scanning. The driver immediately starts
to scan and buffer the data. SCScan does not fetch any scan data (see
SCGetScanLine). SCScan returns 0 if successful, -1 if there is an error.
SCGetScanLine Function
int SCGetScanLine(SCANNER *s, void *buf, int bytes)

This function retrieves scan line data. bytes should be set to the number of
bytes in a scan line as determined by SCGetScanSize.
Note that for color planar data, SCGetScanLine is called once for each line in
each plane of data. For 100 lines of 24-bit RGB planar data, SCGetScanLine is
called a total of 300 times, with the first 100 calls retrieving the red plane, the
second 100 calls retrieving the green plane, and the third 100 calls retrieving
the blue plane.
SCDataReady Function
int SCDataReady(SCANNER *s)

This function is used to determine whether any data is available for calls to
SCGetScanLine; that is, whether a call to SCGetScanLine will block waiting for
data to become available.
SCDataReady returns 1 if data is available (SCGetScanLine will not block), 0 if
no data is available (SCGetScanLine will block), or -1 if there is an error. It is
an error to call SCDataReady if scanning was started by a call to SCScanFD.

123

Generic Scanner Interface

SCGetFD Function
int SCGetFD(SCANNER *s)

This function returns the file descriptor over which scan data from the
scanner driver will be coming. Checking the state of this descriptor with the
select(2) system call is equivalent to calling SCDataReady. If SCScanFD was
called, SCGetFD returns the file descriptor that was passed to that function.
SCGetFD returns -1 if there is an error.
SCScanFD Function
int SCScanFD(SCANNER *s, int fd)

This function is an alternative to calling SCScan to start scanning and
SCGetLine to fetch the data. After SCScanFD is called, the driver writes the
scanned data to fd; this is useful if the output data format of the scanner
interface matches the input data type of another interface. SCScanFD returns
0 if successful, -1 if there is an error.
SCAbort Function
int SCAbort(SCANNER *s)

This function aborts the current scan. Data buffered by the driver is
discarded. SCAbort returns 0 if successful, -1 if there is an error.
SCGetStatus Function
enum scstate { SC_READY, SC_SCANNING, SC_ERROR };
typdef struct tag_scstatus {
enum scstate state;
/* ready, scanning, error */
int errno;
/* only valid if state == SC_ERROR */
long curline;
/* current line being scanned */
int pass;
/* current scanning pass */
} SCSTATUS;
int SCGetStatus(SCANNER *s, SCSTATUS *st)

This function gets the status of the scanner. It returns 0 if successful, -1 if
there is an error.

124

Functions

SCGetStatusFD Function
int SCGetStatusFD(SCANNER *s)

This function returns a file descriptor that can be passed to the select(2)
system call. When select(2) indicates that the file descriptor is ready for
reading, the scanner driver has updated the scanning status. Retrieve the
status by calling SCGetStatus; do NOT pass the file descriptor returned from
SCGetStatusFD to any other system call.
SCGetStatusFD provides a mechanism whereby it is not necessary for an
application to periodically call SCGetStatus in a timer loop to detect changes
in scanner status. SCGetStatusFD returns -1 if there is an error.

Document Feeder Functions
The scanner interface has provisions for the support of scanners that have
document feeders attached. This facilitates the development of applications
that can scan multiple pages without user intervention. Table 9-4 lists the
document feeder functions.
Table 9-4

Document Feeder Functions

Function

Description

SCFeederGetFlags Gets the feeder flags.
SCFeederSetFlags

Sets feeder flags.

SCFeederAdvance Advances the feeder to the next document.
SCFeederReady

Checks if the feeder is ready for feeding.

125

Generic Scanner Interface

SCFeederGetFlags Function
typedef unsigned int SCFEEDERFLAGS;
#define SC_HASFEEDER 1
#define SC_AUTOFEED 2
#define SC_PROGFEED 4
int SCFeederGetFlags(SCANNER *s, SCFEEDERFLAGS *flags);

This function fills in the flags variable with flags appropriate for the scanner
associated with s. If SC_AUTOFEED and SC_PROGFEED are both set,
SCFeederSetFlags should be called before any calls to SCScan to establish how
the application is to interact with the feeder. The meanings of the flags are as
follows:
SC_HASFEEDER Set if there is a document feeder attached to the scanner.
SC_AUTOFEED Set if the feeder can operate such that each call to SCScan
causes the next document to be loaded.
SC_PROGFEED Set if the feeder can operate so that SCScan can be called
multiple times per document. It is necessary to call
SCFeederAdvance to load the next document.
SCFeederGetFlags returns 0 if successful, -1 if there is an error.
SCFeederSetFlags Function
int SCFeederSetFlags(SCANNER *s, SCFEEDERFLAGS flags);

This function should be called before calling SCScan for scanners in which
SCFeederGetFlags sets both SC_AUTOFEED and SC_PROGFEED. After
calling SCFeederSetFlags(s, SC_AUTOFEED), the feeder advances to the next
document after every call to SCScan. After calling SCFeederSetFlags(s,
SC_PROGFEED), a call to SCFeederAdvance is necessary to advance to the
next document. SCFeederSetFlags returns 0 if successful, -1 if there is an error.

126

Functions

SCFeederAdvance Function
int SCFeederAdvance(SCANNER *s)

This function advances the feeder to the next document. This call is valid
only if the scanner supports the SC_PROGFEED mode. For scanners that
support both the SC_AUTOFEED and SC_PROGFEED modes,
SCFeederSetFlags(s, SC_PROGFEED) must have been called previously.
SCFeederAdvance returns 0 if successful, -1 if there is an error. When
unloading the last document, this function returns -1 with SCerrno set to
SCFEEDEREMPTY.
SCFeederReady Function
int SCFeederReady(SCANNER *s)

This function checks if the feeder is ready for feeding. SCFeederReady returns
0 if the feeder is ready, -1 if not. If the feeder is empty, SCerrno is set to
SCFEEDEREMPTY; if any other error conditions exist, SCerrno is set
appropriately.
Note that this function needs to be called before SCFeederAdvance to
determine whether a document is ready to be scanned after the call to
SCFeederAdvance.

127

Generic Scanner Interface

Events
Scanner applications need to be aware that the configuration information
about a scanner obtained from SCGetMinMaxRes, SCGetScannerRes,
SCGetPageSize, and SCGetDataTypes can change. This typically happens
when the user selects a new input medium using the scanner specific options
panel. For example, some scanners support transparency options that have
a different scanning page size than the normal scanning bed. When the user
decides to scan transparencies, the driver will notify the application that it
needs to call SCGetPageSize by sending an event. See Table 9-5.
Table 9-5

Event Functions

Function

Description

SCGetEvent

Receives an event from the scanner driver.

SCEventPending

Tests whether an event is currently pending.

SCGetEventFD

Obtains an event file descriptor for passing to select(2).

SCGetEvent
typedef struct tag_infoChange {
unsigned int pageSizeChanged : 1;
unsigned int resolutionChanged : 1;
unsigned int dataTypesChanged : 1;
unsigned int feederFlagsChanged : 1;
} SCINFOCHANGE;
#define SCEVENT_INFOCHANGE 1
typedef struct tag_scevent {
unsigned int eventType;
union {
SCINFOCHANGE infoChange;
} event;
} SCEVENT;
int SCGetEvent(SCANNER *s, SCEVENT *event)

SCGetEvent is called to receive an event from the scanner driver. The event
structure should be examined, and if the pageSizeChanged field is set, the
application should call SCGetPageSize to query the new page size; if the

128

Events

resolutionChanged field is set the application should call SCGetMinMaxRes
and SCGetScannerRes to query the new resolutions; if the dataTypesChanged
field is set the application should call SCGetDataTypes to query the new data
types, and if the feederFlagsChanged field is set the application should call
SCGetFeederFlags to query the new feeder flags.
SCEventPending
int SCEventPending(SCANNER *s)

SCEventPending is called to test whether or not an event is currently pending.
If an event is pending, the application should call SCGetEvent to receive it.
SCEventPending returns 1 if any events are pending, and 0 if no events are
pending.
SCGetEventFD
int SCGetEventFD(SCANNER *s)

SCGetEventFD returns a file descriptor which can be passed to the select
system call. When select indicates that this file descriptor is ready for reading,
then an event is pending and the application should call SCGetEvent to
retrieve it.

129

Chapter 10

Testing for Impressario Compatibility

This chapter explains how to use the
programs included in the Impressario
Developer’s kit to test the output
capabilities of an Impressario-supported
printer, and test an Impressario printer
software installation.

Chapter 10

10.

Testing for Impressario Compatibility

This chapter explains how to use the programs that test printing
compatibility with the Impressario environment.
The topics discussed in this chapter are:
•

“Testing Impressario Printing Compatibility” on page 134

•

“Testing an Impressario Printer” on page 134

•

“Testing an Impressario Printer Software Installation” on page 136

Note: See the testipr(1) and testiconfig(1) man pages for command line

options and the most up-to-date information on these test programs.

133

Testing for Impressario Compatibility

Testing Impressario Printing Compatibility
The Impressario Developer’s Kit provides two programs for testing printing
compatibility with the Impressario environment. The testipr program tests
the output capabilities of an Impressario-supported printer. The testiconfig
program tests an Impressario printer software installation. Both of these
programs are located in the directory /usr/impressario/tests/print.
Note: The use of these test harnesses is not sufficient testing to ensure the

quality of your product. They are only helpful tools, not a substitute for
additional testing.

Testing an Impressario Printer
A printer supported by Impressario can print a wide range of file formats
with a large selection of printing options for each file format. Testing each
supported file format and printing option can be a laborious task if done
manually, one test case at a time. testipr automates the testing process by
printing a set of standard test files, according to a standard test plan.
testipr is in the directory /usr/impressario/tests/print and typically is run from
there. The name of a printer installed on the system is the only required
command line parameter. It is recommended that the printer be physically
connected to the system on which is testipr run. It is the responsibility of the
user to ensure that the printer is not used by other users during testing.
On startup testipr looks in the /usr/impressario/tests/print directory for test
configuration files. These files are identified by a .ipr suffix and a basename
corresponding to the test class name. There are three standard configuration
files: text.ipr, image.ipr, and postscript.ipr. These files comprise the text, image,
and PostScript test classes, respectively. Each configuration file describes a
set of tests to be run by testipr. These files should not be modified. If you wish
to create your own test cases, you can copy the existing configuration files to
a new location, modify them to suit your needs, and use the -p command line
option to tell testipr where to find the files.

134

Testing Impressario Printing Compatibility

The format of the configuration file follows that of a X Window System
resource file. For example:
! This is a comment in an example .ipr file
test.basePath: /usr/impressario/data
test.1.file: testfile.sgi
test.1.options: -rotate 90 -gamma 3.5
test.1.desc: “SGI Image File - rotated 90, gamma 3.5”
test.2.file: testfile.sgi
test.2.options: -rotate 90 -gamma 3.5
test.2.desc: “SGI Image File - rotated 90, gamma 3.5”

Each resource must start with the keyword test. basePath is an optional
resource that specifies a directory path. If it is specified, the path will be
prepended to each file resource. The file resource specifies a test file to print.
Typically, these test files are from /usr/impressario/test/data. The options
resource specifies the actual -o model file options to be used in the test. Note
that the -o should not be specified. The testipr program automatically
prepends the nobanner option to all option strings. The option string is
passed as the argument to the lp command’s -o option. The desc resource
provides a description of the test. This string will be written to the test log
file. Each test case must be numbered consecutively starting with one.
The file specified in each test is submitted for printing using the specified
printing options. A log file, called /var/tmp/testipr..log, is
created. This log file contains general information about the printer being
tested and its host environment. The log also contains a detailed list of all
tests performed and their corresponding spooling system print job IDs. A
complete test record consists of the printer output, the corresponding log
file, and the /var/spool/lp/log file. See the testipr(1) man page for command line
options and the most up-to-date information on this test program.
Example 1:

Run all tests on the printer hp4.
testipr hp4

135

Testing for Impressario Compatibility

Example 2:

Run only image tests on the printer hp4.
testipr -c image hp4
Example 3:

Run only image tests numbers 5 and 6 on the printer hp4.
testipr -c image -t 5,6 hp4

Testing an Impressario Printer Software Installation
An Impressario supported printer has greatly enhanced printing capabilities
over a non-Impressario printer. To provide these enhanced capabilities,
software complying with Impressario specifications must be installed in
standard locations. The testiconfig program checks that the software support
for a printer conforms to Impressario specifications. Typical users of this
program are third-party printer developers who wish to verify that their
printer support is compatible with the Impressario printing environment.
testiconfig performs a number of checks to ensure conformance to
Impressario printer support specifications. The program performs checks on
the printer model file, POD files, graphical options panel and printer driver.
All output is sent to the standard output. If the -v option is specified,
additional information is displayed during the test. The testiconfig program
requires the name of the printer model file. The printer support software
must be installed on the system on which the testiconfig is run. Note that a
printer need not be physically installed on the system or installed by the
spooling system to run this test program.
Example:

Test the installation for an HP LaserJet 4:
testiconfig -v laserjet_model

Note: See the testiconfig(1) man page for command line options and the most

up-to-date information on this program.

136

Chapter 11

Packaging Your Impressario Product

This chapter explains how to package
your Impressario product to make
distribution simple and consistent with
the Impressario printing and scanning
environment.

Chapter 11

11.

Packaging Your Impressario Product

This chapter explains how to package your Impressario Product.
The topics discussed in this chapter are:
•

“Making a Software Distribution” on page 140

•

“Packaging Impressario Printing Software” on page 141

•

“Packaging Impressario Scanning Software” on page 144

Overview
Impressario provides an open printing and scanning environment. Third
party support for printers and scanners can be plugged into the Impressario
environment by following the procedures described in this chapter.
Note: As of this writing, Silicon Graphics is in the process of making its inst

software packaging and installation technology available to its developers.
The inst software packaging mechanism is far superior to the use of tar
archives. When available, inst software packaging should be used instead of
tar archives.

139

Packaging Your Impressario Product

Making a Software Distribution
The current method for creating an Impressario software distribution uses
the tar(1) file archiving program. To create a software distribution use the
following procedure.
1.

Become superuser. The creation of all tape archives and the subsequent
installation of the product by the end user must be done as superuser.
Becoming superuser is typically accomplished by either logging in as
root or executing the su(1M) command. Typically, a password must be
provided to gain superuser access to a system. Ask your system
administrator for assistance.

2.

Copy the files that comprise your product from your development area
to the directories into which they will be installed. See “Packaging
Impressario Printing Software” on page 141 and “Packaging
Impressario Scanning Software” on page 144 for the files typically
installed by printing and scanning products.

3.

Change the permissions and ownership of each file in accordance with
the recommendations in “Packaging Impressario Printing Software”
and “Packaging Impressario Scanning Software.” The chmod(1)
command is used to change file permissions and the chown(1)
command is used to change file ownership. For example, to give the file
foo read/write permission for the owner and read-only permission for
all others, and to specify a root owner and sys group, execute the
following commands:
chmod 0644 foo
chown root.sys foo

4.

Run the tar command and specify the absolute pathname of each file that
is part of the distribution. For example, to create an archive consisting
of two files and place that archive on the default tape device, execute
the following command:
tar cvLf /dev/tape /usr/lib/print/mydriver /var/spool/lp/model/mymodel

For detailed information on the tar program, refer to the tar(1) manual
page.
5.

140

Optionally, you may include in your distribution a shell script that
removes the files that are installed by your product. This allows
customers to reclaim the disk space used by your product if your
product is no longer being used.

Packaging Impressario Printing Software

Packaging Impressario Printing Software
To illustrate better the process of packaging Impressario printing support
software, let us create a fictitious product. The product will provide
Impressario support for the Blast family of printers. The Blast product line
consists of the Blast 1, Blast 2CVX, and the Blast P+. Since each of the Blast
printers is similar in functionality, support for all of them will be provided
by a single model file.
Impressario printing support products typically are named with the printer
family, the word Print and the lowest version number of Impressario that
supports the product. In keeping with this convention, we will name our
product “BlastPrint for Impressario 1.2”.
A typical Impressario printer support product consists of the following files:
Model file

When the printer is registered with the spooling system,
this file is copied and becomes the printer interface file. The
spooling system executes this shell script for each print job.

Driver

This executable program performs the work of
communication with the printer. The interface file invokes
the driver to do the actual printing of a file. The driver sends
data to the printer and updates the POD status file.

POD files

The POD consists of three files, all with the same basename
as the model file but with the suffixes config, status, and log.
These plain text files contain static and dynamic printer
information.

Graphical options panel program
This GUI program provides users with graphical access to
printer specific options. The program is given the same
basename as the model file with the suffix gui.
Graphical options panel resource file
This is an X Window system resource file for the graphical
options panel program. The file is named with the class
name of the graphical options panel program. This name
must also match the GUI_CLASS variable in the model file.
Manual page

A manual page should be created that describes the printing
product. By convention, this manual page should be named
with the product name. The manual page must be

141

Packaging Your Impressario Product

formatted using nroff(1) and must be compressed before
installation. A product manual page template and a
Makefile to perform the required formatting, compression,
and installation is provided in the directory
/usr/impressario/man.
Note: In order to create a manual page you must have the

Documenter’s Workbench product installed on the
development system.
The files listed in Table 11-1 comprise the BlastPrint product. The files are
listed with their absolute pathnames, ownership, and permissions.
Table 11-1

Typical Printing Product Files

Description Pathname

Permiss.

Owner

Model file

/var/spool/lp/model/blast_model

0755

lp.lp

Driver

/usr/lib/print/blaster

0755

lp.lp

POD files

/usr/lib/print/data/blast_model.config

0664

lp.lp

/usr/lib/print/data/blast_model.status

0664

lp.lp

/usr/lib/print/data/blast_model.log

0664

lp.lp

/var/spool/lp/gui_model/ELF/blast_model.gui 0755

lp.lp

Graphical
options
program

Before creating the actual software distribution, the above files must be
copied to the directories indicated and given the specified ownership and
permissions. Once this is done, the Impressario test program testiconfig(1)
can be run to verify that the product conforms to Impressario product
installation specifications.
To run the testiconfig program on the BlastPrint product, execute the
following:
cd /usr/impressario/tests/print
./testiconfig blast_model

Once the product installation has been verified, a software distribution can
be created. This is done using the tar(1) command. Assuming we are making

142

Packaging Impressario Printing Software

a tape distribution, we would issue the following command (note the use of
the line continuation character ‘\’ to allow the command line to extend over
multiple lines):
tar cvLf /dev/tape /var/spool/lp/model/blast_model \
/usr/lib/print/blaster \
/usr/lib/print/data/blast_model.config \
/usr/lib/print/data/blast_model.status \
/usr/lib/print/data/blast_model.log \
/var/spool/lp/gui_model/ELF/blast_model.gui \
/usr/lib/X11/app-defaults/Blast \
/usr/share/catman/u_man/cat1/blastprint.z

The resulting tape archive represents the BlastPrint product.
It is recommended that the copying of the files to their installation
directories, the assigning of ownership and permissions, and the archiving
of the files all be automated in a shell script. This eliminates a large amount
of typing and provides a reproducible distribution mechanism.
Once the distribution tape has been created, it should be taken to a new
system (in other words, one that has never had BlastPrint installed) and
installed. This is done using the following command as superuser:
tar xvf /dev/tape

Once BlastPrint has been installed, the testiconfig program should again be
run to verify that the installation is complete and correct. A printer should
then be connected to the system and registered with the spooling system
using the Printer Manager (printers(1M)). The Impressario test program
testipr(1) should be run on the newly installed printer to verify that it is able
to print all supported Impressario file formats and options.
If the printer was installed with the name myblaster, it can be tested by
executing the commands:
cd /usr/impressario/tests/print
./testipr myblaster

This completes the creation of an Impressario printer support product.

143

Packaging Your Impressario Product

Packaging Impressario Scanning Software
To illustrate the process of packaging Impressario scanning software, we
will create a fictitious product to provide Impressario support for the
LowTech 100 scanner.
Impressario scanning products are typically named with the scanner family,
the word Scan, and the lowest version number of Impressario that supports
this product. We will name our product “LowTechScan for Impressario 1.2”.
A typical Impressario scanner support product consists of the following
files:
Scanner driver The executable program that gets the data from a scanner.
Graphical options program
Graphical scanner-specific options program launched from
a scanning application. The graphical options program
showcases a scanner’s features. This program must have
the same base name as the scanner driver in order to be
recognized by scanners(1M), the scanner install tool.
Graphical options resource file
X Window System resource file for the graphical options
program. This file is named with the class name of the
graphical options program. This class name must be the
same as the graphical options program name with the first
letter capitalized. If the graphical options program resource
file is not named using these conventions, the options
program will not have access to its resources when invoked
for a network scanner.
Manual page

144

A manual page should be created that describes the
scanning product. By convention, this manual page should
be named with the product name. The manual page must be
formatted using nroff(1) and must be compressed before
installation. A product manual page template and a
Makefile to perform the required formatting, compression,
and installation is provided in the directory
/usr/impressario/man.

Packaging Impressario Scanning Software

Note: In order to create a manual page you must have the

Documenter’s Workbench product installed on the
development system.
The files listed in Table 11-2 comprise the LowTechScan product. The files are
listed with their absolute pathnames, ownership, and permissions
Table 11-2

Typical Scanning Product Files

Description Pathname

Permissions Owner

Scanner
driver

/usr/lib/scan/drv/lowtech

0755

root.sys

Graphical
options
program

/usr/lib/scan/opt/lowtech

0755

root.sys

Graphical
options
resources

/usr/lib/X11/app-defaults/Lowtech

0644

root.sys

Manual
page

/usr/share/catman/u_man/cat1/lowtech.z

0444

root.sys

Before creating the actual software distribution, the above files must be
copied to the directories indicated and given the specified ownership and
permissions. Then the scanners(1M) tool should be run to verify that the
correct string for the LowTech 100 scanner appears in the “Install New
Scanner” dialog. The scanners tool should be used to install a LowTech 100
scanner, and gscan(1) should be able to run the graphical options program
from the “Scanner Specific Options” command on the “Parameters” menu.
Once the product installation has been verified, a software distribution can
be created. This is done using the tar(1) command. Assuming we are making
a tape distribution, we would issue the following command (note the use of
the line continuation character ‘\’ to allow the command line to extend over
multiple lines):
tar cvLf /dev/tape /usr/lib/scan/drv/lowtech \
/usr/lib/scan/opt/lowtech \
/usr/lib/X11/app-defaults/Lowtech \
/usr/share/catman/u_man/cat1/lowtech.z

145

Packaging Your Impressario Product

The resulting tape archive represents the LowTechScan product.
It is recommended that the copying of the files to their installation
directories, the assigning of ownership and permissions, and the archiving
of the files all be automated in a shell script. This will eliminate a large
amount of typing and provides a reproducible distribution mechanism.
Once the distribution tape has been created, it should be taken to a new
system (in other words, one that has never had LowTechScan installed) and
installed. This is done using the following command as superuser:
tar xvf /dev/tape

Once LowTechScan has been installed, the scanners and gscan programs
should again be run to verify that the installation is complete and correct.
This completes the creation of an Impressario scanner support product.

146

Chapter 12

Enhancing Impressario with Plug-Ins

This chapter explains how to add new
features to the Impressario open
architecture. It describes how
Impressario’s automatic filetype
recognition and conversion pipeline
works, how to add new file types, and
how to add a new PostScript Raster
Image Processor (RIP).

Chapter 12

12.

Enhancing Impressario with Plug-Ins

This chapter explains how you can add plug-ins to Impressario to satisfy
needs that haven’t yet been integrated into the base software. This allows
you to dynamically update the feature set of Impressario.
This chapter explains:
•

How Impressario’s automatic file type recognition and file conversion
pipeline works

•

How to add new file types to those that Impressario printers already
recognize and print

•

How to add a new PostScript Raster Image Processor (RIP) to
Impressario and switch between the standard Impressario RIP and
your new RIP

149

Enhancing Impressario with Plug-Ins

How the Impressario File Conversion Pipeline Works
The key components of the Impressario file conversion pipeline are:
•

A database of File Type Rules (FTRs)

•

The wstype runtime filetype recognition utility

•

The fileconvert file conversion utility

File Type Rules
The file type rules of the FTR database are well-documented in the Indigo
Magic Integration Guide, which is available as an online book and is
installable from your IRIX CD.
The File Type Rules have two parts relevant to printing. The first part is a
TYPE rule for recognizing that a file is of a particular type, given the first 512
bytes of the file. The second part is a CONVERT rule for converting that type
to another type, with the eventual goal of being able to convert any file type
to a set of printable file types. Each CONVERT rule contains a pair of known
types (source and destination type), a Bourne shell command for going from
the source to the destination type, and a cost for the conversion. Impressario
builds on the standard IRIX database of filetypes, extending the FTR set to
handle additional input file types, and adding new destination file types.

Runtime File Type Recognition Utility
The wstype utility is used to determine the file type of a file or set of files. It
is similar to file(1) in basic operation, but has no hardcoded special cases and
no /etc/magic file, relying on the compiled FTR database for typing
information.
See the wstype(1) man page for additional information.

150

How the Impressario File Conversion Pipeline Works

File Conversion Utility
The fileconvert utility builds a directed acyclic graph out of all known file
types, determines the input file type, and attempts to find the lowest-cost
path from source to destination.
If a conversion path exists, fileconvert prints a Bourne shell command string
which, when executed, generates the destination file type on stdout. Most
model files simply execute this shell command string, piping the results to
the printer driver. This flexible, extensible mechanism enables Impressario
to print virtually any recognizable file type on any printer that is compliant
with Impressario.
See the fileconvert(1) man page for additional information.

151

Enhancing Impressario with Plug-Ins

Adding a New Filetype to Impressario
To extend Impressario to make a new type of file printable, you need only
perform the following steps:
1.

Write a filter to convert your new type.

2.

Write an FTR rule that recognizes the new filetype.

3.

Add a CONVERT rule from that type to a known Impressario type.

4.

Install and test your changes.

Writing a New Filter
First, write a filter to convert your new type to either STIFF or PostScript, the
two main formats for input to Impressario. Fileconvert requires that your
filter be able to accept input either on stdin or from a specified filename. It
should also be able to write output to stdout without using intermediate files,
so that the conversion can succeed, even if the converting host has low disk
space. See the Indigo Magic Integration Guide, Chapter 5, for more details. See
the gif2stiff(1) man page for an example.

Writing an FTR
Next, write an FTR that can recognize the new filetype given only the first
512 bytes of the file. See the Indigo Magic Integration Guide and the ftr(1) man
page for a description of the available primitives for matching a file’s type
and for a description of the additional parts of a good FTR.

Adding a CONVERT Rule
As part of your FTR, add a CONVERT rule from that type to a known
Impressario type. We strongly recommend that you convert image types to
the STIFF93aImage type and convert other non-image file formats to the
PostScriptFile type. Refer to Appendix A and the libstiff(3) man page for
information on writing STIFF output. Note that once you convert to either a
PostScriptFile or a STIFF93aImage, Impressario knows how to convert that
filetype to a printable format on any printer.

152

Adding a New Filetype to Impressario

Model files that are compliant with Impressario also automatically set the
proper environment variables for the options the user selected on the
spooler command line, and the standard Impressario CONVERT rules
automatically pick up the appropriate environment variables when
converting these file types to printable types. This is how user-specified
printing options are applied to the dynamically-constructed file conversion
pipeline.

Installation and Testing
The easiest way to show how to test a new filetype is by example.
Setting Up an Example

Our example makes the following assumptions:
•

The new filetype is called “BlastFile.”

•

The new FTR is in the directory /usr/tmp/blastfile.ftr.

•

A sample BlastFile is in the directory /usr/tmp/sample.blastfile.

•

All BlastFiles start with the word “blastfile.”

A sample (although incomplete) TYPE rule for our example would look like
this:
TYPE BlastFile
MATCH string(0,9) == "blastfile";
LEGEND Blast Image File
CONVERT BlastFile STIFF93aImage
COST 50
FILTER /usr/lib/print/blast2stiff $IMPR_IMG2STIFFOPTS

Testing the New Filetype

1.

To test the new filetype, become root by typing:
su

and supplying a password, if necessary.

153

Enhancing Impressario with Plug-Ins

2.

Copy your FTR into /usr/lib/filetype/install:
cp /usr/tmp/blastfiletype.ftr /usr/lib/filetype/install

3.

Compile the FTR database:
cd /usr/lib/filetype ; make

See the ftr(1) man page if any errors occur.
4.

Run wstype to verify that Impressario now recognizes your file type:
wstype /usr/tmp/sample.blastfile

You should see the following output:
/usr/tmp/sample.blastfile BlastFile

5.

Try to convert that file type to a printable file type. The most printable
filetype in the Impressario database is ImpressarioPostScriptFile, so
let’s try that:
fileconvert -d ImpressarioPostScriptFile \
/usr/tmp/sample.blastfile

You should get back something like:
PRINTFILES=”/usr/tmp/sample.blastfile” ; /usr/lib/print/blast2stiff
$IMPR_IMG2STIFFOPTS $PRINTFILES | /usr/lib/print/stiff2ps $IMPR_SGI2PSOPTS

Note: The above output would appear on one line.

If fileconvert does not return a valid shell command string, check the exit
code of the filter. If you are in the C shell, type:
echo $status

If you are in the Bourne shell, type:
echo $?

If the exit code is not zero, then fileconvert was unable to convert your
filetype. Verify that your destination filetype is convertible to a
printable type by checking the CONVERT rules in the FTR database
and making sure there is a conversion path from your destination type
to the Impressario type, and try the above steps again.
6.

Once the above steps work, verify that your filter produces valid
output by typing:
vstiff /usr/tmp/sample.blastfile

154

Adding a New Filetype to Impressario

This should bring up the vstiff(1) previewer, which uses the FTR
database of TYPE and CONVERT rules to convert to a screen-viewable
STIFF file. Use the “PostScript Options...” menu choice on the File
menu to choose different color spaces and depths. See the vstiff(1) man
page for more help.
Note: If your filter converts directly to STIFF93aImage, the PostScript
options in vstiff will not be applicable.

7.

Finally, try printing that file to an Impressario printer. Type:
lp -dprintername /usr/tmp/sample.blastfile

Watch the spooler log file for errors and the printstatus panel for printer
messages until the file prints. If you were able to vstiff the file, then you
should to be able to print it.
When you have completed this process, you should have the files shown in
Table 12-1. These files should be installed with the permissions and the
ownerships shown and at the locations shown. The actual file basename may
change but the pathname should not. Conversion filters should be installed
in /usr/lib/print.
Table 12-1

New Filetype Pathnames

Mode

Owner

Group

Full Pathname

-r--r--r--

root

sys

/usr/lib/filetype/install/blastfiletype.ftr

-rwxr-xr-x

root

sys

/usr/lib/print/blast2stiff

155

Enhancing Impressario with Plug-Ins

Using an Alternate PostScript RIP
Using an alternate PostScript Raster Image Processor (RIP) is extremely easy
in the Impressario open architecture. You can even switch RIPs on the fly, at
the last possible moment, without losing any of the features of Impressario’s
file conversion pipeline.
The steps required to add an alternate RIP to your system are:
1.

Make the new RIP command line compatible with the Impressario RIP,
psrip(1).

2.

Write a dummy TYPE.

3.

Test the alternative RIP.

4.

Package the files.

You should be able to use this alternate RIP instead of, or in addition to, the
standard Impressario interpreter.
Note: In the example below, the new RIP is called “blastrip” and is installed

in the directory /usr/lib/print, next to Impressario’s psrip.

Making the Command line Compatible
Your new RIP must be command-line compatible with psrip. Look at the
psrip(1) man page for more information on what that means. psrip accepts
ASCII and binary PostScript either on stdin or in a disk file, and generates a
variety of sizes, colorspaces, and depths of STIFF bitmaps on stdout.
Being command-line compatible with psrip is probably the most tedious part
of adding a new interpreter, but is well worth the effort when you consider
that you gain all the advantages of Impressario:

156

•

Plug-and-play printer drivers

•

Automatic filetype recognition

•

Automatic filetype conversion

Using an Alternate PostScript RIP

Writing a Dummy TYPE
The next step is to write a dummy TYPE and a simple CONVERT rule. First
create a new, empty TYPE definition for your output raster format. Here’s an
example:
TYPE BlastRasterBitmap
# dummy type for use in model file only
MATCH false;
CONVERT ImpressarioPostScriptFile BlastRasterBitmap
# convert from formatted, filtered ImpressarioPostScriptFile
# to a RIPped bitmap
COST
50
FILTER /usr/lib/print/blastrip $IMPR_PSRIPOPTS

Install that file in /usr/lib/filetype/install/blastrip.ftr and compile your FTR
database by typing:
su ; cd /usr/lib/filetype ; make

Now test the conversion and preview the bitmap by using vstiff:
fileconvert -d BlastRasterBitmap /etc/passwd | vstiff -stdin

If you run into problems viewing it, then save it to disk and use other tools
to verify that you have a valid STIFF file. However, if vstiff cannot view it,
then Impressario printer drivers will probably not be able to print it.

Testing the Alternate RIP
To use the alternative RIP in your printer model files instead of the default
psrip, change all references to “ImpressarioRasterBitmap” to
“BlastRasterBitmap.” The lines below were taken from the laserjet_model
template model file and the word “ImpressarioRasterBitmap” was changed
to “BlastRasterBitmap”:
# Use fileconvert to convert to the printer’s native format.
# For raster printers, it is BlastRasterBitmap.
# For PostScript printers, it is ImpressarioPostScriptFile.
#
CMD=‘$fileconvert $fileconvertopts -d BlastRasterBitmap $file 2> /dev/null‘

157

Enhancing Impressario with Plug-Ins

Packaging the Files
You are done now, and need only package these optional RIP files for
installation. The files you should be installing may have different names, but
should be installed in the following directories, with the permissions and
ownerships shown in Table 12-2.
Table 12-2

Alternative RIP Pathnames

Mode

Owner

Group

Full Pathname

-r--r--r--

root

sys

/usr/lib/filetype/install/blastrip.ftr

-rwxr-xr-x

root

sys

/usr/lib/print/blastrip

You should modify your printer’s model file to use the new RIP whenever
you want. You can, of course, still ask for ImpressarioRasterBitmap.
Note: Test carefully to make sure that your new RIP is, in fact, compatible

with the existing psrip before shipping your product.

158

Appendix A

Stream TIFF Data Format

This appendix describes the Stream TIFF
file format (STIFF), the primary
interchange file format between printer
filters and drivers. It also describes
libstiff, a C-language application
programming interface (API) used to
read and write Stream TIFF files.

Appendix A

A.

Stream TIFF Data Format

This appendix describes the Stream TIFF data format (STIFF), the primary
interchange file format between printer filters and drivers, and libstiff, a
C-language application programming interface (API) used to read and write
Stream TIFF files. Stream TIFF is also used by gscan(1) to store images in TIFF
files and to scan to the screen (in conjunction with vstiff(1)).
The major topics discussed are:
•

“Library Description” on page 162

•

“Library Access” on page 162

•

“Library Functions” on page 163

•

“Printing-Specific STIFF” on page 166

•

“Generic STIFF File Structure” on page 167

161

Stream TIFF Data Format

Library Description
libstiff provides a C-language application programming interface (API) to
the reading and writing of Stream TIFF files. Stream TIFF (STIFF) is a subset
of the Tag Image File Format (TIFF) Revision 6.0 originally developed by
Aldus Corporation. TIFF is an extremely flexible format, well suited for
monochrome and color bitmap images. The primary difference between
TIFF and STIFF is that while a TIFF file may require file seeking during
reading or writing, a STIFF file does not. This means that a STIFF file can be
read and written to both files and non-seekable streams such as pipes and
sockets. STIFF can be used by application developers to write TIFF 6.0
compliant files, and a STIFF file can be read by any TIFF reader that
conforms to the TIFF Revision 6.0 specifications. However, libstiff cannot be
used to read many standard TIFF files since STIFF is a subset of TIFF.
The functions provided by libstiff greatly simplify the reading and writing of
TIFF-compatible files. Using the STIFF API, TIFF 6.0-compatible STIFF files
can be read and written without the need to understand the structure of a
TIFF file and without the need to explicitly specify TIFF tags.

Library Access
There are two sets of libstiff functions. One set comprises the generic libstiff
API. These functions are designated by an ST prefix and may be used to read
and write generic STIFF files. To access these functions, an application must
include the header file stiff.h located in the /usr/include directory. The second
set of libstiff functions is tailored to reading and writing STIFF files that are
to be passed between printing filters and drivers. These printing-related
functions are designated by the prefix PST and are accessed through the
header file printstiff.h, also located in /usr/include. If printstiff.h is used, the
header stiff.h need not be specified. The generic and printing-specific
functions may be freely intermixed within an application.
Programs that call libstiff functions must link with the libstiff.a library located
in the directory /usr/lib. An example command line is shown below:
cc -o myprog myprog.c -lstiff

162

Library Functions

Library Functions
libstiff provides the generic functions listed in Table A-1.
Table A-1

STIFF Generic Functions

Name

Description

Stream Handling
STOpen

Opens a STIFF stream on the specified file descriptor

STClose

Closes a STIFF stream opened by STOpen

STSkipTo

Skips forward on a specified stream

Reading and Writing
STReadImageHeader Reads the STIFF image header from the specified stream
STWriteImageHeader Writes the image header to the specified stream
STRead

Reads the specified amount of image data from the stream

STWrite

Writes the specified amount of image data to the stream

TIFF Tag Support
STAddTag

Adds the specified tag to the TIFF tag list

STRemoveTag

Removes the specified tag from the output TIFF tag list

STGetTag

Searches the tag list for the specified TIFF tag

STPrintTags

Prints the current TIFF tag list

Execution Error Handling
STPerror

Prints error messages to standard error

STErrorString

Gets the error string for the specified error code

163

Stream TIFF Data Format

STIFF also provides the printing-specific functions listed in Table A-2.
Table A-2

STIFF Printing-Specific Functions

Name

Description

PSTReadImageHeader Reads the printing-specific STIFF image header from the
stream
PSTWriteImageHeader Writes the printing-specific STIFF image header to the
stream

Example Usage
The sequence of operations for writing a STIFF stream is as follows:
1.

Obtain a writable file descriptor. Note that this descriptor can be
associated with a non-seekable stream.

2.

Call STOpen with the writable file descriptor and the flag ST_WRITE.

3.

Fill in the STIFF image header (STImageHeader or PSTImageHeader).

4.

Optionally, add any application-specific TIFF tags to the file using
STAddTag.

5.

Call the image header write function STWriteImageHeader or
PSTWriteImageHeader.

6.

Write the image data using STWrite.

7.

Repeat steps 3 through 6 for each page of image data.

8.

Close the STIFF file using STClose.

9.

Close the file descriptor.

The sequence of operations for reading a STIFF stream is as follows:

164

1.

Obtain a readable file descriptor. Note that this descriptor can be
associated with a non-seekable stream.

2.

Call STOpen with the readable file descriptor and the flag ST_READ.

3.

Call the image header read function STReadImageHeader or
PSTReadImageHeader.

Library Functions

4.

Access the fields of the image header structure to determine the amount
of image data to be read for this page.

5.

Optionally, retrieve any application-specific TIFF tags from the file
using STGetTag.

6.

Read the image data using STRead.

7.

Repeat steps 3 through 6 for each page of image data. The last page of
image data will be an empty page (that is, the amount of data equals
zero). An STEEOF error occurs if an attempt is made to read past the
end of the STIFF.

8.

Close the STIFF stream using STClose.

9.

Close the file descriptor.

If an error condition is returned by a libstiff function, STPerror can be used to
print a diagnostic error message to the standard error, and STErrorString can
be used to obtain an appropriate error message for display to the user by
other means.

165

Stream TIFF Data Format

Printing-Specific STIFF
The printing-specific functions (PST) provided by libstiff read and write
STIFF files as described above. The printing-specific aspect of these
functions is found in the image header structure. PSTImageHeader, the
printing-specific image header, contains all fields of the STImageHeader plus
printing-specific information fields such as image resolution and halftoning
method.
If a STIFF file is written using the generic functions and is read using the
printing-specific functions, default values are used for the PSTImageHeader
fields not found in the STIFF. Similarly, a STIFF file written using the
printing-specific functions can be read by the generic functions. In this case,
the additional information in the stream can be ignored or obtained using
the STGetTag function.
Refer to the header file /usr/include/printstiff.h for additional information
regarding printing-specific STIFF.
Printer driver developers should pay special attention to the command-line
options string that is part of a PST image header. See the LaserJet example
driver for an example of how to combine parsing the command-line and
image-header driver options.

166

Generic STIFF File Structure

Generic STIFF File Structure
While it is not necessary to understand the STIFF file structure to use libstiff,
this explanation is provided for those who need to know. A Stream TIFF file
is first and foremost a valid TIFF file. STIFF is derived from the TIFF 6.0
specifications available from Aldus Corporation (see below). The terms used
below to describe a STIFF file (for example, IFD) are explained in the TIFF
specifications and are not described here.
The primary restriction STIFF places on the TIFF structure is that all data
must be read from or written to the file without the need to seek within the
file. Specifically, within a STIFF file:
1.

The bitmap image data must be in page-number order.

2.

Data that does not fit in the value section of a tag must be located
immediately after the IFD and must occur in the same order in which
the tags are encountered. The exception to this is the image data itself,
which must come last for each page.

3.

Image data must immediately follow the IFD and any offset values
associated with it.

4.

A terminating, empty IFD is always added to the end of the STIFF file.
This IFD guarantees that an IFD with 0000 in its “next IFD” field
appears in the IFD chain. Note that this empty IFD is not encountered
when following IFD pointers if the last “real” IFD is written with the
last parameter set to 1. While the TIFF specifications states that IFDs
should not be empty, relaxing this restriction appears to have no impact
on TIFF compatibility.

A generic STIFF file can be represented as shown in Figure A-1.

167

Stream TIFF Data Format

TIFF header (8 bytes)
Optional intervening space
IFD for page 1
Data for long values in IFD 1
Image data for page 1
Optional intervening space
IFD for page 2
Data for long values in IFD 2
Image data for page 2
•••
Terminating empty IFD

Figure A-1

Generic STIFF File Structure

The libstiff functions support only the Motorola (MM) byte ordering. In
addition to supporting TIFF class R, G, and B data, libstiff supports the
CMYK color image data type (PhotoMetricInterpretation = 5 and InkSet = 1)
and four additional color image separation types: CMY, YMC, YMCK, and
KCMY.
For these additional types, PhotoMetricInterpretation = 5, InkSet = 2,
NumberOfInks = 3 or 4, and the InkNames tag is used to indicate the inks
contained in each channel.
When reading an image header, libstiff parses the ink names for these
additional types and sets the type field of the STImageHeader structure to the
appropriate value defined in stiff.h. When writing an image header, libstiff

168

Generic STIFF File Structure

writes the appropriate PhotoMetricInterpretation, InkSet, NumberOfInks, and
InkNames tags based on the value of the type field of the STImageHeader
structure.
The CMYK data format is a TIFF data format extension, as shown in
Table A-3.
Table A-3

CMYK Data Format

Tag

Possible Values

BitsPerSample

(1,1,1,1) (4,4,4,4) (8,8,8,8)

PhotoMetricInterpretation

5

SamplesPerPixel

4

PlanarConfiguration

1,2

NumberOfInks

4

The CMY data class is a subset of the CMYK class and differs from the
CMYK class in a TIFF-compliant manner, as shown in Table A-4.
Table A-4

CMY Data Format

Tag

Possible Values

BitsPerSample

(1,1,1,1)(1,1,1) (4,4,4) (8,8,8)

PhotoMetricInterpretation

5

SamplesPerPixel

3 (4 or 8 bits, 1 bit planar) or 4 (1 bit chunky)

PlanarConfiguration

1,2

NumberOfInks

3

169

Stream TIFF Data Format

The YMC data class is similar to the CMY class except that data is organized
as YMC instead of CMY (see Table A-5). When using libstiff, YMC data
corresponds to the data type ST_TYPE_YMC.
Table A-5

YMC Data Format

Tag

Possible Values

BitsPerSample

(1,1,1,1)(1,1,1) (4,4,4) (8,8,8)

PhotoMetricInterpretation

5

SamplesPerPixel

3 (4 or 8 bits, 1 bit planar) or 4 (1 bit chunky)

PlanarConfiguration

1,2

NumberOfInks

3

InkSet

2

InkNames

yellow, magenta, cyan

The YMCK class is similar to the CMYK class except that data is organized
as YMCK instead of CMYK (see Table A-6). When using libstiff, YMCK data
corresponds to the data type ST_TYPE_YMCK.
Table A-6

170

YMCK Data Format

Tag

Possible Values

BitsPerSample

(1,1,1,1) (4,4,4,4) (8,8,8,8)

PhotoMetricInterpretation

5

SamplesPerPixel

4

PlanarConfiguration

1,2

NumberOfInks

4

InkSet

2

InkNames

yellow, magenta, cyan, black

Generic STIFF File Structure

The KCMY class is similar to the CMYK class except that the data is
organized as KCMY instead of CMYK (see Table A-7). When using libstiff,
KCMY data corresponds to the data type ST_TYPE_KCMY.
Table A-7

KCMY Data Format

Tag

Possible Values

BitsPerSample

(1,1,1,1) (4,4,4,4) (8,8,8,8)

PhotoMetricInterpretation

5

SamplesPerPixel

4

PlanarConfiguration

1,2

NumberOfInks

4

InkSet

2

InkNames

black, cyan, magenta, yellow

Note that for the RGB, CMY, and YMC classes with BitsPerSample values of
(1,1,1) and a PlanarConfiguration value of 1, pixels are stored two to a byte,
with the bits ordered from most-significant to least-significant.
For example, CMY data is stored as:
CMY0CMY0

Rows are padded to contain an integral number of bytes.
Refer to the header file stiff.h for additional information regarding the STIFF
file structure.

171

Appendix B

Silicon Graphics Image File Format API

This chapter describes libimp, the Clanguage application programming
interface (API) for reading and writing
Silicon Graphics Image Format files.

Appendix B

B.

Silicon Graphics Image File Format API

This appendix describes libimp, the C-language application programming
interface (API) for reading and writing Silicon Graphics Image format files.
The major topics discussed are:
•

“Library Description” on page 175

•

“Library Access” on page 176

•

“Library Functions” on page 176

•

“IMPImage Structure” on page 179

Library Description
libimp provides a C-Language application programming interface (API) for
reading and writing Silicon Graphics Image format files and for performing
a number of format-independent image processing operations. These
operations include color space conversion and filtered image zooming.
libimp provides all functionality of the libimage library1. In addition, libimp
provides function prototypes, a documented interface, reliable error
reporting, and a number of other enhancements.

1

See the rgb(4) man page for a description of libimage.

175

Silicon Graphics Image File Format API

Library Access
A program that calls libimp functions must include the header file imp.h
located in the directory /usr/include. In addition, the program must link with
the libimp.a library located in /usr/lib. The link line would look like this:
... -limp ...

Library Functions
The libimp library, which is based heavily on the libimage and libgutil
libraries, consists of two main sets of functions. The functions shown in
Table B-1 perform operations on Silicon Graphics Image format files.
Table B-1

Silicon Graphics Image Format File Functions

Function

Description

Image Access
impOpen

Opens an Silicon Graphics Image format file for reading or
writing

impOpenFd

Opens an Silicon Graphics Image file format for reading or
writing

impClose

Closes an Silicon Graphics Image file format for reading or
writing

impCloseFd

Closes an Silicon Graphics Image Format format file for
reading or writing

Image I/O
impReadRow

Reads image row

impReadRowB

Reads byte image row

impWriteRow

Writes image row

impWriteRowB

Writes byte image row

The functions shown in Table B-2 perform operations on image data in a
format-independent manner.

176

Library Functions

Table B-2

Format-Independent File Functions

Function

Description

Zooming
impCreateZoom

Creates zoom operator

impDestroyZoom

Destroys zoom operator

impResetZoom

Resets zoom row cache

impZoomRow

Zooms an image row

Data Packing
impPackRow

Packs two-byte data into one byte

impUnpackRow

Unpacks one-byte data into two bytes

Math Operations
impZeroRow

Sets row to zero

impInitRow

Initializes a row to a value

impCopyRow

Copies a row

impSAddRow

Adds a value to a row

impVAddRow

Adds two rows

impSSubRow

Subtracts a value from a row

impVSubRow

Subtracts two rows

impSMulRow

Multiplies a row by a value

impSDivRow

Divides a row by a value

impClampRow

Clamps row values

Color Space Conversion
impRGBtoW

Converts an array from RGB format to W format

impWtoRGB

Converts an array from W format to RGB format

impRGBtoK

Converts an array from RGB format to K format

177

Silicon Graphics Image File Format API

Table B-2 (continued)

Format-Independent File Functions

Function

Description

impKtoRGB

Converts an array from K format to RGB format

impRGBtoCMY

Converts an array from RGB format to CMY format

impCMYtoRGB

Converts an array from CMY format to RGB format

impRGBtoYIQ

Converts an array from RGB format to YIQ format

impYIQtoRGB

Converts an array fromYIQ format to RGB format

impRGBtoYUV

Converts an array from RGB format to YUV format

impYUVtoRGB

Converts an array from YUV format to RGB format

impRGBtoYCbCr

Converts an array from RGB format to YCbCr format

impYCbCrtoRGB

Converts an array from YCbCr format to RGB format

impRGBtoCMYK

Converts an array from RGB format to CMYK format

impCMYKtoRGB

Converts an array from CMYK format to RGB format

impRGBtoDevCMYK

Converts an array from RGB format to device CMYK
format

impRGBtoHSV

Converts an array from RGB format to HSV format

impHSVtoRGB

Converts an array from HSV format to RGB format

impRGBtoHLS

Converts an array from RGB format to HLS format

impHLStoRGB

Converts an array from HLS format to RGB format

Error Handling

178

impPerror

Prints libimp execution error messages to standard error

impErrorString

Obtains libimp execution error messages

IMPImage Structure

IMPImage Structure
The IMPImage structure contains public and private information about an
Silicon Graphics image file. This structure is identical both in size and field
naming to the IMAGE structure defined in the header file image.h, included
by applications that use the libimage library. While it has been common
practice to directly modify the public fields of the image structure, this is not
recommended. Macros are defined in imp.h for manipulating the structure
fields. It is strongly recommended that these macros be used to set and get
values from the image structure. The IMPImage structure is defined as
follows:
typedef struct _impImage {
/******* Public image header information (archived) */
ushort_t imagic; /* Silicon Graphics Image file magic number */
ushort_t type;
/* Raster type (e.g. verbatim, rle) */
ushort_t dim;
/* Image dimension */
ushort_t xsize; /* X size (pixels) */
ushort_t ysize; /* Y size (pixels) */
ushort_t zsize; /* Number of channels (e.g. rgb = 3) */
long
min;
/* Minimum intensity in image */
long
max;
/* Maximum intensity in image */
ulong_t wastebytes;
/* Padding */
char
name[IMP_NAME_MAX+1]; /* Image name */
ulong_t colormap;
/* Image type (e.g. colormap, normal) */
/*******
long
ushort_t
short
short
short
short
short
short
short
short
ulong_t
ulong_t
ulong_t
long
} IMPImage;

Private image header information (core use only) */
file;
flags;
dorev;
x;
y;
z;
cnt;
*ptr;
*base;
*tmpbuf;
offset;
rleend;
*rowstart;
*rowsize;

179

Silicon Graphics Image File Format API

Note: ushort_t and ulong_t are unsigned short and unsigned long,

respectively.
Arguments:

180

magic

Magic number identifying this file as an Silicon Graphics
Image Format file.

type

Bitwise-OR combined code indicating the raster encoding
method and the number of bytes per pixel per channel.
Currently, Silicon Graphics Image files support either a
verbatim, uncompressed raster encoding or a run-length,
compressed encoding. Both of these encodings are available
at one or two bytes per pixel per channel. The header file
imp.h defines codes for all supported combinations of
encoding methods and pixel widths.

dim

Number of dimensions to the image. A colormap file has
dimension one (length), a black and white image has
dimension two (height and width), and an RGB image has
dimension three (height, width, and depth).

xsize, ysize

Image size in pixels.

zsize

Number of color channels or depth. A black and white
image has one channel and an RGB image has three
channels.

min, max

The minimum and maximum intensity values in the image.
These values are the minimum and maximum for all
channels combined.

name

A descriptive name string for the image.

colormap

The image type. Refer to imp.h for the supported image type
codes. The field is named colormap for compatibility with
the IMAGE structure used by the libimage library.

Image Access Functions

Image Access Functions
impOpen Function

This function opens the image file specified by fname. If mode is r, the file is
opened for reading. If mode is w, the file is opened for writing and created if
it does not exist, or truncated to zero length if it does exist.
impOpenFd opens the image file pointed to by the file descriptor fd. The
descriptor's permissions must permit the operations specified by mode. That
is, if mode is w, the descriptor must have write permission. In addition, it
must be possible to seek on the specified descriptor. At this time, read/write
mode is not supported for Silicon Graphics Image files. Upon successful
execution, both functions return a pointer to an Silicon Graphics Image file
structure.
Synopsis:
#include 
IMPImage* impOpen(const char *fname, const char *mode, ...);
IMPImage* impOpenFd(int fd, const char *mode, ...);

In write mode, impOpen and impOpenFd require that these additional
parameters be specified:
uint_t rasterType, uint_t dimension, uint_t xSize,
uint_t ySize, uint_t numChannels, uint_t imageType, char *name

Note: uint_t stands for unsigned int.
Arguments:

rasterType

Specifies the raster encoding method and the number of
bytes per pixel per channel. Silicon Graphics Image Format
files can be written either uncompressed or with run-length
encoding compression, and with one or two bytes per pixel
per channel. Refer to imp.h for the supported raster types.

dimension

Specifies the number of dimensions in the image. A
colormap file has dimension one, a black and white image
has dimension two, and an RGB image has dimension three.

xSize, ySize

Specifies the image size in pixels.

181

Silicon Graphics Image File Format API

numChannels

Specifies the number of image color channels. A black and
white image has one channel and an RGB image has three
channels.

imageType

Specifies how the image data is to be interpreted. Image
data is either actual color values (normal), screen colormap
indices (screen), or a colormap (colormap). Refer to imp.h for
the supported image types.

name

Specifies a descriptive string for the image. Strings longer
than IMP_NAME_MAX characters are truncated. Refer to
imp.h for the value of IMP_NAME_MAX. If this parameter
is specified as NULL, the string “no name” is written into
the file. Use the empty string "" to write an empty name
string into the image.

impOpen, impOpenFd, impClose, and impCloseFd Functions

impClose closes an Silicon Graphics Image Format file previously opened by
impOpen or impOpenFd. Among other tasks, impClose closes the file
descriptor associated with an image file. If the image was opened using
impOpenFd, the file descriptor specified in that function call will be closed by
impClose.
impCloseFd performs the same function as impClose, but it leaves open the file
descriptor associated with the image and returns it in the parameter fdp. It
then becomes the responsibility of the caller to close the file descriptor when
it is no longer needed. It is essential that either impClose or impCloseFd be
called at the completion of writing an Silicon Graphics Image file so that all
buffered data can be written and the image header can be updated.
Synopsis:
#include 
int impClose(IMPImage *image);
int impCloseFd(IMPImage *image, int *fdp);
Return Value:

182

Image Access Functions

impOpen and impOpenFd return a pointer to an image structure if execution
was successful. NULL is returned and IMPerrno is set if an execution error
has occurred.
impClose and impCloseFd return 0 if execution was successful; a -1 is returned
and IMPerrno is set if an execution error has occurred.
Execution Error Codes:

impOpen and impOpenFd fail under the following circumstances:
IMP_ERR_READWRITE
IMP_ERR_MEMALLOC
IMP_ERR_BADMAGIC
IMP_ERR_BADRASTER
IMP_ERR_BADIMAGE

In addition, impOpenFd fails under the following circumstances:
IMP_ERR_BADFD
IMP_ERR_SEEK

impClose and impCloseFd fail under the following circumstances:
IMP_ERR_WRITEFLAG
IMP_ERR_BADBPP
IMP_ERR_BADIMAGE

Note: The storage for the IMPImage structure is allocated by the image open

function. This storage is deallocated by the impClose and impCloseFd
functions. The caller should not explicitly reallocate or deallocate any
storage related to the image structure.
See also:

libimp(3), impReadRow(3), impReadRowB(3)

Data Packing Functions
impPackRow and impUnpackRow Functions
Synopsis:

183

Silicon Graphics Image File Format API

#include 
void impPackRow(uchar_t *dptr, short *sptr, int n);
void impUnpackRow(short *dptr, uchar_t *sptr, int n);

impPackRow converts the array of short integers pointed to by sptr into the
array of unsigned char values pointed to by dptr. Source data that is too large
to fit in a character is truncated. For example, the source value 0x0B56 will
be converted into 0x56 in the destination array. impUnpackRow converts the
array of unsigned char values pointed to by sptr into the array of short
integers pointed to by dptr. For example, the source value 0x56 will be
converted into 0x0056 in the destination array. The parameter n specifies the
number of elements in the source and destination arrays.
Note: The allocation of storage for the source and destination arrays is the

responsibility of the caller.
See also:

libimp(3)

Error Handling Functions
impPerror and impErrorString Functions
Synopsis:
#include 
void impPerror(const char *str);
char* impErrorString(int errCode);
extern int IMPerrno;

impPerror prints error messages to stderr in a format similar to the standard
C library function perror(3C). If an error occurs during a libimp function call,
the global error variable IMPerrno will be set with an error code. The error
code will be either a system error code (errno) or a libimp-specific code. The
symbolic names for the libimp error codes are defined in imp.h. The value of
IMPerrno is used by impPerror as an index to a table of error messages.

184

Image Access Functions

impPerror prints user-supplied string str followed by a colon (:), a space, and
the error message corresponding to the current value of IMPerrno.
If the string str is the NULL string (""), no colon or space will be printed, only
the error message. The error message will be either a system error message
or a libimp-specific message. To be of most use, a call to impPerror should be
made immediately following the libimp function call where an error has been
detected. impErrorString is similar to the strerror(3C) function and returns the
error message corresponding to the error code specified by errCode.
If errCode is less than IMP_ERR_BASE, the message returned is a system
error message generated by strerror. If errCode is one of the error codes
specified in imp.h, the returned string is a libimp-specific error message.
See also:

libimp(3), perror(3C), strerror(3C)

Image I/O Functions
impReadRow, impReadRowB, impWriteRow, and impWriteRowB
Functions
Synopsis:
#include 
int impReadRow(IMPImage *image, short *buffer,
ushort_t row, ushort_t channel);
int impReadRowB(IMPImage *image, uchar_t *buffer,
ushort_t row, ushort_t channel);
int impWriteRow(IMPImage *image, short *buffer,
ushort_t row, ushort_t channel);
int impWriteRowB(IMPImage *image, uchar_t *buffer,
ushort_t row, ushort_t channel);

impReadRow and impReadRowB each read a row of image data from the
specified channel of an Silicon Graphics Image Format file.

185

Silicon Graphics Image File Format API

impReadRow stores the row data in an array of short integers and can read
image data that is one or two bytes per pixel per channel in width.
impReadRowB stores the data in a character array and can handle only image
data that is one byte per pixel per channel wide.
If impReadRowB is called to read image data that is two bytes per pixel per
channel, an error condition is reported. impWriteRow and impWriteRowB
each write a row of image data to the specified channel of an Silicon
Graphics Image file. impWriteRow writes one or two bytes per pixel per
channel image row data. impWriteRowB writes only one byte per pixel data.
It is an error to use impWriteRowB to write to images that expect two bytes
per pixel per channel data.
The functions take the following parameters:
image

Pointer to an IMPImage structure returned by a call to
impOpen or impOpenFd.

buffer

Caller-allocated buffer containing the data to write to or to
be filled with the data read from the image. The amount of
storage allocated for the buffer should be impXSize(image) *
sizeof(short) if impReadRow or impWriteRow is used and
impXSize(image) if impReadRowB or impWriteRowB is used.

row

The image row to read. Rows are numbered from 0 through
impYSize(image) minus 1.

channel

The image channel to read. Channels are numbered from 0
through impNumChannels(image) minus 1.

Return Value:

If execution was successful, all functions return the number of pixels (not
bytes) read or written. If an execution error occurred, -1 is returned and
IMPerrno is set.
Execution Error Codes:

impWriteRow and impWriteRowB fails under the following circumstances:
IMP_ERR_WRITEFLAG
IMP_ERR_BADBPP
IMP_ERR_BADIMAGE
IMP_ERR_SHORTWRITE

186

Image Access Functions

impReadRow and impReadRowB fails under the following circumstances:
IMP_ERR_READFLAG
IMP_ERR_BADBPP
IMP_ERR_BADIMAGE
IMP_ERR_SHORTREAD

Note: It is the caller's responsibility to allocate enough buffer storage for
image row data.
See also:

libimp(3), impOpen(3)

187

Silicon Graphics Image File Format API

Color Space Conversion Functions
These functions perform color space conversion between a given color space
and RGB. The actual transformations performed are described below.
Certain functions specify the parameter unity. unity should be set to the
value of maximum possible intensity for the arrays specified. For example,
if 8-bit data is being converted, unity would be specified as 255. If the data
makes use of the full 16 bits available in each array element, unity would be
specified as 65535. Note that the parameter n specifies the number of
elements in the arrays and not the number of bytes.
impRGBtoW, impWtoRGB Functions

Figure B-1 shows the equation for W conversions.

W=

0.299 0.587 0.114

G
B

*

W

R
=

R
G
B

W
W

Figure B-1

W Conversions

Synopsis:
#include 
void impRGBtoW(short *rbuf, short *gbuf, short *bbuf,
short *wbuf, int n);
void impWtoRGB(short *wbuf, short *rbuf, short *gbuf,
short *bbuf, int n);

impRGBtoK, impKtoRGB Functions

Figure B-2 shows the equation for K conversions.

188

Image Access Functions

1.0 - R
K =

0.299 0.587 0.114

Figure B-2

*

1.0 - G
1.0 - B

K Conversions

Synopsis:
#include 
void impRGBtoK(short *rbuf, short *gbuf, short *bbuf,
short *kbuf, short unity, int n);
void impKtoRGB(short *kbuf, short *rbuf, short *gbuf,
short *bbuf, short unity, int n);

impRGBtoCMY, impCMYtoRGB Functions

Figure B-3 shows the equation for CMY conversions.
C
M

1.0 - R
=

R
G
B

1.0 - G
1.0 - B

Y

1.0 - C
=

1.0 - M
1.0 - Y

Figure B-3

CMY Conversions

Synopsis:
#include 
void impRGBtoCMY(short *rbuf, short *gbuf, short *bbuf,
short *cbuf, short *mbuf, short *ybuf,
short unity, int n);
void impCMYtoRGB(short *cbuf, short *mbuf, short *ybuf,
short *rbuf, short *gbuf, short *bbuf,
short unity, int n);

189

Silicon Graphics Image File Format API

impRGBtoYIQ, impYIQtoRGB Functions

Figure B-4 shows the equation for YIQ conversions.
Y

0.299 0.587 0.114

I

0.596 -0.274 -0.322

=

Q

0.212 -0.523 0.311

R
G

R
G

*

B

1.000 0.955 0.622
=

B

1.000 -0.271 -0.648
1.000 -1.107 1.702

Figure B-4

Y
I

*

Q

YIQ Conversions

Synopsis:
#include 
void impRGBtoYIQ(short *rbuf, short *gbuf, short *bbuf,
short *ybuf, short *ibuf, short *qbuf,
int n);
void impYIQtoRGB(short *ybuf, short *ibuf, short *qbuf,
short *rbuf, short *gbuf, short *bbuf,
int n);

impRGBtoYUV, impYUVtoRGB Functions

Figure B-5 shows the equation for YUV conversions.
Y
U

0.299 0.587 0.114
=

V

0.615 -0.515 -0.100

R
G

R

*

1.000 0.000 1.140
=

B

Figure B-5

190

-0.147 -0.289 0.436

1.000 -0.395 -0.581
1.000 2.032 0.000

YUV Conversions

G
B
Y

*

U
V

Image Access Functions

Synopsis:
#include 
void impRGBtoYUV(short *rbuf, short *gbuf, short *bbuf,
short *ybuf, short *ubuf, short *vbuf,
int n);
void impYUVtoRGB(short *ybuf, short *ubuf, short *vbuf,
short *rbuf, short *gbuf, short *bbuf,
int n);

impRGBtoYCbCr, impYCbCrtoRGB Functions

Figure B-6 shows the equation for YCbCr conversions.
Y

0.299

0.587

0.114

-0.169

-0.331

0.500

Cr

0.500

-0.419

-0.081

R

1.000

-0.001

1.402

1.000

-0.344

-0.714

1.000

1.772

0.001

Cb

G

=

=

B

Figure B-6

R

*

G
B
Y

*

Cb
Cr

YCbCr Conversions

Synopsis:
#include 
void impRGBtoYCbCr(short *rbuf, short *gbuf, short *bbuf,
short *ybuf, short *cbbuf, short *crbuf,
int n);
void impYCbCrtoRGB(short *ybuf, short *cbbuf, short *crbuf,
short *rbuf, short *gbuf, short *bbuf,
int n);

impRGBtoCMYK, impRGBtoDevCMYK, impCMYKtoRGB Functions

Figure B-7 shows the equation for CMYK conversions.

191

Silicon Graphics Image File Format API

Ci
Mi
Yi
K
C
M
Y

=
=
=
=
=
=
=

1.0 - R
1.0 - G
1.0 - B
Min(Ci, Mi, Yi)
Ci - K
Mi - K
Yi - K

Ci
Mi
Yi
Ki
Kucr
Device M
Device C
Device Y
Device K

Figure B-7

=
=
=
=
=
=
=
=
=

Ci
Mi
Yi
R
G
B

=
=
=
=
=
=

C+K
M+K
Y+K
1.0 - Min(1.0, Ci)
1.0 - Min(1.0, Mi)
1.0 - Min(1.0, Yi)

1.0 - R
1.0 - G
1.0 - B
Min(Ci, Mi, Yi)
UCR(Ki)
Min(1.0, Max(0.0, Ci - Kucr))
Min(1.0, Max(0.0, Mi - Kucr))
Min(1.0, Max(0.0, Yi - Kucr))
BG(Ki)

CMYK Conversions

Synopsis:
#include 
void impRGBtoCMYK(short *rbuf, short *gbuf, short *bbuf,
short *cbuf, short *mbuf, short *ybug,
short *kbuf, short unity, int n);
void impRGBtoDevCMYK(short *rbuf, short *gbuf, short *bbuf,
short *cbuf, short *mbuf, short *ybug,
short *kbuf, IMPUCRFunc ucr, IMPBGFunc bg,
short unity, int n);
short (*IMPBGFunc)(short k);
short (*IMPUCRFunc)(short k);
void impCMYKtoRGB(short *cbuf, short *mbuf, short *ybuf,
short *kbuf, short *rbuf, short *gbug,
short *bbuf, short unity, int n);

192

Image Access Functions

impRGBtoHSV, impHSVtoRGB Functions
Synopsis:
#include 
void impRGBtoHSV(short *rbuf, short *gbuf, short *bbuf,
float *hbuf, float *sbuf, float *vbuf,
int n);
void impHSVtoRGB(float *hbuf, float *sbuf, float *vbuf,
short *rbuf, short *gbuf, short *bbuf,
int n);

impRGBtoHLS, impHLStoRGB Functions

For HSV conversions, refer to Computer Graphics, Principals and Practice,
Foley and Van Dam, 2nd Edition, pages 590-592. For HLS conversions, refer
to pages 592-595.
Synopsis:
#include 
void impRGBtoHLS(short *rbuf, short *gbuf, short *bbuf,
float *hbuf, float *lbuf, float *sbuf,
short unity, int n);
void impHLStoRGB(float *hbuf, float *lbuf, float *sbuf,
short *rbuf, short *gbuf, short *bbuf,
short unity, int n);

Note: It is the caller's responsibility to allocate all buffer storage.
See Also:

libimp(3)

193

Silicon Graphics Image File Format API

Math Operation Functions
impZeroRow, impInitRow, impCopyRow, impSAddRow, impVAddRow,
impSSubRow, impVSubRow, impSMulRow, impSDivRow,
impClampRow Functions
Synopsis:
#include 
void impZeroRow(short *dptr, int n);
void impInitRow(short *dptr, int val, int n);
void impCopyRow(short *dptr, short *sptr, int n);
void impSAddRow(short *dptr, short *sptr, int val, int n);
void impVAddRow(short *dptr, short *sptr1, short *sptr2,
int n);
void impSSubRow(short *dptr, short *sptr, int val, int n);
void impVSubRow(short *dptr, short *sptr1, short *sptr2,
int n);
void impSMulRow(short *dptr, short *sptr, int val, int n);
void impSDivRow(short *dptr, short *sptr, int val, int n);
void impClampRow(short *dptr, short *sptr, int lov,
int hiv, int n);

194

Image Access Functions

In the following descriptions, the parameter n specifies the number of
elements in an array and not the number of bytes in the array. In addition,
functions that take a source array pointer and a destination array pointer can
specify the same array as both a source and destination.
impZeroRow

Initializes to zero the array pointed to by dptr.

impInitRow

Initializes the array dptr to the value val.

impCopyRow

Copies the array sptr to the array dptr.

impSAddRow

Adds the value val to each element of the array sptr and
stores the result in the array dptr.

impVAddRow

Adds the corresponding elements of sptr1 and sptr2 and
stores the result in the array dptr.

impSSubRow

Subtracts the value val from each element of the array sptr
and stores the result in the array dptr.

impVSubRow

Subtracts the corresponding elements of sptr2 from those of
sptr1 and stores the result in the array dptr.

impSMulRow

Multiplies each element of the array sptr by val and stores
the result in dptr.

impSDivRow

Divides each element of the array sptr by val and stores the
result in dptr.

impClampRow

Clamps the values of the array sptr between the values lov
and hiv inclusive. The result is stored in the array dptr.

Note: It is the caller's responsibility to allocate all buffer storage.
Note: Since the arrays referenced by these functions are short integer arrays,

the caller should be aware of overflow/wraparound conditions.
See also:

libimp(3)

195

Silicon Graphics Image File Format API

Zooming Functions
impCreateZoom, impDestroyZoom, impResetZoom, impZoomRow
Functions
Synopsis:
#include 
IMPZoom* impCreateZoom(ushort_t srcXSize, ushort_t srcYSize,
ushort_t dstXSize, ushort_t dstYSize,
IMPReadRowFunc readRowFunc,
int numChannels,
IMPFilterType filterType,
float blurFactor);
void impDestroyZoom(IMPZoom *zoom);
void impResetZoom(IMPZoom *zoom);
int impZoomRow(IMPZoom *zoom, short *buffer,
ushort_t row, void *clientData);

The libimp library provides an API for performing image resizing or
zooming. Images can be zoomed up or down using any of a number of
resampling methods. The resampling methods divide into two categories.
The first resampling category is non-filtered zooming (also known as
replicative zoom, decimation). The second resampling category is filtered
zooming where a filter of a given shape is applied to the data. The image
zooming is performed on a row-by-row basis using a one-pass,
two-dimensional convolution.
To zoom one or more rows of an image, first create a zoom operator by
calling impCreateZoom. One of the parameters to impCreateZoom is a pointer
to a function that will be called during the zoom to read rows of the source
image. To obtain zoomed rows, call impZoomRow. When all desired zoomed
rows have been obtained, call impDestroyZoom to deallocate storage held by
the zoom operator. When filtered zooming is performed, a number of
contiguous rows of image data are cached. Often all rows of a given image
channel are zoomed, followed by all rows of the next channel. Since rows are
cached, the cache should be flushed when switching between image
channels. The impResetZoom function performs this row cache flushing
operation.

196

Image Access Functions

The impCreateZoom function has the following parameters:
srcXSize, srcYSize
Width and height of the source image in pixels.
dstXSize, dstYSize
Width and height of the destination (that is, zoomed) image
in pixels.
readRowFunc

Pointer to a function that will be called to read a row from
the source image. The prototype for this function is:
int (*IMPReadRowFunc)(short *buffer,
ushort_t row,
void *clientData);

The function should read the image row indicated by row and place the data
in buffer. The storage for buffer is allocated and deallocated by the zoom
operator and should not be manipulated by the read row function. clientData
is a pointer to caller-specific information. The caller may specify a pointer to
client data when calling the impZoomRow function. That pointer is passed to
the read row function.
At the caller's discretion, this pointer may be set to NULL. A common use of
the client data is to pass a pointer to a structure containing the image
structure pointer and the channel number. The read row function must
return -1 if it encounters an error while obtaining the row data and must
return a value of 0 or greater if the function succeeds.
numChannels

Specifies the number of channels of image data that are
packed on a single row. For example, if each row contains
data for only a single channel, then numChannels should be
specified as one. However, if each row contains RGB data
packed together as RGBRGBRGB..., numChannels should be
specified as three.

filterType

Specifies the type of filter to be used for resampling the
image during zooming.

197

Silicon Graphics Image File Format API

The filter types available are:
Filter Type

Category

IMPImpulse

Replicative

IMPBox

Filtered

IMPTriangle

Filtered

IMPQuadratic Filtered
IMPMitchell

Filtered

IMPGaussian

Filtered

Refer to “Filter Functions” on page 199 for detailed
information on the available filters.
blurFactor

Specifies a multiplier for the width of the filter. The default
blur factor is 1.0. Higher factors increase the amount of blur
present in the image.

The impZoomRow function has the following parameters:

198

zoom

Pointer to a zoom operator structure obtained from a call to
impCreateZoom.

buffer

Caller-allocated buffer that will be filled with the zoomed
image row data. The buffer should be allocated to
accommodated dstXSize * numChannels * sizeof(short) bytes.

row

The desired zoomed row. Rows are numbered from 0
through dstYSize minus 1. clientData is a pointer to client
data. This pointer is passed to the readRowFunc. A typical
use of this is for passing a pointer to a structure containing
the IMPImage pointer and the channel number.

Image Access Functions

Filter Functions

The resampling filters available for zooming are summarized below. Note
that the span of the filter (x range) is expressed in terms of the original image,
not the zoomed image. Table B-3 list the available filter functions.
Table B-3

Filter Functions

Filter Type

Function

IMPImpulse

Not Applicable

IMPBox

f(x) = 0.0

x < -0.5

f(x) = 1.0

-0.5 <= x < 0.5

f(x) = 0.0

x >= 0.5

f(x) = 0.0

x < -1.0

f(x) = 1.0+x

-1.0 <= x < 0.0

f(x) = 1.0-x

0.0 <= x < 1.0

f(x) = 0.0

x >= 1.0

f(x) = 0.0

x < -1.5

f(x) = 0.5*(x+1.5)^2

-1.5 <= x < -0.5

f(x) = 0.75-x^2

-0.5 <= x < 0.5

f(x) = 0.5*(x-1.5)^2

0.5 <= x < 1.5

f(x) = 0.0

x >= 1.5

IMPTriangle

IMPQuadratic

IMPMitchell

Span

b = 1.0/3.0
c = 1.0/3.0
p0 = (6.0-2.0*b)/6.0
p2 = (-18.0+12.0*b+6.0*c)/6.0
p3 = (12.0-9.0*b-6.0*c)/6.0
q0 = (8.0*b+24.0*c)/6.0
q1 = (-12.0*b-48.0*c)/6.0

199

Silicon Graphics Image File Format API

Table B-3 (continued)
Filter Type

Filter Functions
Function

Span

q2 = (6.0*b+30.0*c)/6.0
q3 = (-b-6.0*c)/6.0
f(x) = 0.0

x < -2.0

f(x) = q0-x*(q1-x*(q2-x*q3))

-2.0 <= x < -1.0

f(x) = p0+x*x*(p2-x*p3)

-1.0 <= x < 0.0

f(x) = p0+x*x*(p2+x*p3)

0.0 <= x < 1.0

f(x) = q0+x*(q1+x*(q2+x*q3)) 1.0 <= x < 2.0
f(x) = 0.0
IMPGaussian

x >= 2.0

a(x) = 1.0/exp((1.5*x)^2)
b(x) = 1.0/exp(1.5^4)
f(x) = a(x)-b(x)

Return Value:

The impCreateZoom function returns a pointer to a zoom operator structure if
execution was successful. NULL is returned and IMPerrno is set if an
execution error has occurred.
The impZoomRow function returns 0 if execution was successful. -1 is
returned and IMPerrno is set if an execution error occurred.
Execution Error Codes:

The impCreateZoom function fails under the following circumstances:
IMP_ERR_MEMALLOC

The impZoomRow function fails under the following circumstances:
IMP_ERR_READROW

200

Image Access Functions

Note: The storage for the IMPZoom structure is allocated by the zoom

operator creation function. This storage is deallocated by the
impDestroyZoom function. The caller should not explicitly reallocate or
deallocate any storage related to the image structure.
Note: The fields of the IMPZoom structure are private and should not be
modified by the caller.
See also:

libimp(3)

201

Appendix C

Printer Object Database (POD) File
Formats

This appendix describes the file formats
of the ASCII text files that comprise the
Printer Object Database. The default
contents of these files and the
interpretation is also described.

Appendix C

C.

Printer Object Database (POD) File Formats

This appendix describes the file formats of the ASCII text files that comprise
the printer object database (POD).
The major topics discussed are:
•

“General Syntax” on page 208

•

“Input Parsing Rules for libpod Files” on page 209

•

“Printer Configuration File Format” on page 210

•

“Printer Status File Format” on page 220

•

“Printer Log File Format” on page 224

205

Printer Object Database (POD) File Formats

Overview
The printer object database (POD) contains information on the current
configuration, status, and job history of a single printer. Each printer that is
physically installed on a system must maintain its own POD. To maintain
network-transparent, mediated access to the POD files, all interaction
between the printer driver and POD files must be through the libpod API. For
additional information, see “The libpod Library” in Chapter 6 and the
libpod(3) man pages.
The initial set of POD files created by the printer driver developer and
installed on the host server system must include:
•

.config—a configuration file representing the
capabilities of the printer

•

.status—a status file indicating a typical printing state

•

.log—an empty log file

The name of each POD file is formed from the printer name and the suffix
.config, .status, or .log, respectively. Note that the printer name must be the
same as the name of the printer model file. All POD files are copied from the
template POD files and installed in the appropriate directory.
The information contained in each POD file is summarized below and
explained in detail in subsequent sections.

Printer Configuration File
The printer configuration file (.config) contains detailed
information on the printer's capabilities. The file is created by the printer
driver developer to characterize the printer's capabilities. For example, the
possible paper sizes, printer location, and available fonts are all specified in
this file. Typically the information in the config file does not change over
time. Printer filters and drivers treat it as a read-only file. The printer install
tools may modify the file at printer installation time to enter site-specific
data, such as printer location, or note the presence of optional equipment,
such as a duplex option or an envelope feeder.

206

Overview

Printer Status File
The printer status file (.status) contains information about
the current operational status of the printer. The information in the file
indicates whether the printer is busy, what type of printing media is
installed, and so on. The contents of this file change during every print job.
The driver developer provides an initial copy of the status file, but it is the
job of the printer driver to update the file. Printer filter programs normally
treat this file as read-only.

Printer Log File
The printer log file (.log) contains the print job history for the
printer. Information for old jobs as well as the current print job is
maintained. Typically, printer filters and drivers append information to the
log file, while general applications treat the file as read-only.

207

Printer Object Database (POD) File Formats

General Syntax
Character Set
:
:
:
:
:
:
:
:
:

0x09, 0x20 (, )
0x00-0x08, 0x0B, 0x0C, 0x0E-0x1F, 0x7F-0xFF
0x0A, 0x0D (, )
0x7C ('|')
0x21-0x7B, 0x7D, 0x7E
0x30-0x39 ('0'-'9')
, 0x41-0x46, 0x61-0x66
('0'-'9', 'A'-'F', 'a'-'f')
0x2B, 0x2D ('+', '-')
0x2E ('.')

Field Format
:
:
:
:
:
:
:
:

:

208

 [...]
 [...]
 with a specific sequence of 
[]  [[ ]...]
[]
[]  [[ ]...]
[]
 [...]
["0x" | "0X"] [] 
[]  [ []]
or
[]  
 [[ ]...]

Input Parsing Rules for libpod Files

Input Parsing Rules for libpod Files
The following rules apply when a POD file is parsed by the libpod API.
1.

All  characters are ignored; their use is not recommended. This
provision is intended to avoid errors caused by nonprinting characters
appearing in the POD files.

2.

All input lines are truncated to PD_STR_MAX-1, not counting 
characters and , which are removed on input. The value of
PD_STR_MAX is defined in the header file /usr/include/pod.h.

3.

All occurrences of  sequences are reduced to a single 
character. Any  at the beginning or end of a field is removed.

4.

There are no quoted strings. Quotation marks are treated like any other
characters and cannot be used to force additional  into a field.

5.

All fields are checked for correct syntax based on entry type. Failure to
provide information in the correct format results in improper parsing.

6.

When scanning for  or  numbers within a field, all
characters that are not valid within an  or  are treated as
 (in the case of an ,  and  are treated as
). This allows characters to be inserted to improve readability.
For example, the following are equivalent if two  items are
expected:
300 300
300 x 300
300 by 300
300,300

7.

Entries containing no characters other than  prior to the first
 or  are treated as null entries and discarded
without error. These lines may be used as comments simply by placing
a  prior to any other information.

8.

Blank lines are ignored and may be inserted to improve readability.

9.

 matching is done in a case-independent manner.

10. Fields designed to be human-readable are not modified, except to
remove  and excess . Case and all 
sequences are preserved.

209

Printer Object Database (POD) File Formats

11. A  may require a long list of items (for example, Available
Fonts). To improve readability and avoid the risk of input line buffer
overflow (see 2 above), a  may be repeated.
For example, a list of fifty Available Fonts items may be broken into two
Available Fonts entries with 25 items each. The overall number of items
that can be specified in a list is limited only by available system
memory resources.
12. There is no required entry order. The  entries may appear in
any order within a POD file.
13. Default values are assumed for certain fields if values have not been
specified. The values of these defaults should not be relied upon and
may change in future releases.

Printer Configuration File Format
This section describes the format of the printer configuration file. The
configuration file is installed by the printer install tools with the name
.config.

General Format
The format for an entry in the configuration file is:
  [] 

where:

210



is one of the reserved fields described in the “Key Field”
column of Table C-1.



is the “separator” character defined in “Character Set” on
page 208.



is one or more of the options specified in the “Info Field
Type” column of Table C-1.



is one of the “endline” characters defined in “Character Set”
on page 208.

Printer Configuration File Format

Config File Options
All entries in the config file are optional. Entries that are not provided or that
have no  specified are assigned default values. However, since
printer capabilities differ, it is strongly recommended that no entries be
omitted. The defaults should not be relied on, as they may change in future
releases. Table C-1 lists the config file options in alphabetical order. A
detailed explanation of the options follows the table.
Table C-1

Config File Options

Key Field

Info Field Type

Default

Active Status Path



See “Active Status Path” on
page 212

Available Fonts



(0 elements)

Black Substitute



No

Color Adjustment



(0 elements)

Cost per Page



0.00

Default CA



0

Default IS

 [,gamma=]

0, gamma=-1.0

Default MT



0

Default QM



0

Driver Path



See “Driver Path” on
page 215

Error Retry Wait



10 seconds

Input Source



(0 elements)

Location Code



None

Manual Capable



No

Maximum Addr

 

See “Minimum Addr” on
page 216

Maximum Print Area  

See “Maximum Print Area”
on page 216

211

Printer Object Database (POD) File Formats

Table C-1 (continued)

Config File Options

Key Field

Info Field Type

Default

Media Standard



American

Media Type



(0 elements)

Media Wait



300 seconds

Minimum Addr

 

See “Minimum Print Area”
on page 216

Minimum Print Area  

See “Minimum Print Area”
on page 216

Number of Colors

 []

11

Physical Location



Unknown

Port Path



/dev/null

Printer Class



Dumb

Printer Model



Unknown

Printer Options



(empty string)

Quality Modes



(0 elements)

Resolution

 

300 dpi 300 dpi

Size Table Entry



See “Size Table Entry” on
page 218

Status Update Wait



300 seconds

Technology



Unknown

Time per Page

 []

00

Active Status Path

Active Status Path is the full pathname of the POD status file. The value of this
entry is not used by the libpod API. The value of this entry is always set by
the API to PDpod_path/.status. Refer to the libpod(3) man page
for additional information.

212

Printer Configuration File Format

Available Fonts

The Available Fonts option contains a list of font names representing the fonts
available on the printer. For printers with built-in PostScript interpreters,
this list should include only those fonts built into the printer (typically a set
of 35 standard fonts). The default value is 0 elements.
For raster printers, the PostScript interpretation is performed on the printer
host machine. Thus, the fonts listed for these printers should correspond to
the names of the font outline files installed on the printer host. There are two
methods for specifying the font names: the names can be listed individually
or a full path to the directory where the outline fonts are stored can be
specified. The two methods can be mixed. When a path is specified, the
names of the files in that directory are assumed to be the names of the fonts.
To exclude filenames from the directory, specify the names of the files to be
excluded with a leading “!”. The filenames to be excluded must appear on
the same line as the directory containing the filename to be excluded. The
following is a valid Available Fonts list:
NewYearRoman | /usr/lib/DPS/outline/base | !fonts.dir

This entry indicates that the fonts available on the printer are
NewYearRoman, and all filenames are in the directory
/usr/lib/DPS/outline/base with the exception of fonts.dir. Note that font names
must not contain any white space.
Black Substitute

The Black Substitute option is either yes, indicating that the printer should by
default substitute true black for composite black, or no, indicating that it
should not. The default value is no.
Color Adjustment

The Color Adjustment option is a list of color adjustment methods available
for the printer. The color adjustment methods perform color correction
between the current input source and the printer. An example entry is:
None | Fix Blue | Gamma Correct

The default value is 0 elements.

213

Printer Object Database (POD) File Formats

Cost per Page

The Cost per Page option is the cost per printed page in local currency. For
example, 0.50 for 50 cents per page. The default value is 0.00.
Default CA

The Default CA option is the index to the Color Adjustment list indicating the
default adjustment method. This index is based at one rather than zero.
Thus, the first method in the list is at position 1, the second at 2, and so on.
If there are no adjustment methods specified, this entry should either be left
empty or set to 0. The default value is 0.
Default IS

Default IS is the index to the Input Source list indicating the default input
source. This index is based at one rather than zero. Thus, the first source in
the list is at position 1, the second at 2, and so on. If there are no input sources
specified, this entry should either be left empty or set to 0.
When used for printer color correction, this entry can also be used to specify
the default device's gamma correction value. The gamma value is specified
after the default input source index as in the following example:
1, gamma = 1.0

Default MT

Default MT is the index to the Media Type list indicating the default media.
This index is based at one rather than zero. Thus, the first media in the list is
at position 1, the second at 2, and so on. If there are no media types listed,
this entry should either be left empty or set to 0. The default value is 0.
Default QM

Default QM is the index to the Quality Modes list indicating the default
quality mode. This index is based at one rather than zero. Thus, the first
quality mode in the list is at position 1, the second at 2, and so on. If there are
no quality modes specified, this entry should either be left empty or set to 0.
The default value is 0.

214

Printer Configuration File Format

Driver Path

Driver Path is the full pathname of the installed printer driver. The default is
the full pathname of the POD config file with the suffix .config removed.
Error Retry Wait

Error Retry Wait refers to the number of seconds to wait after an error has
occurred before attempting to resume printing. The default is 10 seconds.
Input Source

Input Source is a list of printer input sources. The primary use of this entry is
to list the image source devices that have been characterized for printer color
correction. A common input device is the monitor. An example entry is Sony
16” Monitor.
Location Code

The Location Code option is used to supply a site-specific keyword that
identifies the printer’s physical location. For example, 3U-924. There is no
default value. This code should be machine-readable and -sortable for use by
a location-querying browser.
Manual Capable

Manual Capable is either yes, indicating that the printer is capable of being
manually fed, or no, indicating that it is not. The default value is no. This
value should be set to yes only if the printer supports the -m option (see
“Filter/Driver Specification” in Chapter 3).
Maximum Addr

Maximum Addr is the maximum printable area dimensions expressed in
dots. The default values for this entry assume an A-size page (8.5 by 11.0
inches) in portrait orientation with 0.5-inch margins. At 300 dpi, this gives a
printable area of 2250 by 3000 dots. The minimum and maximum values are
identical in the default case. If a Page Size Table has been specified, the values
for this entry are derived from it. Also see “Minimum Addr.”

215

Printer Object Database (POD) File Formats

Maximum Print Area

Maximum Print Area is the maximum printable area dimensions expressed in
inches. The default values for this entry assume an A-size page (8.5 by 11.0
inches) in portrait orientation with 0.5-inch margins. This gives a printable
area of 7.5 by 10.0 inches. The minimum and maximum values are identical
in the default case. If a Page Size Table has been specified, the values for this
entry are derived from it. Also see “Minimum Print Area.”
Media Standard

The Media Standard keyword indicates the paper measurement standard.
Keywords are American and Metric. The default value is American.
Media Type

Media Type is a list of the output media types supported by the printer.
Typical items are Bond Paper and Transparency Film. The default is 0
elements.
Media Wait

Media Wait is the number of seconds to wait for manual feed or print media
changes before the default media source is used. The default is 300 seconds.
Minimum Addr

Minimum Addr is the minimum printable area dimensions expressed in dots.
The default values for this entry assumes an A-size page (8.5 by 11.0 inches)
in portrait orientation with 0.5-inch margins. At 300 dpi, this gives a
printable area of 2250 by 3000 dots. The minimum and maximum values are
identical in the default case. If a Page Size Table has been specified, the values
for this entry are derived from it. Also see “Maximum Addr.”
Minimum Print Area

Minimum Print Area is the minimum printable area dimensions expressed in
inches. The default values for this entry assume an A-size page (8.5 by 11.0
inches) in portrait orientation with 0.5-inch margins. This gives a printable
area of 7.5 by 10.0 inches. The minimum and maximum values are identical

216

Printer Configuration File Format

in the default case. If a Page Size Table has been specified, the values for this
entry are derived from it. Also see “Maximum Print Area.”
Number of Colors

Number of Colors is the minimum or, optionally, maximum number of colors
that are available on the printer. If the maximum number of colors is not
provided, it is assumed to be the same as the minimum. A monochrome
printer or printer ribbon provides one color. A CMY printer or ribbon
provides three colors.
Note that this field should contain only the number of colors available on the
printer. The colorspace, depth, and data format are provided in the Number of
Colors entry in the status file. The default value is 1.
Physical Location

Physical Location is the human-readable description of the printer's physical
location. For example, Bldg. 3 Upper, Room 924. The default value is
Unknown.
Port Path

Port Path is the full pathname of the I/O port to which the printer is
physically connected. For example, /dev/plp for a parallel printer, /dev/ttyd2
for a serial printer, and /dev/scsi/sc0d6l0 for a SCSI printer. The default value
is /dev/null.
Printer Class

The Printer Class entry is used to specify the class of printer being used.
Available values are Dumb, Raster, ColorRaster, MonoPostScript,
ColorPostScript, and Plotter. The following printer classes are obsolete and
should not be used for new development: DumbColor, PostScript, and
Color. The default value is Dumb.

217

Printer Object Database (POD) File Formats

Printer Model

The Printer Model entry is a keyword that is the manufacturer's description
of the printer. For example, Tektronix Phaser II SX or Apple LaserWriter II
NTX. The default value is Unknown.
Printer Options

Printer Options describe the standard installed printer optional equipment.
For example, 8 megabytes RAM. The default is an empty string.
Quality Modes

Quality Modes is a list of output quality modes available on the printer. For
example, draft and letter. The default value is 0 elements.
Resolution

Resolution is the horizontal or vertical printer resolution in dots per inch
(dpi). For printers that allow multiple resolutions, the status file Printer
Options entry should be parsed for the CurrentRes keyword. This keyword
indicates the current printer resolution. If the keyword is not found, the
config file Resolution entry should be used. The default values are both 300
dots per inch.
Size Table Entry

The Size Table Entry  has the format  defined as:
:      
 [ []]

Size Table Entry describes a particular media size that is supported by the
printer. Typically, there is one Size Table Entry per supported media size (for
example., an entry each for A size and B size), although it is ok to have
multiple entries for a particular paper size if multiple resolutions or ribbons
are supported. The media size entry has seven required fields and two
optional fields. All fields are separated by white space.

218

Printer Configuration File Format

The first required field contains the “media size” keyword (for example, A).
The list of possible media sizes can be found in the file /usr/include/pod.h. The
media size keyword is simply the media size listed in pod.h with the
PD_SIZE_ prefix removed. The size names listed in pod.h with the suffix
_LAND indicate landscape orientation and should not be used as media size
keywords. Media with landscape orientation is indicated by the width and
height fields of the size table entry.
The next two fields are the media-imageable width and height expressed in
dots. Typically, the imageable dimensions are derived by subtracting the
margins from the total media size and converting the result to dots.
The next two fields are the overall media width and height expressed in
inches.
The last two required fields are the left and top margins expressed in inches.
The first optional field specifies the printing raster direction. Refer to pod.h
for the values that may be specified in this field.
The second optional field is the media validation mask. This mask can be
used to differentiate among media entries that have the same media name
but differ in other respects (for example, resolution). The field is a bit mask
and so, to fully differentiate among similar entries, the values must be
powers of two. Refer to the PDReadInfo(3) man page for more information on
the use of this field.
A default Size Table Entry is always added to the end of the table when it is
read by libpod. This default entry is:
A 2250 3000 8.500 11.000 0.500 0.500 0x00 0xFF

Status Update Wait

Status Update Wait is the number of seconds to wait between updates of the
POD status file when no error has occurred. The default is 300 seconds.

219

Printer Object Database (POD) File Formats

Technology

The Technology option indicates the type of printing technology used in the
printer. For example, ink jet, wax transfer, dye sublimation, and color laser.
The default value is Unknown.
Time per Page

Time per Page is the average and, optionally, maximum time to print a page,
in seconds. If the maximum time is not provided, it is assumed to be the
same as the average time. The default values are both 0.

Printer Status File Format
This section describes the format of the printer status file. The status file is
installed by the printer install tools with the name .status.

General Format
The format for an entry in the printer status file is:
  [] 
where:



This parameter is specified by Table C-2.



The separator defined in “Character Set” on page 208.



One of the endline characters defined in “Character Set” on
page 208.

Printer Status File Entries
All entries in the status file are optional. Entries that are not provided or that
have no  are assigned default values. However, since the status
file is the only means to indicate printer status to the user, it is strongly
suggested that a complete status file be provided by the developer and that
the printer driver update the status file to reflect the printer's current status.

220

Printer Status File Format

Table C-2 lists the printer status file entries.
Table C-2

Printer Status File Entries

Key Field

Info Field Type

Default

Operational Status



Idle

Media Size

 [Land]

A

Media Type



Paper

Number of Colors



1 k 1 chunky

Printer Options



(empty string)

Validation Mask



0

Error



(no message)

Warning



(no message)

Information



(no message)

Operational Status

Operational Status is the keyword specifying the current operational status of
the printer. The possible values are Idle, Busy, Faulted, and Unavailable.
The status Faulted indicates that there is a problem with the printer but not
with communication to the printer. The Unavailable designation is similar
to the Faulted state but indicates that communication could not be
established with the printer. The default value is Idle.
Media Size

Media Size is the keyword indicating the currently loaded media size. The
media size keywords are listed in the file pod.h. The keyword is the size name
listed with the PD_SIZE_ prefix removed. The size names listed in pod.h with
the suffix _LAND indicate landscape orientation and are specified in the
entry by the keyword Land.

221

Printer Object Database (POD) File Formats

Media Type

Media Type is the keyword indicating the currently loaded media type. The
value is Paper, Transparency, Other, or Unknown. The default is Paper.
Number of Colors

This field specifies not only the number of output colors but the colorspace,
depth, and organization of the output data. There is one required field and
three optional fields. For proper operation of printing filters, it is strongly
recommended that the optional fields be specified.
The Number of Colors  has the format  defined as:
 [  ]
Arguments:



is required and specifies the number of output colors the
printer can currently print. If only this field is present, the
following defaults apply:
# of colors

colorspace

depth

organization

1

k

1

chunky

3

cmy

1

chunky

4

cmyk

1

chunky



is optional. This field specifies the output colorspace and is
either k, rgb, cmy, ymc, cmyk, ymck, w, or kcmy.



is optional. This field specifies the number of bits per color
component and may be 1, 4, or 8.



is optional. This field specifies the data organization of the
output data and is either chunky or planar.

An example output specification is:
3 rgb 4 planar

This specifies a three-color RGB output with four bits per component (12 bits
total) and a planar data organization. Refer to the libstiff(3) man page for
additional information on raster data output formats.

222

Printer Status File Format

Printer Options

This field is used to describe the currently available optional equipment or
configurations. The field is also used to indicate the current printer
resolution for printers that allow multiple output resolutions. To indicate the
current resolution, the string:
CurrentRes =  x 

is specified. The first integer is the horizontal resolution in dots per inch, and
the second integer is the vertical resolution in the same units. The current
resolution values are used by printing filters such as the PostScript
interpreter psrip to calculate margins for printers whose resolutions can
change, and it is very important that printer drivers update this information
field to ensure proper rendering.
Validation Mask

This field can be used to differentiate among media entries that have the
same media name but differ in other respects (for example, resolution). The
field is a bit mask and so, to fully differentiate among similar entries, the
values must be powers of two. Refer to the PDReadStatus(3) man page for
more information on the use of this field.
Error, Warning, and Information Options

Each Error, Warning, and Information message  has the format
 defined as:
 [ []]  

These three entries indicate messages written by the printer driver to
provide information to the printer user regarding the state of the printer. The
three hex bytes provide a message code. The available message codes are
listed in pod.h (PD_ERROR_*). The low-order three bytes of the codes listed
in pod.h are the codes specified in this field. The high-order byte of the code
is implied by the first field (for example., Information = 00, Warning == 01,
Error = 02). The last field is a string providing the text for the message. There
can be up to PD_MESSAGE_MAX (see pod.h) message entries in a status file.
An example of a complete message entry is:
Information | 01 00 00 | version: driver = 00.00

223

Printer Object Database (POD) File Formats

See the PDMakeMessage routine for the best method of construction these
messages. For the sake of internationalization, it is strongly recommended
that you do not customize messages.

Printer Log File Format
The log file is not currently implemented. Developers should supply an
empty file in /usr/spool/lp/pod with the name .log, and
should not write to the log file.

224

Appendix D

Transition Notes

This appendix explains how Impressario
application developers and filter/driver
developers can take advantage of the new
features in Impressario 1.2, and how to
migrate from Impressario 1.0 or 1.1 to
Impressario 1.2.

Appendix D

D.

Transition Notes

This appendix explains how Impressario application developers and
filter/driver developers can take advantage of the new features in
Impressario 1.2.
The major topics discussed are:
•

“Impressario 1.1 to 1.2” on page 228

•

“Notes for Application Developers” on page 228

•

“Notes for Filter/Driver Developers” on page 228

•

“Impressario 1.0 to 1.2” on page 229

•

“Notes for Application Developers” on page 229

•

“Notes for Filter/Driver Developers” on page 229

•

“General Changes from IRIX 4 to IRIX 5” on page 231

227

Transition Notes

Impressario 1.1 to 1.2
Notes for Application Developers
The major changes in Impressario 1.2 for application developers are:
•

The PrintBox widget now allows printer-specific options panels to be
launched.

•

The new libimp library greatly eases the reading and writing of Silicon
Graphics Image files to any format, in both 8- and 16-bit per channel
formats.

Notes for Filter/Driver Developers
The major changes in Impressario 1.2 for filter/driver developers are:

228

•

The chunky data format is obsolete. Convert your drivers to use STIFF
format.

•

16-bit per channel color and grayscale is now accepted by libimp and
libstiff.

•

SCSI printer drivers should no longer be installed as setuid programs.
The Silicon Graphics printer installer tools reconfigure the device port
to be accessible to lp.

•

Graphical options panels now must be installed in the directory
/var/spool/lp/gui_model/ELF and require their own application resource
file. See chapter 6 for detailed information on the creation and
installation of graphical options panels.

Impressario 1.0 to 1.2

Impressario 1.0 to 1.2
Notes for Application Developers
Developers incorporating printing in their application will find Impressario
1.2 backward-compatible with Impressario 1.0.
The libspool library has expanded support for printer and spooler options
handling. The libpod library now has a function to write the config file as well
as a number of new convenience functions to work with page sizes and
printer resolutions. See the libspool(3) and libpod(3) man pages for details on
these libraries.

Notes for Filter/Driver Developers
The major changes in Impressario 1.2 concern printing filter and driver
development.
PostScript Interpreter Changes

In Impressario 1.2, the host-based PostScript interpreter is now called psrip.
The psrip program obsoletes the Impressario 1.0 interpreter called pschunky.
A shell script called pschunky is provided in Impressario 1.2 for backward
compatibility. This script simply provides a pschunky-compatible front end
to the psrip program.
The psrip program provides expanded output format support. Using psrip, it
is now possible to RIP to the k, w, rgb, cmy, cmyk, ymc, ymck, and kcmy
colorspaces. The raster image may be output in 1-, 4-, or 8-bits per color
component and in either planar or packed format.
The primary output image file format for psrip is Stream TIFF (STIFF). STIFF
is a streamable subset of TIFF (Tag Image File Format). STIFF output
obsoletes the Impressario 1.0 CHUNKY format. For backward compatibility,
psrip can also output Impressario 1.0-compatible CHUNKY format by
specifying colorspaces oldk, oldcmy, and oldcmyk, but this functionality will
soon go away, so you must upgrade your drivers now to use STIFF.

229

Transition Notes

New Interchange File Format

As indicated above, the primary interchange file format between printer
filters and drivers has been changed in Impressario 1.0 from the proprietary
CHUNKY format to STIFF. STIFF is a fully compatible subset of TIFF 6.0 and
therefore has many advantages over CHUNKY format. One such advantage
is the ability to export TIFF-compatible raster files to TIFF 6.0 applications.
All printer driver and filter development must use the STIFF file format
using the libstiff API.
Silicon Graphics Image to PostScript Filter Changes

The rgb2ps filter has been obsoleted by the sgi2ps program. Both programs
take Silicon Graphics image files as input and produce PostScript output.
However, sgi2ps provides expanded output capabilities. The sgi2ps program
can output black and white (w), rgb, and cmyk PostScript in both ASCII and
binary formats. The binary output format is especially efficient when the
output of sgi2ps is piped directly to the psrip interpreter. In addition, sgi2ps
provides multi-image-per-page n-up capability.
Due to performance increases in both the Silicon Graphics Image to
PostScript file generation and the PostScript interpreter, there is no longer a
need for a filter to convert directly from Silicon Graphics image file format
to STIFF format. Conversion from Silicon Graphics image file format to
STIFF raster image format is accomplished by piping the output of sgi2ps to
the psrip interpreter using binary PostScript as the intermediate file format.
The tochunky filter is now obsolete.
New Model File Architecture

The printer model file architecture has changed for Impressario 1.1. The
Impressario 1.1 printer model files now use the programs wstype and
fileconvert to perform file typing and conversion, respectively. The programs
obsolete the use of the file command and the hard-coded filter chains found
in the Impressario 1.0 model files. Use of these programs greatly expands the
number of file types that can be printed and simplifies the model file logic.

230

Impressario 1.0 to 1.2

POD Files Enhanced

In Impressario 1.1, the POD file format has been fully documented (see
pod(4)). In addition, a number of enhancements to the POD files now allow
a wide range of printers to be fully characterized. Specific enhancements
include the ability to specify the colorspace, image format, and image depth
for the printer and the ability to handle printers that can switch resolutions
on the fly. Available fonts can now be searched for in the filesystem instead
of being hard-coded in the config file.

General Changes from IRIX 4 to IRIX 5
Compatibility Issues for Device Developers

IRIX 5 introduces support for multiple parallel ports and up to 72 serial
ports, and provides a number of new options to device developers using
SCSI. We recommend you get a copy of the IRIX Device Driver Programming
Guide if you use SCSI at all.
IRIX 5 ELF versus IRIX 4 COFF-format Options Panel

IRIX 5 uses a new, more flexible compiled format called ELF. You cannot link
ELF and COFF object files together, so you must recompile all sources on an
IRIX 5 machine. If you wish to relink your applications, you may still ship
COFF format options panels and they will continue to work.

231

Appendix E

Scanner Driver Architecture

This appendix discusses scanner driver
architecture. It provides a detailed
analysis and discussion of the template
scanner driver.

Appendix E

E.

Scanner Driver Architecture

This appendix discusses scanner driver architecture. It provides a detailed
analysis and discussion of the template scanner driver.
The following major topics are discussed:
•

“Overview” on page 236

•

“Driver Structure” on page 236

•

“Type Conversion Macros” on page 244

•

“Scanner Functions” on page 238

•

“Queues and Multi-Threaded Scanner Drivers” on page 247

235

Scanner Driver Architecture

Overview
Scanner drivers are programs that are executed by applications that link
with libscan.a and call SCOpen(3). They accept commands from the
application via an input pipe and return results via an output pipe.
All scanner drivers must implement the basic set of commands so that any
application using the libscan interface can have access to the functionality
offered by the scanner. Many library routines are provided for scanner
driver developers to implement functionality in software that may not be
implemented in hardware for some scanners. The support routines for
writing scanner drivers can be found in libscan.a.

Driver Structure
A scanner driver consists of a number of functions that implement the set of
commands required to drive the scanner. In the main routine, a table of these
functions, with the position of each function in the table corresponding to its
SCN #define in scanipc.h, is passed to SCDriverSetCallbacks(), then
SCDriverMainLoop() is called.
SCDriverMainLoop waits for input from the application and calls the function
in the table corresponding to each command received. Each function has the
following prototype:
void scanfunc(int cmd, SCARG *arg, SCRES *res)
Arguments:

cmd

contains the SCN #define of the command to be executed.

arg

is the argument to this scanning function. SCARG is defined
in scandrv.h as follows:
typedef struct tag_scarg {
void *data;
int len;
} SCARG;

arg->data points to the arguments transferred from the
application; the meaning of arg->data depends upon the
cmd (see below).

236

Driver Structure

arg->len encodes the byte length of arg->data.
res

is the result of this scanning function. SCRES is defined in
scandrv.h as follows:
typedef struct tag_scres {
void *data;
int len;
void *freeparam;
void (*free)(void *param, void *data);
int errno;
char *errmsg;
} SCRES;

res->data should be set to point to the data to be returned to
the application as a result of cmd.
res->len is the byte length of res->data.
res->free is a pointer to a function that is called if it is
nonzero after res->data has been transferred to the
application. The function is called with res->freeparam as its
first argument and res->data as its second argument.
res->errno should be set to one of the SCE #defines in
/usr/include/scanner.h or one of the errno values from
/usr/include/sys/errno.h if an error occurs during the
execution of cmd. If res->errno is nonzero, the libscan
function being executed on the application side returns an
error status, and SCerrno is set to the value of res->errno.
res->errmsg is the error message pointer. If res->errno is set
to SCEDRVMSG, then res->errmsg should point to a
driver-specific error message.
Before a scanning function is called, the entire res structure is zeroed.
Scanning functions are allowed to assume that any member of the res
structure not explicitly set remains set to 0.

237

Scanner Driver Architecture

Scanner Functions
Required Scanner Functions
All scanner drivers must implement the functions listed in Table E-1.
Table E-1

238

Scanner Driver Functions

Function

Description

SCN_INITOK

Checks for successful scanner driver initialization

SCN_PAGESIZE

Returns the size of the scan area that is supported by
the scanner

SCN_MINMAXRES

Returns the smallest and largest horizontal and
vertical resolution

SCN_NRES

Returns the number of resolution pairs supported in
hardware

SCN_RES

Returns floating-point numbers representing the
supported hardware resolutions

SCN_NTYPES

Returns the number of data types supported by the
driver

SCN_TYPES

Returns an array of SCDATATYPE objects, one for
each of the types supported by the driver

SCN_FEEDERGETFLAGS

Gets the document feeder flags

SCN_FEEDERSETFLAGS

Sets the document feeder flags

SCN_FEEDERREADY

Determines if the feeder is ready to be advanced

SCN_FEEDERADVANCE

Advances the feeder to the next document

SCN_SETUP

Sets the scanning parameters

SCN_GETSIZE

Returns scan line width (in bytes and pixels) and the
number of scan lines

SCN_SCAN

Tells the scanner driver to start scanning

Scanner Functions

Table E-1 (continued)

Scanner Driver Functions

Function

Description

SCN_ABORT

Stops the scan and releases temporarily allocated
resources

SCN_DIE

Cleans up and calls exit()

SCN_INITOK Function
arg->data: NULL
res->data: NULL

This function exists as a mechanism for the application to determine
whether the scanner driver managed to initialize itself and the scanner
properly. If any problem occurred during initialization, res->errno should be
set to one of the SCE #defines in scanner.h; otherwise, no action is necessary.
SCN_PAGESIZE Function
arg->data: int * (Metric)
res->data: SCWINDOW *
typedef struct tag_scwindow {
float x, y, width, height;
} SCWINDOW;

This function returns the size of the scannable area supported by the scanner.
Fill res->data in with the x, y, width, and height of the scannable area in inches
or centimeters, depending on whether arg->data is SC_INCHES or
SC_CENTIM.
SCN_MINMAXRES Function
arg->data: NULL
res->data: SCMINMAXRES *
typedef struct tag_scminmaxres {
float minx, miny, maxx, maxy;
} SCMINMAXRES;

This function sets the smallest and largest horizontal and vertical
resolutions. res->data->minx should be set to the smallest horizontal
resolution supported in hardware by the scanner, res->data->miny the

239

Scanner Driver Architecture

smallest vertical resolution, res->data->maxx the largest horizontal
resolution, and res->data->maxy the largest vertical resolution.
SCN_NRES Function
arg->data: NULL
res->data: int *

This function sets the number of resolution pairs supported in hardware.
*res->data should be set to the number of (xres, yres) resolution pairs
supported in hardware by the scanner.
SCN_RES Function
arg->data: int *
res->data: float *

This function sets floating-point numbers representing supported hardware
resolutions. arg->data points to the metric of the resolution; either
SC_INCHES for pixels/inch or SC_CENTIM for pixels/centimeter.
res->data should be set to point to a floating-point array that represent
supported hardware resolutions. There should be an even number of
resolutions, with all of the horizontal resolutions first, then all of the vertical
resolutions.
Note: All scanner drivers must support arbitrary resolutions; software

routines are provided to perform zoom operations. The above information is
provided so that scanner application developers can retrieve pure data from
the scanner and perform their own zooming (with filters; libscan zooming
does no filtering) to achieve the desired resolution.
SCN_NTYPES Function
arg->data: NULL
res->data: int *

This function sets the number of data types supported by the driver.
*res->data should be set to the number of data types supported by this
scanner driver.

240

Scanner Functions

SCN_TYPES Function
arg->data: NULL
res->data: SCDATATYPE *
typedef struct tag_scdatatype {
unsigned int packing : 4;
unsigned int channels : 4;
unsigned int type : 8;
unsigned int bpp : 8;
} SCDATATYPE;

The res->data of the SCN_TYPES function points to an array of
SCDATATYPE objects, one for each of the types supported by the scanner
driver.
All scanner drivers must support monochrome data; that is, the type
{SC_PACKPIX, 1, SC_MONO, 1}. All scanner drivers that support any kind
of greyscale or color output must support the type { SC_PACKPIX, 1,
SC_GREY, 8 }; that is, 8-bit greyscale. All scanner drivers that support any
kind of color output must support either { SC_PACKPIX, 3, SC_RGB, 8 }
(24-bit CHUNKY color data) or { SC_PACKPLANE, 3, SC_RGB, 8 } (24-bit
planar color data).
Library routines in libscan.a exist to facilitate compliance with these
conventions.
SCN_FEEDERGETFLAGS Function
arg->data: NULL
res->data: SCFEEDERFLAGS *
typedef unsigned int SCFEEDERFLAGS;

This function returns the feeder flags for this scanner to the application. See
“Header Files” in Chapter 7.
SCN_FEEDERSETFLAGS Function
arg->data: SCFEEDERFLAGS *
res->data: NULL

This function sets the feeder flags.

241

Scanner Driver Architecture

SCN_FEEDERREADY Function
arg->data: NULL
res->data: NULL

This function determines whether or not the feeder is ready for an advance
command.
SCN_FEEDERADVANCE Function
arg->data: NULL
res->data: NULL

This function causes the feeder to advance to the next document.
SCN_SETUP Function
arg->data: SCSETUP *
res->data: NULL
typedef struct tag_scsetup {
int preview;
SCDATATYPE type;
int rmetric;
float xres, yres;
int wmetric;
float x, y, width, height;
} SCSETUP;

The SCN_SETUP function sets the scanning parameters. The upper-left x
and y coordinates, the width, and the height are specified in either pixels,
inches, or centimeters, depending on whether arg->data->wmetric is
SC_PIXELS, SC_INCHES, or SC_CENTIM.
Set the scanning horizontal and vertical resolutions, in pixels per inch or
pixels per centimeter, depending on the value of arg->data->rmetric. Set the
data type for scanning. If this is a preview, arg->data->preview will have a
nonzero value.
Note: If a resolution or combination of resolutions not supported in

hardware is specified, the driver MUST zoom the image in order to supply
the requested resolution. Library routines to aid zooming are available in
libscan.a.

242

Scanner Functions

SCN_GETSIZE Function
arg->data: NULL
res->data: SCSIZE *
typedef struct tag_scsize {
long xbytes, xpixels, ysize;
} SCSIZE;

This function returns, to the scanning application, the width of a scan line in
bytes and pixels, and the number of scan lines in the scan. This is called after
SCN_SETUP so the application will know exactly how much data to expect.
SCN_SCAN Function
arg->data: NULL
res->data: NULL

This function tells the scanner driver to initiate scanning.
SCN_ABORT Function
arg->data: NULL
res->data: NULL

This function stops the scan and releases any resources temporarily
allocated. The application has decided to stop retrieving data before
scanning has been completed. The driver should physically stop the scan
and release any resources that were temporarily allocated for the scan.
SCN_DIE Function
arg->data: NULL
res->data: NULL

This function cleans up and calls exit(2). The application has demanded that
the driver terminate. This function should not return; it should perform any
necessary cleanup and then call exit(2).

243

Scanner Driver Architecture

Type Conversion Macros
The macros listed in Table E-2 are provided to convert between data types.
Table E-2

Type Conversion Macros

Macro

Description

GRIDTOFLOAT

Convert from grid format to floating-point format

FLOATTOGRID

Convert from floating-point format to grid format

GRIDTOFLOAT(int pos, int n)
FLOATTOGRID(float pos, int n)

These macros determine which destination pixel or line the pos'th source
pixel or line corresponds to. For example, if we are scanning at 120 dpi, but
the application has requested 100 dpi, and our scan height is 1 inch, we need
to skip 20 scan lines to provide the desired resolution. The following loop
obtains scan lines from the scanner and passes them on to the application:
float fy;
int imgy, scany;
while (imgy < 100) {
fy = GRIDTOFLOAT(imgy, 100);
scany = FLOATTOGRID(fy, 120);
...
/* Get the scany'th scan line from the scanner */
/* Do conversion and horizontal zooming */
/* Call SCDriverPutRow */
imgy++;
}

Zooming and Type Conversion Functions
The functions listed in Table E-3 are provided to support zooming and
converting between data types.

244

Scanner Functions

All conversion routines simultaneously zoom, so that only one conversion
per line should ever be necessary.
Table E-3

Zooming and Type Conversion Functions

Function

Description

SCCreateZoomMap

Creates a zoom map

SCDestroyZoomMap

Frees memory allocated to store a zoom map

SCZoomRow1

Zooms a row of 1-bit pixels

SCZoomRow8

Zooms a row of 8-bit pixels

SCZoomRow24

Zooms a row of 24-bit pixels

SCZoomRow32

Zooms a row of 32-bit pixels

SCBandRGB8ToPixelRGB8

Converts a row of pixels, in three rows (R, G, and B)
of 8-bit components per pixel, to a row of 24-bit pixels

SCGrey8ToMono

Converts a row of pixels from 8-bit greyscale to
monochrome

SCCreateZoomMap Function
int *SCCreateZoomMap(int anx, int bnx);

This function creates a zoom map. When zooming in the horizontal
direction, it is wasteful to use GRIDTOFLOAT and FLOATTOGRID for every
pixel of every line, since the same calculations would be repeated many
times. A zoom map is an array of bnx integers, each of which is the pixel
between 0 and anx - 1 that should be used when zooming a row of anx pixels
to a row of bnx pixels. The zooming and conversion functions all take zoom
maps for efficient zooming; for conversion functions where no zooming is to
occur, the zmap parameter can be NULL.
SCDestroyZoomMap Function
void SCDestroyZoomMap(int *zmap);

This function frees memory allocated to store a zoom map.

245

Scanner Driver Architecture

SCZoomRow1 Function
void SCZoomRow1(char *abuf, int anx, char *bbuf, int bnx, int *zmap);

This function zooms a row of anx pixels to a row of bnx pixels, 1 bit per pixel.
SCZoomRow8 Function
void SCZoomRow8(char *abuf, int anx, char *bbuf, int bnx, int *zmap);

This function zooms a row of anx pixels to a row of bnx pixels, 8 bits per pixel.
SCZoomRow24 Function
void SCZoomRow24(void *abuf, int anx, void *bbuf, int bnx, int *zmap);

This function zooms a row of anx pixels to a row of bnx pixels, 24 bits per
pixel.
SCZoomRow32 Function
void SCZoomRow32(void *abuf, int anx, void *bbuf, int bnx, int *zmap);

This function zooms a row of anx pixels to a row of bnx pixels, 32 bits per
pixel.
SCBandRGB8ToPixelRGB8 Function
void SCBandRGB8ToPixelRGB8(void *frombuf, int fromx,
void *tobuf, int tox, int *zmap);

This function converts a row of fromx pixels, laid out in three rows (R, G, and
B) of 8-bit components per pixel, to a row of tox pixels, 24 bits per pixel.
SCGrey8ToMono Function
void SCGrey8ToMono(unsigned char thresh, void *frombuf,
int fromx, void *tobuf, int tox, int *zmap);

This function converts a row of pixels from 8-bit greyscale to monochrome,
thresholding each pixel with thresh.

246

Queues and Multi-Threaded Scanner Drivers

Queues and Multi-Threaded Scanner Drivers
To achieve optimal performance in a scanner driver, it is helpful to
parallelize the operations being performed. A pipeline carries data from the
scanner to the ultimate destination, often a file. One can imagine that at the
beginning of the pipeline, most of the time is spent waiting for I/O to
complete. An intermediate image processing stage is CPU-bound as it
zooms and converts rows of data. The final stage, writing to a file, is again
I/O-bound.
Rather than adding these times together, we notice that all three stages of the
pipeline can occur at the same time; that is, while the scanning stage is
waiting for I/O, the file-writing stage can also be waiting for I/O, and the
image-processing stage can be using the CPU. As you can imagine,
performance gets even better on multiprocessor systems.
To support this, a multi-threaded queue interface is included in libscan.a.
Each queue is semaphored so that the read thread can be different from the
write thread, and so that the dequeue operation on an empty queue blocks
until another thread has enqueued something.
In the driver template, separate threads implement the scanning stage and
the image-processing stage. The main thread of the driver simply starts the
two processes and waits for more commands from the application.
The driver template uses two queues: one to hold free buffers and one to
hold freshly scanned lines. The amount of concurrency is metered by the
initial size of the free queue; the scanning thread blocks when there are no
more free buffers if it gets too far ahead of the image-processing thread.
The scanning thread dequeues a buffer from the scan free queue, gets data
from the scanner, and stores it in the buffer. Then it breaks the buffer up into
scan lines, enqueueing each line on the scan queue (it is typically faster to
scan chunks of lines rather than one line at a time).
The image-processing thread dequeues a buffer from the scan queue. It then
zooms and converts it, and writes the result to a stream that the application
is reading to obtain the data. It puts the original buffer back on the scan free
queue (actually, since the scanning thread breaks its buffer up into scan
line-sized chunks, the image-processing thread has to know how to put the
chunks back together).

247

Scanner Driver Architecture

Figure E-1 illustrates the scanning process.

Scanner
Application

Convert Process
writes cooked data
to the file descriptor
passed by the
application

Convert Process converts
from the scanner-specific
data formats to standard
formats and, if necessary,
performs simple zooming
Convert
Process
Convert Process gets
raw data buffers
from the head of
Scan Queue

Convert Process adds
written buffers back
to the tail of
Free Queue

Scan
commands
and results

Parent
Process

Free
Queue

Scan
Queue

Scan Process
adds the buffered
scanned data to the
tail of Scan Queue

Scan Process
gets the empty
buffers from the
head of Free Queue
Scan
Process
Scan Process issues
the device-specific
commands to get scan
data from the scanner

raw data

Scanner

Figure E-1

248

Scanner Driver Architecture

Queues and Multi-Threaded Scanner Drivers

Queue Manipulating Functions
The following functions are provided for manipulating queues:
typedef struct tag_scqueue SCQUEUE;

Table E-4 lists the queue manipulating functions.
Table E-4

Queue Manipulating Functions

Function

Description

SCCreateQueue

Creates a multi-threaded safe, block-on-empty dequeue, queue

SCDestroyQueue Frees the resources used by a queue
SCEnqueue

Adds an element to the tail of the queue

SCDequeue

Removes an element from the head of a queue and returns it

SCQueueSetExit

Sets a flag associated with a queue that tells all queue users to
exit

SCCreateQueue Function
SCQUEUE * SCCreateQueue(int nelems);

This function creates a multi-threaded safe, block-on-empty dequeue,
queue. nelems is the maximum number of elements that can be stored in the
newly created queue. Enqueue operations on full queues will block until
another thread has completed a dequeue operation.
SCDestroyQueue Function
int SCDestroyQueue(SCQUEUE *q);

This function frees the resources used by a queue.
SCEnqueue Function
void SCEnqueue(SCQUEUE *q, void *data);

This function adds an element to the tail of the queue. It unblocks a thread
waiting to dequeue or blocks it if the queue is full.

249

Scanner Driver Architecture

SCDequeue Function
void * SCDequeue(SCQUEUE *q);

This function removes an element from the head of a queue and returns it.
SCDequeue unblocks a thread waiting to enqueue or blocks it if the queue is
empty.
SCQueueSetExit Function
void * SCQueueSetExit(SCQUEUE *q);

This function sets a flag associated with a queue that tells all users of the
queue to exit. Any thread blocking in SCEnqueue or SCDequeue will be
terminated. SCQueueSetExit is used by the main thread of a scanner driver to
tell the child threads to exit when the user aborts a scan.

250

Appendix F

Man Pages

This appendix lists all man pages
associated with Impressario: the general
interest man pages, the printing
developers man pages, and the scanning
developers man pages.

Appendix F

F.

Man Pages

This appendix lists all man pages associated with Impressario. Table F-1 lists
the general interest man pages.
Table F-1

General Interest Man Pages

Names

Description

Impressario(1)

Printing and scanning environment for SGI
systems

glp(1), PrintPanel, printpanel

Graphical lp printing command

PrintStatus(1), printstatus

Graphical printer status tool

gscan(1)

Graphical scanning tool

scanners(1M)

Scanner installation and management tool

fileconvert(1)

File to printer or filetype converter

vstiff(1)

Stream TIFF viewer

psrip(1)

PostScript file to raster data format converter

installfoliofonts(1)

PostScript font installation program for Adobe
Macintosh Font Folio™ CDROM

installpcfonts(1)

PostScript font installation program for Adobe
TypeSet™ PC floppy disks

printers(1M)

Printer installation and management program

253

Man Pages

Table F-2 lists the printing developers man pages and Table F-3 lists the
scanning developers man pages. The software the man pages listed below
describe all utilize the C-language application programming interface (API).
Table F-2
Name

Description

libspool(3)

An AP to the UNIX printer spooling systems

libpod(3)

An API to the printer object database (POD)

libprintui(3X)

An API to the PrintBox widget

libstiff(3)

An API for reading and writing the STIFF (Stream TIFF) data file
format. It is described in detail in Appendix A

libimp(3)

An API for reading and writing Silicon Graphics Image format
files. It is described in detail in Appendix B

Table F-3

254

Printing Developers Man Pages

Scanning Developers Man Pages

Name

Description

libscan(3)

An API for scanning

libstiff(3)

An API for reading and writing the STIFF (Stream TIFF) data file
format. It is described in detail in Appendix A

libimp(3)

An API for reading and writing Silicon Graphics Image Format
files. It is described in detail in Appendix B

Glossary

Glossary

API
Application programming interface; a set of function calls for achieving
some purpose.
BSD
Berkeley Software Distribution.
CHUNKY file format
The original Impressario 1.0 data format; it has been obsoleted in favor of the
Stream TIFF data format.
CMYK STIFF data format
CMYK is a TIFF data format extension. See “Generic STIFF File Structure” in
Appendix A for detailed information. CMYK stands for Cyan, Magenta,
Yellow, and blacK, the subtractive color process primaries.
CMY STIFF data format
CMY data class is a subset of the CMYK class and differs from the CMYK
class in a TIFF-compliant manner. See “Generic STIFF File Structure” in
Appendix A for detailed information.
File Type Rules (FTR)
A database that is one of the three key components of the Impressario file
conversion pipeline. These rules are well-documented in the Indigo Magic
Integration Guide, available as an online book and installable from your IRIX
CD.
filter/driver specification
See “Filter/Driver Specification” in Chapter 3.

257

Glossary

FTR
See File Type Rules.
generic scanner interface
An interface between application programs and scanner drivers. See
Chapter 9, “Generic Scanner Interface,” for additional information.
glp
A graphical end-user interface for submitting print jobs from applications.
See the glp(1) man page for additional information.
graphical options panel
See Chapter 5, “Printer Graphical Options Panel,” for additional
information.
gscan
A graphical end-user interface for using scanners. See the gscan(1) man page
for additional information.
GUI
Graphical user interface.
Impressario
A visual printing and scanning environment for IRIS workstations.
Impressario architecture
See Chapter 1, “Impressario Architecture,” for printing and scanning
architecture.
libimp
A C-language application programming interface (API) for reading and
writing Silicon Graphics Image Format files.
libpod
A C-language application programming interface to the printer object
database (POD).

258

libprintui
A graphical user interface (GUI) printing library.
libscan
A C-language application programming interface for scanning.
libspool
A C-language application programming interface to the UNIX printer
spooling system.
libstiff
A C-language API for reading and writing Stream TIFF files.
lp command
The System V release 3 command to send a print job to the printer. See the
lp(1) man page.
lpr command
The BSD command to send a print job to a printer. See the lpr(1) man page.
lpsched command
The System VR3 spooler job scheduler. Not invoked by end users.
packed data format
Bitmapped data organized by pixel, with all color components for each pixel
adjacent; for example., RGBRGBRGB . . .
planar data format
Bitmapped data organized by color “plane,” with all pixels arranged in
planes of component colors, all components of one color, then another, etc.
plotter format
A raster-based page-description language, most commonly HPGL or some
variant.
POD
See printer object database.

259

Glossary

PostScript printer
A printer with a built-in PostScript interpreter. The printer can only accept
PostScript files.
PrintBox
A graphical end-user interface for submitting print jobs from applications.
See the libprintui(3) man page for additional information.
printer device drivers
See Chapter 3, “Printer Drivers.”
printer libraries
See Chapter 6, “Printing Libraries.”
Printer Manager
A graphical end-user interface for managing and installing printers. See the
man page for additional information.
printer model file
A Bourne shell script that controls the filtering and printing of a set of files.
Invoked by the lpsched command. See Chapter 4, “Printer Model Files.”

.config
A configuration file representing the capabilities of the printer. The .config
file is part of the printer object database (POD).
.log
The printer log file for the specified printer. The .log file is part of the printer
object database (POD).
.status
A status file indicating the current printing state. The .status file is part of the
printer object database (POD).
printer object database (POD)
The POD contains information on the current configuration, status, and job
history of a single printer. It is the central database used by all printing filters
and is maintained by each driver. See Appendix C, “Printer Object Database

260

(POD) File Formats,” for detailed information.
printers
See Printer Manager.
printing architecture
See “Impressario Printing Architecture” in Chapter 1.
PrintPanel
An alias for glp, graphical end-user interface for modifying printer settings.
See the glp(1) man page for additional information.
PrintStatus
A graphical end-user interface for checking printer status. See the
PrintStatus man page for additional information.
raster printer
A printer that only accepts bitmap image data.
scanner driver
A program that interfaces with a scanner. See Chapter 7, “Scanner Drivers,”
for additional information.
scanner-specific options
See Chapter 8, “Scanner-Specific Options.”
scanners
A graphical end-user interface for installing and managing scanners. See the
scanners(1) man page for additional information.
spooling system API
See libspool and libprintui.
STIFF
Stream TIFF is a subset of the Tagged Image File Format (TIFF) originally
developed by Aldus Corporation. See Appendix A, “Stream TIFF Data
Format,” for more information.

261

Glossary

System V spooler interface
See the lp command and lpsched command.
Tagged Image File Format
The Tagged Image File Format (TIFF) originally developed by Aldus
Corporation. See Appendix A, “Stream TIFF Data Format,” for more
information.
TIFF
See Tagged Image File Format.
YMC data format
A data class similar to the CMY class with the exception that data is
organized as YMC instead of CMY. YMC stands for Yellow, Magenta, and
Cyan.
YMCK data format
A class similar to CMYK except that data is organized as YMCK instead of
CMYK. YMCK stands for Yellow, Magenta, Cyan, and blacK.

262

Index

Index

A

B

active icons subsystem, 48
Active Status Path, 212
adding a CONVERT rule, 152
adding a new filetype to Impressario, 152
Adobe Systems, Inc, 2
AdvanceFeeder function, 91
Aldus Corporation, 2
API, 257
libpod, 8
libprintui, 8
libspool, 8
APIs to spooling systems, 7, 64
Apple Computer, 2
application developers
programming interface, 6, 8
application programming interface, 257
application programming interfaces, 6, 8
application/driver functions, 117
AT&T, 2
AT&T System V, 2
AT&T System V printer spooling system, xviii
audience, xviii
Available Fonts option, 213

banner page, 43
banner pages, 49
Berkeley Software Distribution, 2, 257
Black Substitute option, 213
bold syntax convention, xx
brackets, xx
BSD, 2, 257
BSD spooling system, 6
BSD spooling system interface, 9

C
callbacks, 72
Centronics Data Computer Corporation, 2
Centronics interfaces, 48
CHUNKY file format, 257
CMY data format, 169
CMY STIFF data format, 257
CMYK data format, 169
CMYK STIFF data format, 257
Color Adjustment option, 213
color space conversion functions, 188
ColorPostScript, 48
ColorRaster, 48
compatibility issues for device developers, 231
CompuServe, 2

265

Index

.config, 260
config file option
Active Status Path, 212
Available Fonts, 213
Black Substitute, 213
Color Adjustment, 213
Cost per Page, 214
Default CA, 214
Default IS, 214
Default MT, 214
Default QM, 214
Driver Path, 215
Error Retry Wait, 215
Input Source, 215
Location Code, 215
Manual Capable, 215
Maximum Addr, 215
Maximum Print Area, 216
Media Standard, 216
Media Type, 216
Media Wait, 216
Minimum Addr, 216
Minimum Print Area, 216
Number of Colors, 217
Physical Location, 217
Port Path, 217
Printer Class, 217
Printer Model, 218
Printer Options, 218
Quality Modes, 218
Resolution, 218
Size Table Entry, 218
Status Update Wait, 219
Technology, 220
Time per Page, 220
configuration file, 5, 73
configuring the Impressario software, 22
connecting the printer or scanner, 21
copies, number of, 40
Cost per Page option, 214

266

courier syntax convention, xx
creating a graphical options panel, 6
creating a model file, 5
customized banner pages, 49

D
data format
STIFF, 161
data packing functions, 183
data structure
SCANINFO, 81
SCANPARAMS, 83
data structures
scanner, 80
debug switch, 49
Default CA option, 214
Default IS option, 214
Default MT option, 214
Default QM option, 214
DeleteScanner function, 95
deskjet_model.gui, 57
developing a printer driver, 4
device interface, 48
directory
example POD files, 5
model files, 5
printer filter programs, 5
disk space requirements, 20
Display PostScript, 20
document feeder functions, 125
document introduction, xvii
Documenter’s Workbench, 2
DoScan function, 89
dps_eoe subsystem, 20
driver, 141

Driver Path, 215
driver see also printer drivers
development, 27
driver template
scanner, 80

E
engine-specific options, 34
enhancing Impressario with plug-ins, 149
enscript man page, 23
Epson GT-6000, 18
Error, 223
error handling functions, 184
Error Retry Wait option, 215
events, 95

F
fast path for text, 50
FeederReady function, 91
file conversion utility, 151
file extensions
.config, 5
.log, 5
.status, 5
file processing, 44
File Type Rules, 257
file type rules, 150
fileconvert, 230
fileconvert man page, 253
fileconvert utility, 151
files
Impressario Developer’s Kit, 19
filter functions, 199

filter/driver
specification, 32
filter/driver specification, 257
filtering options, 50
FindScanners function, 92
FIT, 18
FIT image file format, xix
FTR, 150, 258
Function
SCBandRGB8ToPixelRGB8, 246
SCCreateQueue, 249
SCCreateZoomMap, 245
SCDequeue, 249, 250
SCDestroyQueue, 249
SCDestroyZoomMap, 245
SCEnqueue, 249
SCGrey8ToMono, 246
SCN_ABORT, 243
SCN_DIE, 243
SCN_FEEDERADVANCE, 242
SCN_FEEDERGETFLAGS, 241
SCN_FEEDERREADY, 242
SCN_FEEDERSETFLAGS, 241
SCN_GETSIZE, 243
SCN_INITOK, 239
SCN_MINMAXRES, 239
SCN_NRES, 240
SCN_NTYPES, 240
SCN_PAGESIZE, 239
SCN_RES, 240
SCN_SCAN, 243
SCN_SETUP, 242
SCN_TYPES, 241
SCQueueSetExit, 249, 250
SCZoomRow1, 246
SCZoomRow24, 246
SCZoomRow32, 246
SCZoomRow8, 246
function
AdvanceFeeder, 91

267

Index

DeleteScanner, 95
DoScan, 89
FeederReady, 91
FindScanners, 92
impClampRow, 194
impClose, 182
impCloseFd, 182
impCMYKtoRGB, 191
impCMYtoRGB, 189
impCopyRow, 194
impCreateZoom, 196
impDestroyZoom, 196
impErrorString, 184
impHSVtoRGB function, 193
impInitRow, 194
impKtoRGB, 188
impOpen, 182
impOpenFd, 182
impPackRow, 183
impPerror, 184
impReadRow, 185
impReadRowB, 185
impResetZoom, 196
impRGBtoCMY, 189
impRGBtoCMYK, 191
impRGBtoDevCMYK, 191
impRGBtoHLS, 193
impRGBtoHSV, 193
impRGBtoK, 188
impRGBtoW, 188
impRGBtoYCbCr, 191
impRGBtoYIQ, 190
impRGBtoYUV, 190
impSAddRow, 194
impSDivRow, 194
impSMulRow, 194
impSSubRow, 194
impUnpackRow, 183
impVAddRow, 194
impVSubRow, 194
impWriteRow, 185

268

impWriteRowB, 185
impWtoRGB, 188
impYCbCrtoRGB, 191
impYIQtoRGB, 190
impZeroRow, 194
impZoomRow, 196
InstallScanner, 94
OpenScanner, 86
PrintID, 92
SCAbort, 124
SCBandRGB8ToPixelRGB8, 246
SCClose, 118
SCCreateQueue, 249
SCCreateZoomMap, 245
SCDataReady, 123
SCDefaultScannerName, 120
SCDequeue, 250
SCDestroyQueue, 249
SCDestroyZoomMap, 245
SCEndScanEnt, 119
SCEnqueue, 249
SCErrorString, 116
SCFeederAdvance, 127
SCFeederGetFlags, 126
SCFeederReady, 127
SCFeederSetFlags, 126
SCGetDataTypes, 121
SCGetFD, 124
SCGetMinMaxRes, 120
SCGetPageSize, 121
SCGetScanEnt, 119
SCGetScanLine, 123
SCGetScannerRes, 120
SCGetScanSize, 123
SCGetStatus, 124
SCGetStatusFD, 125
SCGrey8ToMono, 246
SCN_ABORT, 243
SCN_DIE, 243
SCN_FEEDERGETFLAGS, 241
SCN_FEEDERREADY, 242

SCN_FEEDERSETFLAGS, 241
SCN_GETSIZE, 243
SCN_INITOK, 239
SCN_MINMAXRES, 239
SCN_NRES, 240
SCN_NTYPES, 240
SCN_PAGESIZE, 239
SCN_RES, 240
SCN_SCAN, 243
SCN_SETUP, 242
SCN_TYPES, 241
SCOpen, 118
SCOpenFile, 118
SCOpenScreen, 118
SCPerror, 116
SCQueueSetExit, 250
SCScan, 123
SCScanFD, 124
SCScannerName, 119
SCSetScanEnt, 118
SCSetup, 122
SCZoomRow1, 246
SCZoomRow24, 246
SCZoomRow32, 246
SCZoomRow8, 246
SetFeederFlags, 91
SetupScan, 88

glossary, 257
glp, 9, 10, 258
program, 58
glp man page, 253
graphical interface
PrintBox, 2
printers, 2
PrintPanel, 2
PrintStatus, 2
scanners, 2
graphical options panel, 53, 258
action area, 55
development, 56
installation, 57
invocation, 58
layout, 54
naming, 57
options handling, 56
termination, 59
graphical options panel program, 141
graphical options panel resource file, 141
graphical user interface, xviii
Graphics Interchange Format, 2
grelnotes man page, xvii
gscan, 13, 258
gscan man page, 161, 253
GUI, xviii, 258

G
general changes from IRIX 4 to IRIX 5, 231
general filter/driver architecture, 7
general interest man pages, 253
generic scanner API, 101
generic scanner interface, 111, 258
generic STIFF file structure, 166
getopts, 30
GIF, 2
GIF image file format, xix

H
hardware interfaces, 48
header files
scanner, 80
helvetic bold syntax convention, xx
helvetic syntax convention, xx
Hewlett-Packard, 2
how the file conversion pipeline works, 150

269

Index

how to use this guide, xix
HP DesignJet 650C, 2, xix, 19
HP DeskJet, 19
HP LaserJet, 2, 19
HP PaintJet, 19
HP ScanJet IIc, 18
HP ScanJet IIcx, 18
HP-GL, 2

I
image access functions, 181
image file format
FIT, xix
GIF, xix
JPEG, xix
PBM, xix
PGM, xix
PhotoCD, xix
PPM, xix
RGB, xix
Silicon Graphics, xix
TIFF, xix
image I/O functions, 185
impClampRow function, 194
impClose function, 182
impCloseFd function, 182
impCMYKtoRGB function, 191
impCMYtoRGB function, 189
impCopyRow function, 194
impCreateZoom, 196
impCreateZoom function, 196
impDestroyZoom, 196
impDestroyZoom function, 196
impErrorString function, 184
impHLStoRGB function, 193

270

IMPImage structure, 179
impInitRow function, 194
impKtoRGB function, 188
impOpen function, 181, 182
impOpenFd function, 182
impPackRow function, 183
impPerror function, 184
impr_base.books.user, 18
impr_base.man.impr, 18
impr_base.man.relnotes, 18
impr_base.sw.il_image, 18
impr_base.sw.il_images, 20
impr_base.sw.impr, 18
impr_dev.books.developer, 19
impr_dev.man.impr, 19
impr_dev.man.print, 19
impr_dev.man.scan, 19
impr_dev.sw.impr, 19
impr_dev.sw.print, 19
impr_dev.sw.scan, 19
impr_dev.sw.tests, 19
impr_fonts, 21
impr_fonts.man.gifts, 18
impr_fonts.sw.adobe22, 18
impr_fonts.sw.gifts, 18
impr_rip, 21
impr_rip_printers.man.designjet, 19
impr_rip_printers.man.deskjet, 19
impr_rip_printers.man.laserjet, 19
impr_rip_printers.sw.designjet, 19
impr_rip_printers.sw.deskjet, 19
impr_rip_printers.sw.laserjet, 19
impr_rip.man.impr, 19
impr_rip.sw.impr, 19
impr_scan.man.impr, 18

impr_scan.sw.epson, 18
impr_scan.sw.hp, 18
impr_scan.sw.impr, 18
impr_scan.sw.ricoh, 18
impr_scan.sw.sharpscsi, 18
impr_scan.sw.utek, 18
impr_server.man.impr, 18
impr_server.sw.impr, 18
impr_server.sw.laserwriter, 19
impReadRow function, 185
impReadRowB function, 185
impResetZoom, 196
impResetZoom function, 196
Impressario, 258
APIs to spooling system, 7
application programming interfaces, 6, 8
architecture, 1
printing, 3
compliance
print driver developers, 4
compliance, scanner driver development, 13
overview, 2
printing application development, 10
printing architecture, 3
scanner application development, 13
scanner driver development, 13
subsystems, 18, 134
Impressario 1.0 to 1.2, 229
Impressario 1.1, xix
Impressario 1.1 to 1.2, 228
Impressario 1.2, xix
Impressario architecture, 258
Impressario compliance
for scanners, 11
Impressario Developer’s Kit, xvii
Impressario Developer’s Kit files, 19
Impressario Developer’s Kit software, 17

Impressario man page, 253
Impressario printing architecture, 3
Impressario release notes, xvii
Impressario subsystems, 18, 134
impRGBtoCMY function, 189
impRGBtoCMYK function, 191
impRGBtoDevCMYK function, 191
impRGBtoHLS function, 193
impRGBtoHSV function, 193
impRGBtoK function, 188
impRGBtoW function, 188
impRGBtoYCbCr function, 191
impRGBtoYIQ function, 190
impRGBtoYUV function, 190
impSAddRow function, 194
impSDivRow function, 194
impSMulRow function, 194
impSSubRow function, 194
impUnpackRow function, 183
impVSubRow function, 194
impWriteRow function, 185
impWriteRowB function, 185
impWtoRGB function, 188
impYCbCrtoRGB function, 191
impYIQtoRGB function, 190
impYUVtoRGB, 190
impYUVtoRGB function, 190
impZeroRow function, 194
impZoomRow, 196
impZoomRow function, 196
Indigo, 2
Indigo Magic desktop, 20
Information, 223
Input Source option, 215
installation

271

Index

disk space requirements, 20
software prerequisites, 20
installation method, 20
installation software prerequisites, 20
installfoliofonts man page, 253
installing Impressario software, 17, 21
installpcfonts man page, 253
InstallScanner function, 94
interfaces, 48
interprocess scanner communication, 12
IRIS, 2
IRIX, 2
IRIX 4.0.5 clients, xix
IRIX 4.0.5 servers, xix
IRIX 5 ELF versus IRIX 4 COFF-format options panel,
231
IRIX 5.2 clients, xix
IRIX 5.2 servers, xix
ISO text files, xviii
italics syntax convention, xx

J
job
sequence ID number, 40
title, 40
JPEG, xix

K
KCMY data format, 171

272

L
laserjet, 29
LaserWriter, 2
libimp, xix, 2, 175, 258
libimp library, 196
libimp library functions, 176
libimp man page, 254
libpod, 2, 5, 8, 10, 229, 258
libpod API, 8
libpod library, 73
compiling programs, 75
debugging, 75
file parsing rules, 209
functions, 76
local functions, 74
standard functions, 74
libpod man page, 254
libprintui, 2, 9, 10, 54, 259
libprintui API, 8
libprintui library, 8, 67
compiling, 70
example program, 71
functions, 71
libprintui man page, 254
library
libimp, xix, 2
libpod, 2
libprintui, 2, 8
libscan, 2
libspool, xviii, 2
libstiff, 2
libscan, 2, 11, 13, 259
libscan man page, 254
libscan.a, 11, 236
libspool, xviii, 2, 8, 9, 10, 229, 259
libspool API, 8
libspool library, 64

compiling, 64
functions, 65
libspool man page, 254
libstiff, 2, 13, 161, 254, 259
libstiff man page, 254
Location Code, 215
.log, 260
lp command, 6, 259
lpr command, 6, 259
lpsched
command-line arguments, 40
lpsched command, 259

M
making a software distribution, 140
man page
fileconvert, 253
glp, 253
grelnotes, xvii
gscan, 253
Impressario, 253
installfoliofonts, 253
installpcfonts, 253
libimp, 254
libpod, 254
libprintui, 254
libscan, 254
libspool, 254
libstiff, 254
printers, 253
PrintPanel, 253
printpanel, 253
PrintStatus, 253
printstatus, 253
psrip, 253
relnotes, xvii
scanners, 253

vstiff, 253
man pages, 253
enscript, 23
Manual Capable option, 215
manual page, 141
Massachusetts Institute of Technology, 2
Maximum Addr option, 215
Maximum Print Area option, 216
Media Size, 221
Media Standard option, 216
Media Type, 222
Media Type option, 216
Media Wait option, 216
MediaWaitTimeout, 34
MicroTek ScanMaker 600ZS, 18
Minimum Addr option, 216
Minimum Print Area option, 216
model file, 39, 141
banner pages, 49
command-line arguments, 40
debug routines, 49
device interface, 48
file processing, 44
filtering options, 50
general options, 45
printer name, 47
template, 47
MonoPostScript, 48
Motif, 2
Motif widget, 2

N
network communication, 74
new interchange file format, 230
new model file architecture, 230

273

Index

Number of Colors, 222
Number of Colors option, 217

O
online man pages, xxiv
Open Software Foundation, 2
OpenScanner function, 86, 103
Operational Status, 221
OSF, 2
OSF/Motif, 2, 56
output-specific options, 35
overview of chapters and appendices, xxi

P
packaging Impressario printing software, 141
packaging Impressario scanning software, 144
packaging your Impressario product, 139
packed data format, 259
PBM image file format, xix
PDpod_path global variable, 74
Personal IRIS, 2
PGM image file format, xix
phandler, 29
PhotoCD, 18
PhotoCD image file format, xix
Physical Location, 217
planar data format, 259
Plotter, 48
plotter format, 259
plp.h, 29
POD, 259
general syntax, 208
POD files, 5, 141

274

POD general syntax, 208
character set, 208
field format, 208
podd, 8
pod.h, 29
Port Path, 217
PostScript
color and mono, 48
PostScript files, xviii
PostScript interpreter changes, 229
PostScript printer, 260
PPM image file format, xix
PrintBox, 9, 54, 260
example configurations, 68
man page, 71, 76
PrintBox graphical interface, 2
printbox program, 71
PrintBox widget, xviii
printed books, xxiii
printer
Apple LaserWriter II, 21
Apple LaserWriter IIf, 21
Apple LaserWriter IIg, 21
Apple LaserWriter IINT, 21
Apple LaserWriter IINTX, 21
Apple LaserWriter Plus, 21
convenience functions, 42
Hewlett-Packard DesignJet 650C, 21
Hewlett-Packard DeskJet 500C, 21
Hewlett-Packard DeskJet 550C, 21
Hewlett-Packard LaserJet 4, 21
Hewlett-Packard LaserJet III, 21
Hewlett-Packard LaserJet IIIP, 21
Hewlett-Packard LaserJet IIP, 21
Hewlett-Packard LaserJet IIP+, 21
Hewlett-Packard PaintJet XL300, 21
host, 74
HP DesignJet 650C, xix
name, 47

process command-line arguments, 43
types, 48
Printer Class, 217
printer configuration, 22
printer configuration file, 73, 206
format, 210
parsing, 209
printer device drivers, 260
printer drivers
development, 27
engine-specific options, 34
example, 29
include files, 29
invocation, 29
output-specific options, 35
raster-specific options, 34
required options, 33
required switches, 33
reserved options, 33
unreserved options, 35
printer libraries, 260
printer log file, 5, 207
Printer Manager, 22, 48, 260
Printer Model, 218
printer model file, 260
printer object database, 2, 260
files, 73
printer object database (POD) file formats, 205
Printer Options, 218, 223
printer status file, 5, 73, 207
entries, 220
format, 220, 224
general format, 220
parsing, 209
printer status file entry
Error, 223
Information Options, 223
Media Size, 221

Media Type, 222
Number of Colors, 222
Operational Status, 221
Printer Options, 223
Validation Mask, 223
Warning, 223
printer status file format, 220
printer support, 21
printer-specific filter/driver, 49
printers, 261
printers graphical interface, 2
printers man page, 253
PrintID function, 92
printing application development, 10
printing architecture, 261
printing developers man pages, 254
printing environment, xviii
printing libraries, 63
printing-specific STIFF, 166
PrintPanel, 9, 261
PrintPanel man page, 253
printpanel man page, 253
PrintStatus, 261
PrintStatus man page, 253
printstatus man page, 253
providing data filters, 5
providing POD files, 5
pschunky, 229
psrip, 229
psrip man page, 253

Q
Quality Modes option, 218
queues and multi-threaded scanner drivers, 247
queues manipulating functions, 249

275

Index

R
Raster, 48
raster printer, 261
raster-specific options, 34
related publications, xxiii
online man pages, xxiv
printed books, xxiii
relnotes man page, xvii
remote interfaces, 48
required scanner functions, 238
Resolution option, 218
RGB image file format, xix
rgb2ps, 230
Ricoh FS1, 18
routeprint, 48
runtime filetype recognition utility, 150

S
SC4-DPS-1.0, 20
SCAbort function, 124
scanconv.h, 80
scandrv.h, 80
SCANINFO data structure, 81
scanipc.h, 80
Scanner
coordinate system, 112
scanner
data structures, 80
data type conventions, 114
driver template, 80
drivers, 79
Epson GT 6000, 22
header files, 80
Hewlett-Packard ScanJet IIc, 22
installation and testing, 97

276

MicroTek ScanMaker 600 ZS, 22
Ricoh FS1, 22
Sharp JX 320, 22
scanner configuration, 22
scanner data type
8-bit greyscale, 114
monochrome, 114
packed 24-bit RGB color, 115
planar 24-bit RGB color, 115
scanner diagnostic functions, 116
scanner driver architecture, 235, 248
scanner driver interface, 102
scanner driver interface options program, 102
scanner driver structure, 236
scanner drivers, 261
scanner functions, 238
required, 238
scanner run-time components, 11
scanner support, 22
scanner-specific options, 101, 261
scanner-specific options program, 105
scanner.h, 80
scanners, 108, 261
scanners man page, 253
scanning area functions, 121
scanning environment, xviii
scanning functions, 122
scanning resolution functions, 120
SCANPARAMS data structure, 83
SCBandRGB8ToPixelRGB8 function, 246
SCClose function, 118
SCCreateQueue Function, 249
SCCreateQueue function, 249
SCCreateZoomMap function, 245
SCDataReady function, 123
SCDATATYPE data structure, 113

SCDefaultScannerName function, 120
SCDequeue Function, 249
SCDequeue function, 250
SCDestroyQueue Function, 249
SCDestroyQueue function, 249
SCDestroyZoomMap function, 245
SCEndScanEnt function, 119
SCEnqueue Function, 249
SCEnqueue function, 249
SCErrorString function, 116
SCFeederAdvance function, 127
SCFeederGetFlags function, 126
SCFeederReady function, 127
SCFeederSetFlags function, 126
SCGetDataTypes function, 121
SCGetFD function, 124
SCGetMinMaxRes function, 120
SCGetPageSize function, 121
SCGetScanEnt function, 119
SCGetScanLine function, 123
SCGetScannerRes function, 120
SCGetScanOpt, 105, 107
SCGetScanSize function, 123
SCGetStatus function, 124
SCGetStatusFD function, 125
SCGrey8ToMono function, 246
SCLOPT structure, 103
sclopt.h, 102
SCN_ABORT function, 243
SCN_DIE function, 243
SCN_FEEDERADVANCE, 242
SCN_FEEDERADVANCE function, 242
SCN_FEEDERGETFLAGS function, 241
SCN_FEEDERREADY function, 242
SCN_FEEDERSETFLAGS function, 241

SCN_GETSIZE function, 243
SCN_INITOK Function, 239
SCN_MINMAXRES function, 239
SCN_NRES function, 240
SCN_NTYPES function, 240
SCN_PAGESIZE function, 239
SCN_RES function, 240
SCN_SCAN function, 243
SCN_SETUP function, 242
SCN_TYPES function, 241
SCOpen, 236
SCOpen function, 118
SCOpenFile function, 118
SCOpenScreen function, 118
SCOptions, 105
SCPerror function, 116
SCQueueSetExit Function, 249
SCQueueSetExit function, 250
SCScan function, 123
SCScanFD function, 124
SCScannerName function, 119
SCScanOpt, 107
SCSetScanEnt function, 118
SCSetup function, 122
SCZoomRow1 function, 246
SCZoomRow24 function, 246
SCZoomRow32 function, 246
SCZoomRow8 function, 246
serial interfaces, 48
server software, xviii
SetFeederFlags function, 91
SetupScan function, 88
sgi2ps, 230
Sharp JX 320, 18
Silicon Graphics filter/driver specification, 32

277

Index

Silicon Graphics Image file format, xix
Silicon Graphics Image file format API, 175
Silicon Graphics Image files, xviii
Silicon Graphics Image to PostScript filter changes,
230
Size Table Entry option, 218
software file
impr_base.books.user, 18
impr_base.man.impr, 18
impr_base.man.relnotes, 18
impr_base.sw.il_image, 18
impr_base.sw.impr, 18
impr_dev.books.developer, 19
impr_dev.man.impr, 19
impr_dev.man.print, 19
impr_dev.man.scan, 19
impr_dev.sw.impr, 19
impr_dev.sw.print, 19
impr_dev.sw.scan, 19
impr_dev.sw.tests, 19
impr_fonts.man.gifts, 18
impr_fonts.sw.adobe22, 18
impr_fonts.sw.gifts, 18
impr_rip_printers.man.designjet, 19
impr_rip_printers.man.deskjet, 19
impr_rip_printers.man.laserjet, 19
impr_rip_printers.sw.designjet, 19
impr_rip_printers.sw.deskjet, 19
impr_rip_printers.sw.laserjet, 19
impr_rip.man.impr, 19
impr_rip.sw.impr, 19
impr_scan.man.impr, 18
impr_scan.sw.epson, 18
impr_scan.sw.hp, 18
impr_scan.sw.impr, 18
impr_scan.sw.ricoh, 18
impr_scan.sw.sharpscsi, 18
impr_scan.sw.utek, 18
impr_server.man.impr, 18
impr_server.sw.impr, 18

278

impr_server.sw.laserwriter, 19
spooling system API, 64, 261
ST4-DPS-1.0, 20
.status, 260
status file, 73
Status Update Wait, 219
stdout, 55
STIFF, 13, 261
STIFF data format, 161
STIFF generic functions, 163
STIFF library access, 162
STIFF library description, 162, 175
STIFF library functions, 163
STIFF printing-specific functions, 164
stream TIFF, 161
style conventions, xx
notations, xx
syntax, xx
summary of libpod functions, 76
summary of libprintui functions, 71
syntax convention
bold, xx
brackets, xx
courier, xx
helvetic, xx
helvetic bold, xx
italics, xx
System V Spooler Interface, 262
System V spooler interface, 6
System V spooling system interface, 9

T
Tagged Image File Format, 262
Technology, 220
Tektronix, 2

Tektronix Phaser, 2
Tektronix Phaser II PXi, 2
Tektronix Phaser II SX, 2
Tektronix, Inc, 2
template model file execution, 41
testiconfig, 6, 136
testiconfig man page, 133
testing an Impressario printer, 134
testing an Impressario printer software installation,
136
testipr, 6, 134
testipr man page, 133
TIFF, 2, 18, 262
TIFF image file format, xix
Time per Page option, 220
TranScript, 2
TranScript printer model files, 23
transition notes, 227
Impressario 1.0 to 1.2, 229
compatibility issues for device developers, 231
for application developers, 229
for filter/driver developers, 229
general changes from IRIX 4 to IRIX 5, 231
IRIX 5 ELF versus IRIX 4 COFF-format options
panel, 231
new interchange file format, 230
new model file architecture, 230
POD files enhancement, 231
PostScript interpreter changes, 229
Silicon Graphics Image to PostScript filter
changes, 230
Impressario 1.1 to 1.2, 228
for application developers, 228
for filter/driver developers, 228

U
UNIX, 2
UNIX System Laboratories, 2
unreserved options, 35
user name, 40
using an alternate PostScript RIP, 156

V
Validation Mask, 223
vendor-supplied model file additions, 47
Versatec, 2
Versatec Corporation, 2
Versatec interfaces, 48
vstiff man page, 253

W
Warning, 223
widget
example configurations, 68
WorkSpace, 2
writing a new filter, 152
writing an FTR, 152
wstype, 230
wstype utility, 150

X
X and Xt Motif documentation set, 106
X applications, 71
X Window System, 2
Xt options, 58
XtAppInitialize, 107

279

Index

Y
YMC data format, 170, 262
YMCK data format, 170, 262

Z
zooming and type conversion functions, 244, 245
zooming Functions, 196

280

Tell Us About This Manual
As a user of Silicon Graphics products, you can help us to better understand your needs
and to improve the quality of our documentation.
Any information that you provide will be useful. Here is a list of suggested topics:
•

General impression of the document

•

Omission of material that you expected to find

•

Technical errors

•

Relevance of the material to the job you had to do

•

Quality of the printing and binding

Please send the title and part number of the document with your comments. The part
number for this document is 007-1633-030.
Thank you!

Three Ways to Reach Us
•

To send your comments by electronic mail, use either of these addresses:
–

On the Internet: techpubs@sgi.com

–

For UUCP mail (through any backbone site): [your_site]!sgi!techpubs

•

To fax your comments (or annotated copies of manual pages), use this
fax number: 650-932-0801

•

To send your comments by traditional mail, use this address:
Technical Publications
Silicon Graphics, Inc.
2011 North Shoreline Boulevard, M/S 535
Mountain View, California 94043-1389



Source Exif Data:
File Type                       : PDF
File Type Extension             : pdf
MIME Type                       : application/pdf
PDF Version                     : 1.1
Linearized                      : No
Page Count                      : 308
Create Date                     : 1999:01:06 12:59:11
Producer                        : Acrobat Distiller 3.02
EXIF Metadata provided by EXIF.tools

Navigation menu