pax_global_header 0000666 0000000 0000000 00000000064 14074577431 0014526 g ustar 00root root 0000000 0000000 52 comment=1c76c98cbac9c86567f1cd8d31b10270164ecc4f
.depend 0000664 0000000 0000000 00000000435 14074577431 0012334 0 ustar 00root root 0000000 0000000 # DO NOT DELETE
error.o: raster.h
raster.o: raster.h
RasterDisplay.o: RasterDisplay.h raster.h
RasterView.o: RasterView.h RasterDisplay.h raster.h eyedropper.xbm left.xbm
RasterView.o: list.xbm move.xbm right.xbm zoom-in.xbm zoom-out.xbm
main.o: RasterView.h RasterDisplay.h raster.h
.lgtm.yml 0000664 0000000 0000000 00000000076 14074577431 0012641 0 ustar 00root root 0000000 0000000 queries:
- exclude: cpp/resource-not-released-in-destructor
LICENSE 0000664 0000000 0000000 00000026136 14074577431 0012107 0 ustar 00root root 0000000 0000000
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Makefile.in 0000664 0000000 0000000 00000007655 14074577431 0013154 0 ustar 00root root 0000000 0000000 #
# Makefile for rasterview, a CUPS/PWG Raster viewing program.
#
# Copyright © 2002-2021 by Michael R Sweet
#
# Licensed under Apache License v2.0. See the file "LICENSE" for more
# information.
#
# Version...
VERSION = @VERSION@
# Installation directories
BUILDROOT = $(DSTROOT)$(RPM_BUILD_ROOT)$(DESTDIR)
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
datadir = @datadir@
datarootdir = @datarootdir@
desktopdir = @desktopdir@
# Compiler definitions...
ARCHFLAGS = @ARCHFLAGS@
CC = @CC@
CFLAGS = $(ARCHFLAGS) $(CPPFLAGS) $(OPTIM) @CFLAGS@ @DEFS@
CP = @CP@
CODE_SIGN = @CODE_SIGN@
CODESIGN_IDENTITY = -
CPPFLAGS = @CPPFLAGS@
CSFLAGS = -s "$(CODESIGN_IDENTITY)" @CSFLAGS@ --timestamp
CXX = @CXX@
CXXFLAGS = $(ARCHFLAGS) $(CPPFLAGS) $(OPTIM) @CXXFLAGS@ @DEFS@
FLTKCONFIG = @FLTKCONFIG@
LDFLAGS = $(ARCHFLAGS) $(OPTIM) @LDFLAGS@
LIBS = @LIBS@
OPTIM = @OPTIM@
MKDIR = @MKDIR@ -p
RM = @RM@ -f
SHELL = /bin/sh
# Rules for compiling...
.SUFFIXES: .c .cxx .o
.c.o:
$(CC) $(CFLAGS) -c $<
.cxx.o:
$(CXX) $(CXXFLAGS) -c $<
# Objects...
RVOBJS = \
RasterDisplay.o \
RasterView.o \
error.o \
raster.o \
main.o
OBJS = \
$(RVOBJS) \
testcie.o
# Standard install targets...
all: rasterview testcie
clean:
$(RM) rasterview testcie
$(RM) $(OBJS)
$(RM) *.bck
$(RM) *~
depend:
makedepend -Y -f .depend *.c *.cxx
distclean: clean
$(RM) -r autom4te*
$(RM) config.*
$(RM) Makefile
$(RM) RasterView.app/Contents/MacOS/rasterview
install: all @INSTALLDESKTOP@
$(MKDIR) $(BUILDROOT)$(bindir)
cp rasterview $(BUILDROOT)$(bindir)
install-desktop:
$(MKDIR) $(BUILDROOT)$(desktopdir)/Development
cp rasterview.desktop $(BUILDROOT)$(desktopdir)/Development
$(MKDIR) $(BUILDROOT)$(datadir)/mimelnk/application
cp vnd.cups-raster.desktop $(BUILDROOT)$(datadir)/mimelnk/application
$(MKDIR) $(BUILDROOT)$(datadir)/mimelnk/image
cp pwg-raster.desktop $(BUILDROOT)$(datadir)/mimelnk/image
cp urf.desktop $(BUILDROOT)$(datadir)/mimelnk/image
$(MKDIR) $(BUILDROOT)$(datadir)/icons/hicolor/32x32/apps
cp rasterview-32.png $(BUILDROOT)$(datadir)/icons/hicolor/32x32/apps/rasterview.png
$(MKDIR) $(BUILDROOT)$(datadir)/icons/hicolor/128x128/apps
cp rasterview-128.png $(BUILDROOT)$(datadir)/icons/hicolor/128x128/apps/rasterview.png
uninstall: @UNINSTALLDESKTOP@
$(RM) $(BUILDROOT)$(bindir)/rasterview
uninstall-desktop:
$(RM) $(desktopdir)/Graphics/rasterview.desktop
$(RM) $(datadir)/mimelnk/application/vnd.cups-raster.desktop
$(RM) $(datadir)/mimelnk/image/pwg-raster.desktop
$(RM) $(datadir)/mimelnk/image/urf.desktop
$(RM) $(datadir)/icons/hicolor/32x32/apps/rasterview.png
$(RM) $(datadir)/icons/hicolor/128x128/apps/rasterview.png
# Make a disk image with the compiled program on macOS...
dmg: all
echo Signing RasterView application bundle
codesign -f $(CSFLAGS) RasterView.app
echo Creating archive for notarization
rm -f RasterView.zip
ditto -c -k --keepParent RasterView.app RasterView.zip
echo Notarizing application
xcrun altool --notarize-app -f RasterView.zip \
--primary-bundle-id org.msweet.rasterview \
--username "$(APPLEID)" \
--password "@keychain:AC_$(TEAMID)" \
--asc-provider "$(TEAMID)"
echo Making disk image
rm -f rasterview-$(VERSION).dmg
dmgbuild -s dmgbuild.py "RasterView $(VERSION)" ~/Desktop/rasterview-$(VERSION)-macos.dmg
# Make an RPM for Linux...
rpm: all
epm -v -f rpm -nsm --output-dir dist rasterview
mv dist/*.rpm .
rm -rf dist
# Build the rasterview program...
rasterview: $(RVOBJS) Makefile
$(CXX) $(LDFLAGS) -o $@ $(RVOBJS) $(LIBS)
if test x`uname` = xDarwin; then \
test -d RasterView.app/Contents/MacOS || mkdir RasterView.app/Contents/MacOS; \
$(CP) rasterview RasterView.app/Contents/MacOS/rasterview; \
$(CODE_SIGN) $(CSFLAGS) RasterView.app; \
fi
$(RVOBJS): RasterView.h RasterDisplay.h
# Build the CIE test program...
testcie: testcie.o Makefile
$(CC) $(LDFLAGS) -o $@ testcie.o -lm
# Dependencies...
$(OBJS): Makefile
include .depend
NOTICE 0000664 0000000 0000000 00000000066 14074577431 0012000 0 ustar 00root root 0000000 0000000 RasterView
Copyright © 2002-2021 by Michael R Sweet
README.md 0000664 0000000 0000000 00000007362 14074577431 0012361 0 ustar 00root root 0000000 0000000 RasterView
==========
RasterView is a CUPS, PWG, and Apple raster file viewing application. It
basically allows you to look at the raster data produced by any of the standard
CUPS RIP filters (cgpdftoraster, imagetoraster, pdftoraster, and pstoraster) and
is normally used to either test those filters or look at the data that is being
sent to your raster printer driver.
RasterView is licensed under the Apache License Version 2.0.
More information can be found at:
https://www.msweet.org/rasterview
Requirements
------------
If you plan on (re)compiling it, you'll need FLTK () 1.1.x
or later and a C++ compiler.
## How to Compile
Run the following commands:
./configure
make
How to Use
----------
The program is called "rasterview" on UNIX/Linux and "RasterView.app" on macOS.
Run the program and then open a raster file, or pass the filename on the
command-line. You can view multiple files simultaneously.
The "test" subdirectory includes a script for generating raster data using the
standard RIP filters. Run the following command for help:
tools/maketestfiles.sh help
Legal Stuff
-----------
RasterView is Copyright © 2002-2021 by Michael R Sweet.
RasterView is provided under the terms of the Apache License, Version 2.0. A
copy of this license can be found in the file `LICENSE`. Additional legal
information is provided in the file `NOTICE`.
Unless required by applicable law or agreed to in writing, software distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.
Changes in v1.8 (2021-07-17)
----------------------------
- Fixed HiDPI support on Linux (Issue #11)
- Fixed macOS 11 (Big Sur) issues (Issue #15)
- Can now view page bitmaps up to 2GB in size (Issue #16)
- Color picker mode now copies the hex RGB color to the clipboard.
- Zoom gestures are now supported on macOS.
- Addressed a few warnings from LGTM.
- Fixed macOS bundle information and now provide fat binaries for Intel and
Apple Silicon.
Changes in v1.7.1 (2018-07-02)
------------------------------
- Fixed a crash bug on macOS.
Changes in v1.7 (2018-06-03)
----------------------------
- Updated the page controls to allow navigation to the previous page and to
selected pages.
- Added mode buttons for zoom, pan, and color (to show the current mode).
Changes in v1.6 (2018-01-21)
----------------------------
- Now licensed under the Apache License Version 2.0.
- Fixed support for 16-bit per color files.
- Added support for gzip'd raster files (Issue #7)
Changes in v1.5 (2017-03-22)
----------------------------
- Added support for Apple raster files.
Changes in v1.4.1 (2015-08-27)
------------------------------
- Fixed the dependency on strlcpy.
Changes in v1.4 (2015-08-26)
----------------------------
- Added support for Device-N raster files.
- Colorants can now be changed for Device-N, K, CMY, and CMYK raster files.
- Attributes for PWG Raster files are now reported using the PWG 5102.4
naming and contents.
Changes in v1.3 (2011-05-18)
----------------------------
- Added support for PWG Raster files (requires CUPS 1.5 or higher)
Changes in v1.2.2 (2007-06-21)
------------------------------
- Added range checks to the page reader so that pages larger than 64MB or with
invalid dimensions will not cause the program to crash.
Changes in v1.2.1 (2006-09-28)
------------------------------
- Changed the default scheme to gtk+, which is available in FLTK 1.1.8
and higher.
- Added a --enable-static configure option to use the static CUPS
libraries.
Changes in v1.2 (2006-05-13)
----------------------------
- First public release.
RasterDisplay.cxx 0000664 0000000 0000000 00000354273 14074577431 0014422 0 ustar 00root root 0000000 0000000 //
// CUPS/PWG Raster display widget methods.
//
// Copyright © 2002-2021 by Michael R Sweet.
//
// Licensed under Apache License v2.0. See the file "LICENSE" for more
// information.
//
#include "RasterDisplay.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//
// Absolute value macro...
//
#define abs(a) ((a) < 0 ? -(a) : (a))
//
// Constants...
//
#define D65_X (0.412453 + 0.357580 + 0.180423)
#define D65_Y (0.212671 + 0.715160 + 0.072169)
#define D65_Z (0.019334 + 0.119193 + 0.950227)
#define SBWIDTH 17 // Scrollbar width
//
// Local globals...
//
static int endian_offset = -1;
static Fl_Preferences *prefs = NULL;
//
// Local functions...
//
static void convert_cmy(cups_page_header2_t *header, uchar *line,
uchar *colors, uchar *pixels);
static void convert_cmyk(cups_page_header2_t *header, uchar *line,
uchar *colors, uchar *pixels);
static void convert_device(cups_page_header2_t *header, uchar *line, uchar *colors, uchar *pixels, uchar device_colors[][3]);
static void convert_k(cups_page_header2_t *header, uchar *line,
uchar *colors, uchar *pixels);
static void convert_kcmy(cups_page_header2_t *header, uchar *line,
uchar *colors, uchar *pixels);
static void convert_kcmycm(cups_page_header2_t *header, uchar *line,
uchar *colors, uchar *pixels);
static void convert_lab(cups_page_header2_t *header, uchar *line,
uchar *colors, uchar *pixels);
static void convert_rgb(cups_page_header2_t *header, uchar *line,
uchar *colors, uchar *pixels);
static void convert_rgba(cups_page_header2_t *header, int y, uchar *line,
uchar *colors, uchar *pixels);
static void convert_rgbw(cups_page_header2_t *header, uchar *line,
uchar *colors, uchar *pixels);
static void convert_w(cups_page_header2_t *header, uchar *line,
uchar *colors, uchar *pixels);
static void convert_xyz(cups_page_header2_t *header, uchar *line,
uchar *colors, uchar *pixels);
static void convert_ymc(cups_page_header2_t *header, uchar *line,
uchar *colors, uchar *pixels);
static void convert_ymck(cups_page_header2_t *header, uchar *line,
uchar *colors, uchar *pixels);
static ssize_t raster_cb(gzFile ctx, unsigned char *buffer, size_t length);
//
// 'RasterDisplay::RasterDisplay()' - Create a new raster display widget.
//
RasterDisplay::RasterDisplay(
int X, // I - X position
int Y, // I - Y position
int W, // I - Width
int H, // I - Height
const char *L) // I - Label string
: Fl_Group(X, Y, W, H, L),
xscrollbar_(X, Y + H - SBWIDTH, W - SBWIDTH, SBWIDTH),
yscrollbar_(X + W - SBWIDTH, Y, SBWIDTH, H - SBWIDTH)
{
end();
box(FL_DOWN_BOX);
memset(&header_, 0, sizeof(header_));
fp_ = NULL;
filename_ = NULL;
ras_ = NULL;
pixels_ = NULL;
alloc_pixels_ = 0;
colors_ = NULL;
alloc_colors_ = 0;
factor_ = 0.0;
mode_ = RASTER_MODE_ZOOM_IN;
mouse_x_ = 0;
mouse_y_ = 0;
xscrollbar_.type(FL_HORIZONTAL);
xscrollbar_.callback(scrollbar_cb, this);
yscrollbar_.type(FL_VERTICAL);
yscrollbar_.callback(scrollbar_cb, this);
resize(X, Y, W, H);
}
//
// 'RasterDisplay::~RasterDisplay()' - Destroy a raster display widget.
//
RasterDisplay::~RasterDisplay()
{
close_file();
}
//
// 'RasterDisplay::close_file()' - Close an opened raster file.
//
int // O - 1 on success, 0 on failure
RasterDisplay::close_file()
{
if (ras_)
{
cupsRasterClose(ras_);
ras_ = NULL;
}
if (fp_)
{
gzclose(fp_);
fp_ = NULL;
}
if (filename_)
{
free((void *)filename_);
filename_ = NULL;
}
if (pixels_)
{
delete[] pixels_;
pixels_ = NULL;
alloc_pixels_ = 0;
}
if (colors_)
{
delete[] colors_;
colors_ = NULL;
alloc_colors_ = 0;
}
memset(&header_, 0, sizeof(header_));
return (1);
}
//
// 'RasterDisplay::draw()' - Draw the raster display widget.
//
void
RasterDisplay::draw()
{
int xoff, yoff; // Offset of image
int X, Y, W, H; // Interior of widget
#ifdef DEBUG
puts("RasterDisplay::draw()");
#endif // DEBUG
X = x() + Fl::box_dx(box());
Y = y() + Fl::box_dy(box());
W = w() - Fl::box_dw(box());
H = h() - Fl::box_dh(box());
if (factor_)
{
xscrollbar_.show();
yscrollbar_.show();
W -= SBWIDTH;
H -= SBWIDTH;
}
else
{
xscrollbar_.hide();
yscrollbar_.hide();
}
if (damage() & FL_DAMAGE_SCROLL)
fl_push_clip(X, Y, W, H);
if (factor_)
draw_box(box(), x(), y(), w() - SBWIDTH, h() - SBWIDTH, color());
else
draw_box();
if (damage() & FL_DAMAGE_SCROLL)
fl_pop_clip();
else if (factor_)
{
fl_color(FL_GRAY);
fl_rectf(x() + w() - SBWIDTH, y() + h() - SBWIDTH, SBWIDTH, SBWIDTH);
}
if (ras_ && pixels_ && header_.cupsWidth && header_.cupsHeight)
{
#ifdef DEBUG
printf(" pixels_=%p, cupsWidth=%d, cupsHeight=%d\n", pixels_,
header_.cupsWidth, header_.cupsHeight);
#endif // DEBUG
fl_push_clip(X, Y, W, H);
if (xsize_ <= W)
xoff = (W - xsize_) / 2;
else
xoff = 0;
if (ysize_ <= H)
yoff = (H - ysize_) / 2;
else
yoff = 0;
xoff += X;
yoff += Y;
xstep_ = header_.cupsWidth / xsize_;
xmod_ = header_.cupsWidth % xsize_;
#ifdef DEBUG
printf(" xoff=%d, yoff=%d, xsize_=%d, ysize_=%d, xstep_=%d, xmod_=%d\n",
xoff, yoff, xsize_, ysize_, xstep_, xmod_);
#endif // DEBUG
fl_draw_image(image_cb, this, xoff, yoff,
xsize_ > W ? W : xsize_,
ysize_ > H ? H : ysize_, bpp_);
fl_pop_clip();
}
draw_label(X, Y, W, H - 2 * labelsize());
if (factor_)
{
if (damage() & FL_DAMAGE_SCROLL)
{
update_child(xscrollbar_);
update_child(yscrollbar_);
}
else
{
draw_child(xscrollbar_);
draw_child(yscrollbar_);
}
}
}
//
// 'RasterDisplay::get_color()' - Return the original color value for a coordinate.
//
uchar * // O - Color values or NULL
RasterDisplay::get_color(int X, // I - X position in image
int Y) // I - Y position in image
{
if (!colors_ || X < 0 || X >= (int)header_.cupsWidth ||
Y < 0 || Y >= (int)header_.cupsHeight)
return (NULL);
else
return (colors_ + (Y * header_.cupsWidth + X) * bpc_);
}
//
// 'RasterDisplay::get_pixel()' - Return the displayed color value for a coordinate.
//
uchar * // O - RGB color value or NULL
RasterDisplay::get_pixel(int X, // I - X position in image
int Y) // I - Y position in image
{
if (!pixels_ || X < 0 || X >= (int)header_.cupsWidth ||
Y < 0 || Y >= (int)header_.cupsHeight)
return (NULL);
else
return (pixels_ + (Y * header_.cupsWidth + X) * bpp_);
}
//
// 'RasterDisplay::handle()' - Handle events in the widget.
//
int // O - 1 if handled, 0 otherwise
RasterDisplay::handle(int event) // I - Event to handle
{
if (header_.cupsWidth && header_.cupsHeight)
{
switch (event)
{
case FL_ENTER :
case FL_MOVE :
update_mouse_xy();
if ((!yscrollbar_.visible() || Fl::event_x() < yscrollbar_.x()) &&
(!xscrollbar_.visible() || Fl::event_y() < xscrollbar_.y()))
switch (mode_)
{
case RASTER_MODE_PAN :
fl_cursor(FL_CURSOR_MOVE);
break;
case RASTER_MODE_ZOOM_IN :
case RASTER_MODE_ZOOM_OUT :
fl_cursor(FL_CURSOR_DEFAULT);
break;
default :
case RASTER_MODE_CLICK :
fl_cursor(FL_CURSOR_CROSS);
break;
}
else
fl_cursor(FL_CURSOR_DEFAULT);
return (1);
case FL_LEAVE :
fl_cursor(FL_CURSOR_DEFAULT);
return (1);
case FL_SHORTCUT :
switch (Fl::event_key())
{
case '-' : // Zoom out
if (factor_)
scale(factor_ * 0.8f);
else
scale((float)xsize_ / (float)header_.cupsWidth * 0.8f);
return (1);
case '=' : // Zoom in
if (factor_)
scale(factor_ * 1.25f);
else
scale((float)xsize_ / (float)header_.cupsWidth * 1.25f);
return (1);
case '0' : // Fit
scale(0.0f);
return (1);
case '1' : // 100%
scale(1.0f);
return (1);
case '2' : // 200%
scale(2.0f);
return (1);
case '3' : // 300%
scale(3.0f);
return (1);
case '4' : // 400%
scale(4.0f);
return (1);
}
break;
case FL_PUSH :
if ((!yscrollbar_.visible() || Fl::event_x() < yscrollbar_.x()) &&
(!xscrollbar_.visible() || Fl::event_y() < xscrollbar_.y()))
{
update_mouse_xy();
last_x_ = Fl::event_x_root();
last_y_ = Fl::event_y_root();
start_x_ = mouse_x_;
start_y_ = mouse_y_;
start_ex_ = Fl::event_x();
start_ey_ = Fl::event_y();
if (mode_ == RASTER_MODE_CLICK)
do_callback();
return (1);
}
break;
case FL_DRAG :
switch (mode_)
{
case RASTER_MODE_PAN :
position(xscrollbar_.value() + last_x_ - Fl::event_x_root(),
yscrollbar_.value() + last_y_ - Fl::event_y_root());
break;
case RASTER_MODE_ZOOM_IN :
if ((Fl::event_x() < start_ex_ && Fl::event_y() < start_ey_) ||
(Fl::event_x() > start_ex_ && Fl::event_y() > start_ey_))
fl_cursor(FL_CURSOR_NWSE);
else
fl_cursor(FL_CURSOR_NESW);
window()->make_current();
fl_overlay_rect(start_ex_, start_ey_,
Fl::event_x() - start_ex_,
Fl::event_y() - start_ey_);
break;
case RASTER_MODE_CLICK :
do_callback();
break;
}
last_x_ = Fl::event_x_root();
last_y_ = Fl::event_y_root();
update_mouse_xy();
return (1);
case FL_RELEASE :
update_mouse_xy();
switch (mode_)
{
case RASTER_MODE_ZOOM_IN :
window()->make_current();
fl_cursor(FL_CURSOR_DEFAULT);
fl_overlay_clear();
if (Fl::event_button() == FL_LEFT_MOUSE)
{
int W, H;
W = w() - SBWIDTH - Fl::box_dw(box());
H = h() - SBWIDTH - Fl::box_dh(box());
if (abs(start_ex_ - Fl::event_x()) > 4 ||
abs(start_ey_ - Fl::event_y()) > 4)
{
// Zoom to box...
float xfactor, yfactor;
xfactor = (float)W / (float)abs(mouse_x_ - start_x_);
yfactor = (float)H / (float)abs(mouse_y_ - start_y_);
// printf("start_x_=%d, start_y_=%d, mouse_x_=%d, mouse_y_=%d\n",
// start_x_, start_y_, mouse_x_, mouse_y_);
// printf("W=%d, H=%d, dx=%d, dy=%d\n", W, H,
// abs(mouse_x_ - start_x_), abs(mouse_x_ - start_x_));
// printf("xfactor=%g, yfactor=%g\n", xfactor, yfactor);
scale(xfactor < yfactor ? xfactor : yfactor);
position((int)((mouse_x_ < start_x_ ? mouse_x_ : start_x_) * scale()),
(int)((mouse_y_ < start_y_ ? mouse_y_ : start_y_) * scale()));
}
else
{
if (factor_)
scale(factor_ * 1.25f);
else
scale((float)xsize_ / (float)header_.cupsWidth * 1.25f);
position((int)((mouse_x_ < start_x_ ? mouse_x_ : start_x_) * scale()) - W / 2,
(int)((mouse_y_ < start_y_ ? mouse_y_ : start_y_) * scale()) - H / 2);
}
break;
}
case RASTER_MODE_ZOOM_OUT :
if (factor_)
scale(factor_ * 0.8f);
else
scale((float)xsize_ / (float)header_.cupsWidth * 0.8f);
break;
case RASTER_MODE_CLICK :
do_callback();
break;
}
return (1);
case FL_ZOOM_GESTURE :
if (Fl::event_dy() < 0)
{
// Zoom out
if (factor_)
scale(factor_ * 0.875f);
else
scale((float)xsize_ / (float)header_.cupsWidth * 0.875f);
}
else
{
// Zoom in
// update_mouse_xy();
if (factor_)
scale(factor_ * 1.125f);
else
scale((float)xsize_ / (float)header_.cupsWidth * 1.125f);
int W, H;
W = w() - SBWIDTH - Fl::box_dw(box());
H = h() - SBWIDTH - Fl::box_dh(box());
position((int)(mouse_x_ * scale()) - W / 2,
(int)(mouse_y_ * scale()) - H / 2);
}
return (1);
}
}
return (Fl_Group::handle(event));
}
//
// 'RasterDisplay::image_cb()' - Provide a single line of an image.
//
void
RasterDisplay::image_cb(void *p, // I - Raster display widget
int X, // I - X offset
int Y, // I - Y offset
int W, // I - Width of image row
uchar *D) // O - Image data
{
RasterDisplay *display; // Display widget
const uchar *inptr; // Pointer into image
int bpp, // Bytes per pixel value
xerr, // Bresenheim values
xstep, // ...
xmod, // ...
xsize; // ...
display = (RasterDisplay *)p;
bpp = display->bpp_;
xstep = display->xstep_ * bpp;
xmod = display->xmod_;
xsize = display->xsize_;
xerr = (X * xmod) % xsize;
if (xsize > (display->w() - Fl::box_dw(display->box()) - SBWIDTH))
X = (X + display->xscrollbar_.value()) *
(display->header_.cupsWidth - 1) / (xsize - 1);
else
X = X * (display->header_.cupsWidth - 1) / (xsize - 1);
if (display->ysize_ > (display->h() - Fl::box_dh(display->box()) - SBWIDTH))
Y = (Y + display->yscrollbar_.value()) *
(display->header_.cupsHeight - 1) / (display->ysize_ - 1);
else
Y = Y * (display->header_.cupsHeight - 1) / (display->ysize_ - 1);
inptr = display->pixels_ + (Y * display->header_.cupsWidth + X) * bpp;
if (xstep == bpp && xmod == 0)
memcpy(D, inptr, (size_t)W * bpp);
else if (bpp == 1)
{
for (; W > 0; W --)
{
*D++ = *inptr;
inptr += xstep;
xerr += xmod;
if (xerr >= xsize)
{
xerr -= xsize;
inptr += bpp;
}
}
}
else
{
for (; W > 0; W --)
{
*D++ = inptr[0];
*D++ = inptr[1];
*D++ = inptr[2];
inptr += xstep;
xerr += xmod;
if (xerr >= xsize)
{
xerr -= xsize;
inptr += bpp;
}
}
}
}
//
// 'RasterDisplay::is_subtractive()' - Is the color space subtractive?
//
int
RasterDisplay::is_subtractive()
{
return ((header_.cupsColorSpace >= CUPS_CSPACE_K && header_.cupsColorSpace <= CUPS_CSPACE_SILVER) ||
(header_.cupsColorSpace >= CUPS_CSPACE_DEVICE1 && header_.cupsColorSpace <= CUPS_CSPACE_DEVICEF));
}
//
// 'RasterDisplay::load_colors()' - Load device colors.
//
void
RasterDisplay::load_colors()
{
int i; // Looping var
char key[256], // Key string
*value; // Value
unsigned c, m ,y; // Colors
if (!is_subtractive() || header_.cupsBitsPerColor < 8)
return;
if (!prefs)
prefs = new Fl_Preferences(Fl_Preferences::USER, "msweet.org", "rasterview");
for (i = 0; i < header_.cupsNumColors; i ++)
{
snprintf(key, sizeof(key), "cs%dc%d", header_.cupsColorSpace, i);
if (prefs->get(key, value, "") && sscanf(value, "%u %u %u", &c, &m, &y) == 3)
{
device_colors_[i][0] = c;
device_colors_[i][1] = m;
device_colors_[i][2] = y;
}
}
}
//
// 'RasterDisplay::load_page()' - Load the next page from a raster stream.
//
int // O - 1 on success, 0 on failure
RasterDisplay::load_page()
{
union
{
unsigned char bytes[sizeof(int)];
int integer;
} endian_test; // Endian test variable
if (!ras_ || page_ >= num_pages_)
return (0);
if (!cupsRasterReadHeader2(ras_, &header_))
{
int err;
fl_alert("Unable to read page header: %s", gzerror(fp_, &err));
return (0);
}
page_ ++;
if (header_.cupsColorOrder == CUPS_ORDER_PLANAR)
{
fl_alert("Sorry, RasterView doesn't support planar raster data at this time.");
return (0);
}
// Allocate memory for the page data...
#ifdef DEBUG
fprintf(stderr, "DEBUG: sizeof(cups_page_header_t) = %d\n", (int)sizeof(cups_page_header_t));
fprintf(stderr, "DEBUG: sizeof(cups_page_header2_t) = %d\n", (int)sizeof(cups_page_header2_t));
fprintf(stderr, "DEBUG: MediaClass = \"%s\"\n", header_.MediaClass);
fprintf(stderr, "DEBUG: MediaColor = \"%s\"\n", header_.MediaColor);
fprintf(stderr, "DEBUG: MediaType = \"%s\"\n", header_.MediaType);
fprintf(stderr, "DEBUG: OutputType = \"%s\"\n", header_.OutputType);
fprintf(stderr, "DEBUG: AdvanceDistance = %d(%x)\n", header_.AdvanceDistance,
header_.AdvanceDistance);
fprintf(stderr, "DEBUG: AdvanceMedia = %d(%x)\n", header_.AdvanceMedia,
header_.AdvanceMedia);
fprintf(stderr, "DEBUG: Collate = %d(%x)\n", header_.Collate,
header_.Collate);
fprintf(stderr, "DEBUG: CutMedia = %d(%x)\n", header_.CutMedia,
header_.CutMedia);
fprintf(stderr, "DEBUG: Duplex = %d(%x)\n", header_.Duplex, header_.Duplex);
fprintf(stderr, "DEBUG: HWResolution = [ %d(%x) %d(%x) ]\n",
header_.HWResolution[0], header_.HWResolution[0],
header_.HWResolution[1], header_.HWResolution[1]);
fprintf(stderr,
"DEBUG: ImagingBoundingBox = [ %d(%x) %d(%x) %d(%x) %d(%x) ]\n",
header_.ImagingBoundingBox[0], header_.ImagingBoundingBox[0],
header_.ImagingBoundingBox[1], header_.ImagingBoundingBox[1],
header_.ImagingBoundingBox[2], header_.ImagingBoundingBox[2],
header_.ImagingBoundingBox[3], header_.ImagingBoundingBox[3]);
fprintf(stderr, "DEBUG: InsertSheet = %d(%x)\n", header_.InsertSheet,
header_.InsertSheet);
fprintf(stderr, "DEBUG: Jog = %d(%x)\n", header_.Jog, header_.Jog);
fprintf(stderr, "DEBUG: LeadingEdge = %d(%x)\n", header_.LeadingEdge,
header_.LeadingEdge);
fprintf(stderr, "DEBUG: Margins = [ %d(%x) %d(%x) ]\n",
header_.Margins[0], header_.Margins[0],
header_.Margins[1], header_.Margins[1]);
fprintf(stderr, "DEBUG: ManualFeed = %d(%x)\n", header_.ManualFeed,
header_.ManualFeed);
fprintf(stderr, "DEBUG: MediaPosition = %d(%x)\n", header_.MediaPosition,
header_.MediaPosition);
fprintf(stderr, "DEBUG: MediaWeight = %d(%x)\n", header_.MediaWeight,
header_.MediaWeight);
fprintf(stderr, "DEBUG: MirrorPrint = %d(%x)\n", header_.MirrorPrint,
header_.MirrorPrint);
fprintf(stderr, "DEBUG: NegativePrint = %d(%x)\n", header_.NegativePrint,
header_.NegativePrint);
fprintf(stderr, "DEBUG: NumCopies = %d(%x)\n", header_.NumCopies,
header_.NumCopies);
fprintf(stderr, "DEBUG: Orientation = %d(%x)\n", header_.Orientation,
header_.Orientation);
fprintf(stderr, "DEBUG: OutputFaceUp = %d(%x)\n", header_.OutputFaceUp,
header_.OutputFaceUp);
fprintf(stderr, "DEBUG: PageSize = [ %d(%x) %d(%x) ]\n",
header_.PageSize[0], header_.PageSize[0],
header_.PageSize[1], header_.PageSize[1]);
fprintf(stderr, "DEBUG: Separations = %d(%x)\n", header_.Separations,
header_.Separations);
fprintf(stderr, "DEBUG: TraySwitch = %d(%x)\n", header_.TraySwitch,
header_.TraySwitch);
fprintf(stderr, "DEBUG: Tumble = %d(%x)\n", header_.Tumble, header_.Tumble);
fprintf(stderr, "DEBUG: cupsWidth = %d(%x)\n", header_.cupsWidth,
header_.cupsWidth);
fprintf(stderr, "DEBUG: cupsHeight = %d(%x)\n", header_.cupsHeight,
header_.cupsHeight);
fprintf(stderr, "DEBUG: cupsMediaType = %d(%x)\n", header_.cupsMediaType,
header_.cupsMediaType);
fprintf(stderr, "DEBUG: cupsBitsPerColor = %d(%x)\n",
header_.cupsBitsPerColor, header_.cupsBitsPerColor);
fprintf(stderr, "DEBUG: cupsBitsPerPixel = %d(%x)\n",
header_.cupsBitsPerPixel, header_.cupsBitsPerPixel);
fprintf(stderr, "DEBUG: cupsBytesPerLine = %d(%x)\n",
header_.cupsBytesPerLine, header_.cupsBytesPerLine);
fprintf(stderr, "DEBUG: cupsColorOrder = %d(%x)\n", header_.cupsColorOrder,
header_.cupsColorOrder);
fprintf(stderr, "DEBUG: cupsColorSpace = %d(%x)\n", header_.cupsColorSpace,
header_.cupsColorSpace);
fprintf(stderr, "DEBUG: cupsCompression = %d(%x)\n", header_.cupsCompression,
header_.cupsCompression);
fprintf(stderr, "DEBUG: cupsNumColors = %d(%x)\n", header_.cupsNumColors,
header_.cupsNumColors);
#endif // DEBUG
bpp_ = ((header_.cupsBitsPerColor < 8 || !is_subtractive()) && header_.cupsNumColors == 1) ? 1 : 3;
if (header_.cupsWidth == 0 || header_.cupsWidth > 1000000 || header_.cupsHeight == 0 || header_.cupsHeight > 1000000)
{
fl_alert("Sorry, image dimensions are out of range (%ux%u).", header_.cupsWidth, header_.cupsHeight);
return (0);
}
long pixelsize = (long)header_.cupsWidth * bpp_;
long bytes = pixelsize * header_.cupsHeight;
if (bytes >= INT_MAX)
{
fl_alert("Sorry, image is too large to display (%ux%ux%u >= 2GB).", header_.cupsWidth, header_.cupsHeight, header_.cupsBitsPerPixel);
return (0);
}
if (bytes > alloc_pixels_)
{
if (pixels_)
delete[] pixels_;
pixels_ = new uchar[bytes];
alloc_pixels_ = bytes;
if (!pixels_)
{
fl_alert("Unable to allocate %ld bytes for page data.", bytes);
return (0);
}
}
bpc_ = (header_.cupsBitsPerPixel + 7) / 8;
if (header_.cupsColorOrder != CUPS_ORDER_CHUNKED)
bpc_ *= header_.cupsNumColors;
long colorsize = (long)header_.cupsWidth * bpc_;
bytes = colorsize * header_.cupsHeight;
if (bytes > alloc_colors_)
{
if (colors_)
delete[] colors_;
colors_ = new uchar[bytes];
alloc_colors_ = bytes;
if (!colors_)
{
fl_alert("Unable to allocate %ld bytes for page data.", bytes);
return (0);
}
}
// Update the page dimensions/scaling...
resize(x(), y(), w(), h());
memset(colors_, 0, alloc_colors_);
memset(pixels_, 255, alloc_pixels_);
uchar *line = new uchar[header_.cupsBytesPerLine];
if (!line)
{
fl_alert("Unable to allocate %d bytes for raster data.", header_.cupsBytesPerLine);
return (0);
}
// See what word order we need to use...
if (endian_offset < 0)
{
memset(&endian_test, 0, sizeof(endian_test));
endian_test.bytes[sizeof(endian_test.bytes) - 1] = 1;
if (endian_test.integer == 1)
endian_offset = 0; // Big endian
else
endian_offset = 1; // Little endian
}
// Set device colors...
memset(device_colors_, 255, sizeof(device_colors_));
switch (header_.cupsColorSpace)
{
case CUPS_CSPACE_DEVICE3 :
case CUPS_CSPACE_DEVICE4 :
case CUPS_CSPACE_CMY :
case CUPS_CSPACE_CMYK :
device_colors_[0][1] = device_colors_[0][2] = 0;
device_colors_[1][0] = device_colors_[1][2] = 0;
device_colors_[2][0] = device_colors_[2][1] = 0;
break;
case CUPS_CSPACE_YMC :
case CUPS_CSPACE_YMCK :
device_colors_[0][0] = device_colors_[0][1] = 0;
device_colors_[1][0] = device_colors_[1][2] = 0;
device_colors_[2][1] = device_colors_[2][2] = 0;
break;
case CUPS_CSPACE_DEVICE6 :
device_colors_[0][1] = device_colors_[0][2] = 0;
device_colors_[1][0] = device_colors_[1][2] = 0;
device_colors_[2][0] = device_colors_[2][1] = 0;
device_colors_[4][0] = 127; device_colors_[4][1] = device_colors_[4][2] = 0;
device_colors_[5][1] = 127; device_colors_[5][0] = device_colors_[5][2] = 0;
break;
case CUPS_CSPACE_W :
case CUPS_CSPACE_SW :
device_colors_[0][0] = device_colors_[0][1] = device_colors_[0][2] = 0;
break;
case CUPS_CSPACE_RGB :
case CUPS_CSPACE_SRGB :
case CUPS_CSPACE_ADOBERGB :
device_colors_[0][0] = 0;
device_colors_[1][1] = 0;
device_colors_[2][2] = 0;
break;
default :
break;
}
load_colors();
// Read the raster data...
uchar *pptr, // Pointer into pixels_
*cptr; // Pointer into colors_
int py; // Current position in page
for (py = header_.cupsHeight, cptr = colors_, pptr = pixels_;
py > 0;
py --, cptr += colorsize, pptr += pixelsize)
{
if ((py % header_.HWResolution[1]) == 0)
{
// Update the screen to show progress...
redraw();
Fl::check();
}
if (!cupsRasterReadPixels(ras_, line, header_.cupsBytesPerLine))
{
fl_alert("Unable to read page data: %s", strerror(errno));
delete[] line;
return (0);
}
switch (header_.cupsColorSpace)
{
case CUPS_CSPACE_DEVICE1 :
case CUPS_CSPACE_DEVICE2 :
case CUPS_CSPACE_DEVICE3 :
case CUPS_CSPACE_DEVICE4 :
case CUPS_CSPACE_DEVICE5 :
case CUPS_CSPACE_DEVICE6 :
case CUPS_CSPACE_DEVICE7 :
case CUPS_CSPACE_DEVICE8 :
case CUPS_CSPACE_DEVICE9 :
case CUPS_CSPACE_DEVICEA :
case CUPS_CSPACE_DEVICEB :
case CUPS_CSPACE_DEVICEC :
case CUPS_CSPACE_DEVICED :
case CUPS_CSPACE_DEVICEE :
case CUPS_CSPACE_DEVICEF :
convert_device(&header_, line, cptr, pptr, device_colors_);
break;
case CUPS_CSPACE_W :
case CUPS_CSPACE_SW :
convert_w(&header_, line, cptr, pptr);
break;
case CUPS_CSPACE_RGB :
case CUPS_CSPACE_SRGB :
case CUPS_CSPACE_ADOBERGB :
convert_rgb(&header_, line, cptr, pptr);
break;
case CUPS_CSPACE_RGBA :
convert_rgba(&header_, py, line, cptr, pptr);
break;
case CUPS_CSPACE_RGBW :
convert_rgbw(&header_, line, cptr, pptr);
break;
case CUPS_CSPACE_K :
case CUPS_CSPACE_WHITE :
case CUPS_CSPACE_GOLD :
case CUPS_CSPACE_SILVER :
if (header_.cupsBitsPerColor >= 8)
convert_device(&header_, line, cptr, pptr, device_colors_);
else
convert_k(&header_, line, cptr, pptr);
break;
case CUPS_CSPACE_CMY :
if (header_.cupsBitsPerColor >= 8)
convert_device(&header_, line, cptr, pptr, device_colors_);
else
convert_cmy(&header_, line, cptr, pptr);
break;
case CUPS_CSPACE_YMC :
if (header_.cupsBitsPerColor >= 8)
convert_device(&header_, line, cptr, pptr, device_colors_);
else
convert_ymc(&header_, line, cptr, pptr);
break;
case CUPS_CSPACE_KCMYcm :
if (header_.cupsBitsPerColor == 1)
{
convert_kcmycm(&header_, line, cptr, pptr);
break;
}
case CUPS_CSPACE_KCMY :
if (header_.cupsBitsPerColor >= 8)
convert_device(&header_, line, cptr, pptr, device_colors_);
else
convert_kcmy(&header_, line, cptr, pptr);
break;
case CUPS_CSPACE_CMYK :
if (header_.cupsBitsPerColor >= 8)
convert_device(&header_, line, cptr, pptr, device_colors_);
else
convert_cmyk(&header_, line, cptr, pptr);
break;
case CUPS_CSPACE_YMCK :
case CUPS_CSPACE_GMCK :
case CUPS_CSPACE_GMCS :
if (header_.cupsBitsPerColor >= 8)
convert_device(&header_, line, cptr, pptr, device_colors_);
else
convert_ymck(&header_, line, cptr, pptr);
break;
case CUPS_CSPACE_CIEXYZ :
convert_xyz(&header_, line, cptr, pptr);
break;
case CUPS_CSPACE_CIELab :
case CUPS_CSPACE_ICC1 :
case CUPS_CSPACE_ICC2 :
case CUPS_CSPACE_ICC3 :
case CUPS_CSPACE_ICC4 :
case CUPS_CSPACE_ICC5 :
case CUPS_CSPACE_ICC6 :
case CUPS_CSPACE_ICC7 :
case CUPS_CSPACE_ICC8 :
case CUPS_CSPACE_ICC9 :
case CUPS_CSPACE_ICCA :
case CUPS_CSPACE_ICCB :
case CUPS_CSPACE_ICCC :
case CUPS_CSPACE_ICCD :
case CUPS_CSPACE_ICCE :
case CUPS_CSPACE_ICCF :
convert_lab(&header_, line, cptr, pptr);
break;
}
}
delete[] line;
// Mark the page for redisplay...
redraw();
// Return successfully...
return (1);
}
//
// 'RasterDisplay::open_file()' - Open a raster file for viewing.
//
int // O - 1 on success, 0 on failure
RasterDisplay::open_file(
const char *filename) // I - File to open
{
cups_page_header2_t header; // Page header
uchar *buffer = NULL; // Line buffer
unsigned bufsize = 0; // Size of line buffer
unsigned y; // Current line
close_file();
if ((fp_ = gzopen(filename, "r")) == NULL)
{
fl_alert("Unable to open file: %s", strerror(errno));
return (0);
}
if ((ras_ = cupsRasterOpenIO((cups_raster_iocb_t)raster_cb, fp_, CUPS_RASTER_READ)) == NULL)
{
fl_alert("Unable to read raster file header.");
gzclose(fp_);
fp_ = NULL;
return (0);
}
filename_ = strdup(filename);
// Figure out the number of pages and their offsets...
num_pages_ = 0;
pages_[0] = gztell(fp_);
while (cupsRasterReadHeader2(ras_, &header))
{
num_pages_ ++;
#ifdef DEBUG
fprintf(stderr, "PAGE %d: %ux%ux%u @ %ld\n", num_pages_, header.cupsWidth, header.cupsHeight, header.cupsBitsPerPixel, (long)pages_[num_pages_ - 1]);
#endif // DEBUG
if (header.cupsBytesPerLine > bufsize)
{
bufsize = header.cupsBytesPerLine;
buffer = (uchar *)realloc(buffer, bufsize);
}
for (y = header.cupsHeight; y > 0; y --)
cupsRasterReadPixels(ras_, buffer, header.cupsBytesPerLine);
if (num_pages_ >= RASTER_MAX_PAGES)
break;
pages_[num_pages_] = gztell(fp_) - rasterOffset(ras_);
}
gzseek(fp_, pages_[0], SEEK_SET);
rasterReset(ras_);
page_ = 0;
return (load_page());
}
//
// 'RasterDisplay::page()' - Return the current page number.
//
int // O - Current page
RasterDisplay::page(void)
{
return (page_);
}
/*
* 'RasterDisplay::page()' - Set the current page number.
*/
void
RasterDisplay::page(int number) // I - New page
{
if (number < 1)
number = 1;
else if (number > num_pages_)
number = num_pages_;
if (number == (page_ + 1))
this->load_page();
else if (number != page_)
{
gzseek(fp_, pages_[number - 1], SEEK_SET);
rasterReset(ras_);
page_ = number - 1;
this->load_page();
}
}
//
// 'RasterDisplay::position()' - Reposition the image on the screen.
//
void
RasterDisplay::position(int X, // I - New X offset
int Y) // I - New Y offset
{
int W, H; // Interior size
W = w() - SBWIDTH;
H = h() - SBWIDTH;
if (X < 0)
X = 0;
else if (X > (xsize_ - W))
X = xsize_ - W;
if (Y < 0)
Y = 0;
else if (Y > (ysize_ - H))
Y = ysize_ - H;
xscrollbar_.value(X, W, 0, xsize_);
yscrollbar_.value(Y, H, 0, ysize_);
damage(FL_DAMAGE_SCROLL);
}
//
// 'RasterDisplay::resize()' - Resize the raster display widget.
//
void
RasterDisplay::resize(int X, // I - New X position
int Y, // I - New Y position
int W, // I - New width
int H) // I - New height
{
Fl_Widget::resize(X, Y, W, H);
xscrollbar_.resize(X, Y + H - SBWIDTH, W - SBWIDTH, SBWIDTH);
yscrollbar_.resize(X + W - SBWIDTH, Y, SBWIDTH, H - SBWIDTH);
W -= Fl::box_dw(box()) + SBWIDTH;
H -= Fl::box_dh(box()) + SBWIDTH;
if (factor_ == 0.0f && header_.cupsWidth && header_.cupsHeight)
{
xsize_ = W;
if (xsize_ > (int)(header_.cupsWidth * 4))
xsize_ = header_.cupsWidth * 4;
ysize_ = xsize_ * header_.cupsHeight / header_.cupsWidth;
if (ysize_ > H)
{
ysize_ = H;
if (ysize_ > (int)(header_.cupsHeight * 4))
ysize_ = header_.cupsHeight * 4;
xsize_ = ysize_ * header_.cupsWidth / header_.cupsHeight;
}
}
update_scrollbars();
redraw();
}
//
// 'RasterDisplay::save_colors()' - Save device colors.
//
void
RasterDisplay::save_colors()
{
int i; // Looping var
char key[256], // Key string
value[256]; // Value
if (!is_subtractive() || header_.cupsBitsPerColor < 8)
return;
if (!prefs)
prefs = new Fl_Preferences(Fl_Preferences::USER, "msweet.org", "rasterview");
for (i = 0; i < header_.cupsNumColors; i ++)
{
snprintf(key, sizeof(key), "cs%dc%d", header_.cupsColorSpace, i);
snprintf(value, sizeof(value), "%d %d %d", device_colors_[i][0], device_colors_[i][1], device_colors_[i][2]);
prefs->set(key, value);
}
prefs->flush();
}
//
// 'RasterDisplay::scale()' - Scale the image.
//
void
RasterDisplay::scale(float factor) // I - Scaling factor (0 = auto)
{
int X, Y, W, H; // Interior of widget
float ratio; // Scaling ratio
if (factor > 10.0f)
factor = 10.0f;
// Make sure that the image doesn't get scaled to nothin'...
if (header_.cupsWidth && header_.cupsHeight)
{
if (factor > 0.0f && (header_.cupsWidth * factor) < 32.0f && header_.cupsWidth > 32)
factor = 32.0f / header_.cupsWidth;
if (factor > 0.0f && (header_.cupsHeight * factor) < 32.0f && header_.cupsHeight > 32)
factor = 32.0f / header_.cupsHeight;
}
if (factor_ == 0.0f)
ratio = 0.0f;
else
ratio = factor / factor_;
factor_ = factor;
redraw();
if (!header_.cupsWidth || !header_.cupsHeight)
return;
W = w() - SBWIDTH - Fl::box_dw(box());
H = h() - SBWIDTH - Fl::box_dh(box());
if (factor_ == 0.0f)
{
xsize_ = W;
if (xsize_ > (int)(header_.cupsWidth * 4))
xsize_ = header_.cupsWidth * 4;
ysize_ = xsize_ * header_.cupsHeight / header_.cupsWidth;
if (ysize_ > H)
{
ysize_ = H;
if (ysize_ > (int)(header_.cupsHeight * 4))
ysize_ = header_.cupsHeight * 4;
xsize_ = ysize_ * header_.cupsWidth / header_.cupsHeight;
}
X = 0;
Y = 0;
}
else
{
xsize_ = (int)((float)header_.cupsWidth * factor_ + 0.5f);
ysize_ = (int)((float)header_.cupsHeight * factor_ + 0.5f);
if (xsize_ <= W)
{
// The image will be centered...
X = 0;
}
else if (ratio == 0.0)
{
// Previous zoom was auto-fit, center it...
X = (xsize_ - W) / 2;
}
else
{
// Try to center on the previous location...
X = (int)((xscrollbar_.value() + W / 2) * ratio) - W / 2;
}
if (ysize_ <= H)
{
// The image will be centered...
Y = 0;
}
else if (ratio == 0.0)
{
// Previous zoom was auto-fit, center it...
Y = (ysize_ - H) / 2;
}
else
{
// Try to center on the previous location...
Y = (int)((yscrollbar_.value() + H / 2) * ratio) - H / 2;
}
}
// Update the scrollbars...
if (X < 0)
X = 0;
else if (X > (xsize_ - W))
X = xsize_ - W;
xscrollbar_.value(X, W, 0, xsize_);
if (xsize_ <= W)
xscrollbar_.deactivate();
else
xscrollbar_.activate();
if (Y < 0)
Y = 0;
else if (Y > (ysize_ - H))
Y = ysize_ - H;
yscrollbar_.value(Y, H, 0, ysize_);
if (ysize_ <= H)
yscrollbar_.deactivate();
else
yscrollbar_.activate();
}
//
// 'RasterDisplay::scrollbar_cb()' - Update the display based on the scrollbar position.
//
void
RasterDisplay::scrollbar_cb(
Fl_Widget *w, // I - Widget
void *d) // I - Raster display widget
{
RasterDisplay *img = (RasterDisplay *)d;
img->damage(FL_DAMAGE_SCROLL);
}
//
// 'RasterDisplay::update_mouse_xy()' - Update the mouse X and Y values.
//
void
RasterDisplay::update_mouse_xy()
{
int X, Y; // X,Y position
int W, H; // Width and height
X = Fl::event_x() - x() - Fl::box_dx(box());
Y = Fl::event_y() - y() - Fl::box_dy(box());
W = w() - SBWIDTH - Fl::box_dw(box());
H = h() - SBWIDTH - Fl::box_dh(box());
if (!ras_ || xsize_ <= 0 || ysize_ <= 0)
{
mouse_x_ = -1;
mouse_y_ = -1;
}
if (xsize_ < W)
{
X -= (W - xsize_) / 2;
if (X < 0)
mouse_x_ = 0;
else if (X >= xsize_)
mouse_x_ = header_.cupsWidth;
else
mouse_x_ = X * header_.cupsWidth / xsize_;
}
else
mouse_x_ = (xscrollbar_.value() + X) * header_.cupsWidth / xsize_;
if (ysize_ < H)
{
Y -= (H - ysize_) / 2;
if (Y < 0)
mouse_y_ = 0;
else if (Y >= ysize_)
mouse_y_ = header_.cupsHeight;
else
mouse_y_ = Y * header_.cupsHeight / ysize_;
}
else
mouse_y_ = (yscrollbar_.value() + Y) * header_.cupsHeight / ysize_;
if (mouse_x_ < 0)
mouse_x_ = 0;
else if (mouse_x_ > (int)header_.cupsWidth)
mouse_x_ = header_.cupsWidth;
if (mouse_y_ < 0)
mouse_y_ = 0;
else if (mouse_y_ > (int)header_.cupsHeight)
mouse_y_ = header_.cupsHeight;
// printf("xscrollbar_=%d, yscrollbar_=%d\n", xscrollbar_.value(),
// yscrollbar_.value());
// printf("mouse_x_=%d, mouse_y_=%d\n", mouse_x_, mouse_y_);
}
//
// 'RasterDisplay::update_scrollbars()' - Update the scrollbars.
//
void
RasterDisplay::update_scrollbars()
{
int X, Y; // X/Y offsets
int W, H; // Interior size
if (header_.cupsWidth && header_.cupsHeight)
{
W = w() - SBWIDTH - Fl::box_dw(box());
H = h() - SBWIDTH - Fl::box_dh(box());
X = xscrollbar_.value();
if (X > (xsize_ - W))
X = xsize_ - W;
else if (X < 0)
X = 0;
xscrollbar_.value(X, W, 0, xsize_);
if (xsize_ <= W)
xscrollbar_.deactivate();
else
xscrollbar_.activate();
Y = yscrollbar_.value();
if (Y > (ysize_ - H))
Y = ysize_ - H;
else if (Y < 0)
Y = 0;
yscrollbar_.value(Y, H, 0, ysize_);
if (ysize_ <= H)
yscrollbar_.deactivate();
else
yscrollbar_.activate();
}
else
{
xscrollbar_.value(0, 1, 0, 1);
yscrollbar_.value(0, 1, 0, 1);
}
}
//
// 'convert_cmy()' - Convert CMY or YMC raster data.
//
static void
convert_cmy(
cups_page_header2_t *header, // I - Raster header */
uchar *line, // I - Raster line
uchar *colors, // O - Original pixels
uchar *pixels) // O - RGB pixels
{
int x, // X position in line
w, // Width of line
val; // Pixel value
uchar *cptr, // Cyan pointer
*mptr, // Magenta pointer
*yptr, // Yellow pointer
bit; // Current bit
w = header->cupsWidth;
if (header->cupsColorOrder == CUPS_ORDER_CHUNKED)
{
// Chunky
switch (header->cupsBitsPerColor)
{
case 1 :
for (x = w; x > 0; x -= 2, pixels += 6)
{
bit = *line++;
*colors++ = bit >> 4;
if (bit & 0x40)
pixels[0] = 0;
if (bit & 0x20)
pixels[1] = 0;
if (bit & 0x10)
pixels[2] = 0;
if (x > 1)
{
*colors++ = bit & 15;
if (bit & 0x04)
pixels[3] = 0;
if (bit & 0x02)
pixels[4] = 0;
if (bit & 0x01)
pixels[5] = 0;
}
}
break;
case 2 :
for (x = w; x > 0; x --)
{
bit = *line++;
*colors++ = bit;
*pixels++ = 255 - 85 * ((bit & 0x30) >> 4);
*pixels++ = 255 - 85 * ((bit & 0x0c) >> 2);
*pixels++ = 255 - 85 * (bit & 0x03);
}
break;
case 4 :
for (x = w; x > 0; x --)
{
*colors++ = bit = *line++;
*pixels++ = 255 - 17 * (bit & 0x0f);
*colors++ = bit = *line++;
*pixels++ = 255 - 17 * ((bit & 0xf0) >> 4);
*pixels++ = 255 - 17 * (bit & 0x0f);
}
break;
case 8 :
for (x = w; x > 0; x --)
{
*colors++ = val = *line++;
*pixels++ = 255 - val;
*colors++ = val = *line++;
*pixels++ = 255 - val;
*colors++ = val = *line++;
*pixels++ = 255 - val;
}
break;
case 16 :
if (endian_offset)
{
for (x = w; x > 0; x --)
{
*colors++ = *line++;
*colors++ = val = *line++;
*pixels++ = 255 - val;
*colors++ = *line++;
*colors++ = val = *line++;
*pixels++ = 255 - val;
*colors++ = *line++;
*colors++ = val = *line++;
*pixels++ = 255 - val;
}
}
else
{
for (x = w; x > 0; x --)
{
*colors++ = val = *line++;
*pixels++ = 255 - val;
*colors++ = *line++;
*colors++ = val = *line++;
*pixels++ = 255 - val;
*colors++ = *line++;
*colors++ = val = *line++;
*pixels++ = 255 - val;
*colors++ = *line++;
}
}
break;
}
}
else
{
// Banded
int bytespercolor = (header->cupsBitsPerColor * header->cupsWidth + 7) / 8;
cptr = line;
mptr = line + bytespercolor;
yptr = line + 2 * bytespercolor;
switch (header->cupsBitsPerColor)
{
case 1 :
for (x = w, bit = 0x80; x > 0; x --, pixels += 3)
{
if (*cptr & bit)
{
*colors++ = 1;
pixels[0] = 0;
}
else
colors ++;
if (*mptr & bit)
{
*colors++ = 1;
pixels[1] = 0;
}
else
colors ++;
if (*yptr & bit)
{
*colors++ = 1;
pixels[2] = 0;
}
else
colors ++;
if (bit > 1)
bit >>= 1;
else
{
bit = 0x80;
cptr ++;
mptr ++;
yptr ++;
}
}
break;
case 2 :
for (x = 0; x < w; x ++)
{
switch (x & 3)
{
case 0 :
*colors++ = val = (*cptr & 0xc0) >> 6;
*pixels++ = 255 - 85 * val;
*colors++ = val = (*mptr & 0xc0) >> 6;
*pixels++ = 255 - 85 * val;
*colors++ = val = (*yptr & 0xc0) >> 6;
*pixels++ = 255 - 85 * val;
break;
case 1 :
*colors++ = val = (*cptr & 0x30) >> 4;
*pixels++ = 255 - 85 * val;
*colors++ = val = (*mptr & 0x30) >> 4;
*pixels++ = 255 - 85 * val;
*colors++ = val = (*yptr & 0x30) >> 4;
*pixels++ = 255 - 85 * val;
break;
case 2 :
*colors++ = val = (*cptr & 0x0c) >> 2;
*pixels++ = 255 - 85 * val;
*colors++ = val = (*mptr & 0x0c) >> 2;
*pixels++ = 255 - 85 * val;
*colors++ = val = (*yptr & 0x0c) >> 2;
*pixels++ = 255 - 85 * val;
break;
case 3 :
*colors++ = val = *cptr & 0x03;
*pixels++ = 255 - 85 * val;
*colors++ = val = *mptr & 0x03;
*pixels++ = 255 - 85 * val;
*colors++ = val = *yptr & 0x03;
*pixels++ = 255 - 85 * val;
cptr ++;
mptr ++;
yptr ++;
break;
}
}
break;
case 4 :
for (x = 0; x < w; x ++)
{
switch (x & 1)
{
case 0 :
*colors++ = val = (*cptr & 0xf0) >> 4;
*pixels++ = 255 - 17 * val;
*colors++ = val = (*mptr & 0xf0) >> 4;
*pixels++ = 255 - 17 * val;
*colors++ = val = (*yptr & 0xf0) >> 4;
*pixels++ = 255 - 17 * val;
break;
case 1 :
*colors++ = val = *cptr & 0x0f;
*pixels++ = 255 - 17 * val;
*colors++ = val = *mptr & 0x0f;
*pixels++ = 255 - 17 * val;
*colors++ = val = *yptr & 0x0f;
*pixels++ = 255 - 17 * val;
cptr ++;
mptr ++;
yptr ++;
break;
}
}
break;
case 8 :
for (x = w; x > 0; x --)
{
*colors++ = val = *cptr++;
*pixels++ = 255 - val;
*colors++ = val = *mptr++;
*pixels++ = 255 - val;
*colors++ = val = *yptr++;
*pixels++ = 255 - val;
}
break;
case 16 :
if (endian_offset)
{
for (x = w; x > 0; x --)
{
*colors++ = *cptr++;
*colors++ = val = *cptr++;
*pixels++ = 255 - val;
*colors++ = *mptr++;
*colors++ = val = *mptr++;
*pixels++ = 255 - val;
*colors++ = *yptr++;
*colors++ = val = *yptr++;
*pixels++ = 255 - val;
}
}
else
{
for (x = w; x > 0; x --)
{
*colors++ = val = *cptr++;
*pixels++ = 255 - val;
*colors++ = *cptr++;
*colors++ = val = *mptr++;
*pixels++ = 255 - val;
*colors++ = *mptr++;
*colors++ = val = *yptr++;
*pixels++ = 255 - val;
*colors++ = *yptr++;
}
}
break;
}
}
}
//
// 'convert_cmyk()' - Convert CMYK raster data.
//
static void
convert_cmyk(
cups_page_header2_t *header, // I - Raster header */
uchar *line, // I - Raster line
uchar *colors, // O - Original pixels
uchar *pixels) // O - RGB pixels
{
int x, // X position in line
w, // Width of line
val; // Pixel value
uchar *cptr, // Cyan pointer
*mptr, // Magenta pointer
*yptr, // Yellow pointer
*kptr, // Black pointer
bit; // Current bit
int r, g, b, k; // Current RGB color + K
w = header->cupsWidth;
if (header->cupsColorOrder == CUPS_ORDER_CHUNKED)
{
// Chunky
switch (header->cupsBitsPerColor)
{
case 1 :
for (x = w; x > 0; x -= 2, pixels += 6)
{
bit = *line++;
*colors++ = bit >> 4;
if (bit & 0x10)
{
pixels[0] = 0;
pixels[1] = 0;
pixels[2] = 0;
}
else
{
if (bit & 0x80)
pixels[0] = 0;
if (bit & 0x40)
pixels[1] = 0;
if (bit & 0x20)
pixels[2] = 0;
}
if (x > 1)
{
*colors++ = bit & 0x0f;
if (bit & 0x01)
{
pixels[3] = 0;
pixels[4] = 0;
pixels[5] = 0;
}
else
{
if (bit & 0x08)
pixels[3] = 0;
if (bit & 0x04)
pixels[4] = 0;
if (bit & 0x02)
pixels[5] = 0;
}
}
}
break;
case 2 :
for (x = w; x > 0; x --)
{
*colors++ = bit = *line++;
k = 85 * (bit & 0x03);
r = 255 - 85 * ((bit & 0xc0) >> 6) - k;
g = 255 - 85 * ((bit & 0x30) >> 4) - k;
b = 255 - 85 * ((bit & 0x0c) >> 2) - k;
if (r <= 0)
*pixels++ = 0;
else
*pixels++ = r;
if (g <= 0)
*pixels++ = 0;
else
*pixels++ = g;
if (b <= 0)
*pixels++ = 0;
else
*pixels++ = b;
}
break;
case 4 :
for (x = w; x > 0; x --)
{
*colors++ = bit = *line++;
r = 255 - 17 * ((bit & 0xf0) >> 4);
g = 255 - 17 * (bit & 0x0f);
*colors++ = bit = *line++;
b = 255 - 17 * ((bit & 0xf0) >> 4);
k = 17 * (bit & 0x0f);
r -= k;
g -= k;
b -= k;
if (r <= 0)
*pixels++ = 0;
else
*pixels++ = r;
if (g <= 0)
*pixels++ = 0;
else
*pixels++ = g;
if (b <= 0)
*pixels++ = 0;
else
*pixels++ = b;
}
break;
case 8 :
for (x = w; x > 0; x --)
{
*colors++ = val = *line++;
r = 255 - val;
*colors++ = val = *line++;
g = 255 - val;
*colors++ = val = *line++;
b = 255 - val;
*colors++ = k = *line++;
r -= k;
g -= k;
b -= k;
if (r <= 0)
*pixels++ = 0;
else
*pixels++ = r;
if (g <= 0)
*pixels++ = 0;
else
*pixels++ = g;
if (b <= 0)
*pixels++ = 0;
else
*pixels++ = b;
}
break;
case 16 :
for (x = w; x > 0; x --)
{
if (endian_offset)
{
*colors++ = *line++;
*colors++ = val = *line++;
r = 255 - val;
*colors++ = *line++;
*colors++ = val = *line++;
g = 255 - val;
*colors++ = *line++;
*colors++ = val = *line++;
b = 255 - val;
*colors++ = *line++;
*colors++ = k = *line++;
}
else
{
*colors++ = val = *line++;
r = 255 - val;
*colors++ = *line++;
*colors++ = val = *line++;
g = 255 - val;
*colors++ = *line++;
*colors++ = val = *line++;
b = 255 - val;
*colors++ = *line++;
*colors++ = k = *line++;
*colors++ = *line++;
}
r -= k;
g -= k;
b -= k;
if (r <= 0)
*pixels++ = 0;
else
*pixels++ = r;
if (g <= 0)
*pixels++ = 0;
else
*pixels++ = g;
if (b <= 0)
*pixels++ = 0;
else
*pixels++ = b;
}
break;
}
}
else
{
// Banded
int bytespercolor = (header->cupsBitsPerColor * header->cupsWidth + 7) / 8;
cptr = line;
mptr = line + bytespercolor;
yptr = line + 2 * bytespercolor;
kptr = line + 3 * bytespercolor;
switch (header->cupsBitsPerColor)
{
case 1 :
for (x = w, bit = 0x80; x > 0; x --, pixels += 3)
{
if (*cptr & bit)
*colors++ = 1;
else
colors ++;
if (*mptr & bit)
*colors++ = 1;
else
colors ++;
if (*yptr & bit)
*colors++ = 1;
else
colors ++;
if (*kptr & bit)
{
*colors++ = 1;
pixels[0] = 0;
pixels[1] = 0;
pixels[2] = 0;
}
else
{
colors ++;
if (*cptr & bit)
pixels[0] = 0;
if (*mptr & bit)
pixels[1] = 0;
if (*yptr & bit)
pixels[2] = 0;
}
if (bit > 1)
bit >>= 1;
else
{
bit = 0x80;
cptr ++;
mptr ++;
yptr ++;
kptr ++;
}
}
break;
case 2 :
for (x = 0; x < w; x ++)
{
switch (x & 3)
{
default :
case 0 :
val = (*kptr & 0xc0) >> 6;
k = 85 * val;
*colors++ = val = (*cptr & 0xc0) >> 6;
r = 255 - 85 * val - k;
*colors++ = val = (*mptr & 0xc0) >> 6;
g = 255 - 85 * val - k;
*colors++ = val = (*yptr & 0xc0) >> 6;
b = 255 - 85 * val - k;
*colors++ = val;
break;
case 1 :
val = (*kptr & 0x30) >> 4;
k = 85 * val;
*colors++ = val = (*cptr & 0x30) >> 4;
r = 255 - 85 * val - k;
*colors++ = val = (*mptr & 0x30) >> 4;
g = 255 - 85 * val - k;
*colors++ = val = (*yptr & 0x30) >> 4;
b = 255 - 85 * val - k;
*colors++ = val;
break;
case 2 :
val = (*kptr & 0x0c) >> 2;
k = 85 * val;
*colors++ = val = (*cptr & 0x0c) >> 2;
r = 255 - 85 * val - k;
*colors++ = val = (*mptr & 0x0c) >> 2;
g = 255 - 85 * val - k;
*colors++ = val = (*yptr & 0x0c) >> 2;
b = 255 - 85 * val - k;
*colors++ = val;
break;
case 3 :
val = *kptr & 0x03;
k = 85 * val;
*colors++ = val = *cptr & 0x03;
r = 255 - 85 * val - k;
*colors++ = val = *mptr & 0x03;
g = 255 - 85 * val - k;
*colors++ = val = *yptr & 0x03;
b = 255 - 85 * val - k;
*colors++ = val;
cptr ++;
mptr ++;
yptr ++;
kptr ++;
break;
}
if (r <= 0)
*pixels++ = 0;
else
*pixels++ = r;
if (g <= 0)
*pixels++ = 0;
else
*pixels++ = g;
if (b <= 0)
*pixels++ = 0;
else
*pixels++ = b;
}
break;
case 4 :
for (x = 0; x < w; x ++)
{
switch (x & 1)
{
default :
case 0 :
val = (*kptr & 0xf0) >> 4;
k = 17 * val;
*colors++ = val = (*cptr & 0xf0) >> 4;
r = 255 - 17 * val - k;
*colors++ = val = (*mptr & 0xf0) >> 4;
g = 255 - 17 * val - k;
*colors++ = val = (*yptr & 0xf0) >> 4;
b = 255 - 17 * val - k;
*colors++ = val;
break;
case 1 :
val = *kptr & 0x0f;
k = 17 * val;
*colors++ = val = *cptr & 0x0f;
r = 255 - 17 * val - k;
*colors++ = val = *mptr & 0x0f;
g = 255 - 17 * val - k;
*colors++ = val = *yptr & 0x0f;
b = 255 - 17 * val - k;
*colors++ = val;
cptr ++;
mptr ++;
yptr ++;
kptr ++;
break;
}
if (r <= 0)
*pixels++ = 0;
else
*pixels++ = r;
if (g <= 0)
*pixels++ = 0;
else
*pixels++ = g;
if (b <= 0)
*pixels++ = 0;
else
*pixels++ = b;
}
break;
case 8 :
for (x = w; x > 0; x --)
{
k = *kptr++;
*colors++ = val = *cptr++;
r = 255 - val - k;
*colors++ = val = *mptr++;
g = 255 - val - k;
*colors++ = val = *yptr++;
b = 255 - val - k;
*colors++ = k;
if (r <= 0)
*pixels++ = 0;
else
*pixels++ = r;
if (g <= 0)
*pixels++ = 0;
else
*pixels++ = g;
if (b <= 0)
*pixels++ = 0;
else
*pixels++ = b;
}
break;
case 16 :
for (x = w; x > 0; x --)
{
if (endian_offset)
{
*colors++ = *cptr++;
*colors++ = val = *cptr++;
r = 255 - val;
*colors++ = *mptr++;
*colors++ = val = *mptr++;
g = 255 - val;
*colors++ = *yptr++;
*colors++ = val = *yptr++;
b = 255 - val;
*colors++ = *kptr++;
*colors++ = k = *kptr++;
}
else
{
*colors++ = val = *cptr++;
r = 255 - val;
*colors++ = *cptr++;
*colors++ = val = *mptr++;
g = 255 - val;
*colors++ = *mptr++;
*colors++ = val = *yptr++;
b = 255 - val;
*colors++ = *yptr++;
*colors++ = k = *kptr++;
*colors++ = *kptr++;
}
r -= k;
g -= k;
b -= k;
if (r <= 0)
*pixels++ = 0;
else
*pixels++ = r;
if (g <= 0)
*pixels++ = 0;
else
*pixels++ = g;
if (b <= 0)
*pixels++ = 0;
else
*pixels++ = b;
}
break;
}
}
}
//
// 'convert_device()' - Convert Device-N raster data.
//
static void
convert_device(
cups_page_header2_t *header, // I - Raster header */
uchar *line, // I - Raster line
uchar *colors, // O - Original pixels
uchar *pixels, // O - RGB pixels
uchar device_colors[][3])
// I - RGB values for each device color
{
int x, // X position in line
z, // Color
w, // Width of line
val; // Pixel value
int r, g, b; // Current RGB color
w = header->cupsWidth;
if (header->cupsColorOrder != CUPS_ORDER_CHUNKED)
{
fputs("Error: Unsupported color order for Device-N...\n", stderr);
return;
}
if (header->cupsBitsPerColor != 8 && header->cupsBitsPerColor != 16)
{
fputs("Error: Unsupported bit depth for Device-N...\n", stderr);
return;
}
switch (header->cupsBitsPerColor)
{
case 8 :
for (x = w; x > 0; x --)
{
r = g = b = 255;
for (z = 0; z < header->cupsNumColors; z ++)
{
*colors++ = val = *line++;
r -= val * device_colors[z][0] / 255;
g -= val * device_colors[z][1] / 255;
b -= val * device_colors[z][2] / 255;
}
if (r <= 0)
*pixels++ = 0;
else
*pixels++ = r;
if (g <= 0)
*pixels++ = 0;
else
*pixels++ = g;
if (b <= 0)
*pixels++ = 0;
else
*pixels++ = b;
}
break;
case 16 :
for (x = w; x > 0; x --)
{
r = g = b = 255;
for (z = 0; z < header->cupsNumColors; z ++)
{
if (endian_offset)
{
*colors++ = *line++;
*colors++ = val = *line++;
}
else
{
*colors++ = val = *line++;
*colors++ = *line++;
}
r -= val * device_colors[z][0] / 255;
g -= val * device_colors[z][1] / 255;
b -= val * device_colors[z][2] / 255;
}
if (r <= 0)
*pixels++ = 0;
else
*pixels++ = r;
if (g <= 0)
*pixels++ = 0;
else
*pixels++ = g;
if (b <= 0)
*pixels++ = 0;
else
*pixels++ = b;
}
break;
}
}
//
// 'convert_k()' - Convert black raster data.
//
static void
convert_k(
cups_page_header2_t *header, // I - Raster header */
uchar *line, // I - Raster line
uchar *colors, // O - Original pixels
uchar *pixels) // O - Grayscale pixels
{
int x, // X position in line
w, // Width of line
val; // Pixel value
uchar bit, // Current bit
byte; // Current byte
w = header->cupsWidth;
switch (header->cupsBitsPerColor)
{
case 1 :
for (x = w, bit = 0x80, byte = *line++; x > 0; x --)
{
if (byte & bit)
{
*colors++ = 1;
*pixels++ = 0;
}
else
{
colors ++;
pixels ++;
}
if (bit > 1)
bit >>= 1;
else
{
bit = 0x80;
byte = *line++;
}
}
break;
case 2 :
for (x = w; x > 0; x -= 4)
{
byte = *line++;
*colors++ = val = (byte & 0xc0) >> 6;
*pixels++ = ~(85 * val);
if (x > 1)
{
*colors++ = val = (byte & 0x30) >> 4;
*pixels++ = ~(85 * val);
}
if (x > 2)
{
*colors++ = val = (byte & 0x0c) >> 2;
*pixels++ = ~(85 * val);
}
if (x > 3)
{
*colors++ = val = byte & 0x03;
*pixels++ = ~(85 * val);
}
}
break;
case 4 :
for (x = w; x > 0; x -= 2)
{
byte = *line++;
*colors++ = val = (byte & 0xf0) >> 4;
*pixels++ = ~(17 * val);
*colors++ = val = byte & 0x0f;
*pixels++ = ~(17 * val);
}
break;
case 8 :
for (x = w; x > 0; x --)
{
*colors++ = val = *line++;
*pixels++ = ~val;
}
break;
case 16 :
if (endian_offset)
{
for (x = w; x > 0; x --)
{
*colors++ = *line++;
*colors++ = val = *line++;
*pixels++ = ~val;
}
}
else
{
for (x = w; x > 0; x --)
{
*colors++ = val = *line++;
*pixels++ = ~val;
*colors++ = *line++;
}
}
break;
}
}
//
// 'convert_kcmy()' - Convert KCMY or KCMYcm (8-bit) raster data.
//
static void
convert_kcmy(
cups_page_header2_t *header, // I - Raster header */
uchar *line, // I - Raster line
uchar *colors, // O - Original pixels
uchar *pixels) // O - RGB pixels
{
int x, // X position in line
w, // Width of line
val; // Pixel value
uchar *cptr, // Cyan pointer
*mptr, // Magenta pointer
*yptr, // Yellow pointer
*kptr, // Black pointer
bit; // Current bit
int r, g, b, k; // Current RGB color + K
w = header->cupsWidth;
if (header->cupsColorOrder == CUPS_ORDER_CHUNKED)
{
// Chunky
switch (header->cupsBitsPerColor)
{
case 1 :
for (x = w; x > 0; x -= 2, pixels += 6)
{
bit = *line++;
*colors++ = bit >> 4;
if (bit & 0x80)
{
pixels[0] = 0;
pixels[1] = 0;
pixels[2] = 0;
}
else
{
if (bit & 0x40)
pixels[0] = 0;
if (bit & 0x20)
pixels[1] = 0;
if (bit & 0x10)
pixels[2] = 0;
}
if (x > 1)
{
*colors++ = bit & 0x0f;
if (bit & 0x08)
{
pixels[3] = 0;
pixels[4] = 0;
pixels[5] = 0;
}
else
{
if (bit & 0x04)
pixels[3] = 0;
if (bit & 0x02)
pixels[4] = 0;
if (bit & 0x01)
pixels[5] = 0;
}
}
}
break;
case 2 :
for (x = w; x > 0; x --)
{
*colors++ = bit = *line++;
k = 85 * ((bit & 0xc0) >> 6);
r = 255 - 85 * ((bit & 0x30) >> 4) - k;
g = 255 - 85 * ((bit & 0x0c) >> 2) - k;
b = 255 - 85 * (bit & 0x03) - k;
if (r <= 0)
*pixels++ = 0;
else
*pixels++ = r;
if (g <= 0)
*pixels++ = 0;
else
*pixels++ = g;
if (b <= 0)
*pixels++ = 0;
else
*pixels++ = b;
}
break;
case 4 :
for (x = w; x > 0; x --)
{
*colors++ = bit = *line++;
k = 17 * ((bit & 0xf0) >> 4);
r = 255 - 17 * (bit & 0x0f) - k;
*colors++ = bit = *line++;
g = 255 - 17 * ((bit & 0xf0) >> 4) - k;
b = 255 - 17 * (bit & 0x0f) - k;
if (r <= 0)
*pixels++ = 0;
else
*pixels++ = r;
if (g <= 0)
*pixels++ = 0;
else
*pixels++ = g;
if (b <= 0)
*pixels++ = 0;
else
*pixels++ = b;
}
break;
case 8 :
for (x = w; x > 0; x --)
{
*colors++ = *line;
k = *line++;
*colors++ = *line;
r = 255 - *line++ - k;
*colors++ = *line;
g = 255 - *line++ - k;
*colors++ = *line;
b = 255 - *line++ - k;
if (r <= 0)
*pixels++ = 0;
else
*pixels++ = r;
if (g <= 0)
*pixels++ = 0;
else
*pixels++ = g;
if (b <= 0)
*pixels++ = 0;
else
*pixels++ = b;
}
break;
case 16 :
for (x = w; x > 0; x --)
{
if (endian_offset)
{
*colors++ = *line++;
*colors++ = k = *line++;
*colors++ = *line++;
*colors++ = val = *line++;
r = 255 - val - k;
*colors++ = *line++;
*colors++ = val = *line++;
g = 255 - val - k;
*colors++ = *line++;
*colors++ = val = *line++;
b = 255 - val - k;
}
else
{
*colors++ = k = *line++;
*colors++ = *line++;
*colors++ = val = *line++;
r = 255 - val - k;
*colors++ = *line++;
*colors++ = val = *line++;
g = 255 - val - k;
*colors++ = *line++;
*colors++ = val = *line++;
b = 255 - val - k;
*colors++ = *line++;
}
if (r <= 0)
*pixels++ = 0;
else
*pixels++ = r;
if (g <= 0)
*pixels++ = 0;
else
*pixels++ = g;
if (b <= 0)
*pixels++ = 0;
else
*pixels++ = b;
}
break;
}
}
else
{
// Banded
int bytespercolor = (header->cupsBitsPerColor * header->cupsWidth + 7) / 8;
kptr = line;
cptr = line + bytespercolor;
mptr = line + 2 * bytespercolor;
yptr = line + 3 * bytespercolor;
switch (header->cupsBitsPerColor)
{
case 1 :
for (x = w, bit = 0x80; x > 0; x --, pixels += 3)
{
if (*kptr & bit)
{
*colors++ = 1;
pixels[0] = 0;
pixels[1] = 0;
pixels[2] = 0;
}
else
{
colors ++;
if (*cptr & bit)
pixels[0] = 0;
if (*mptr & bit)
pixels[1] = 0;
if (*yptr & bit)
pixels[2] = 0;
}
if (*cptr & bit)
*colors++ = 1;
else
colors ++;
if (*mptr & bit)
*colors++ = 1;
else
colors ++;
if (*yptr & bit)
*colors++ = 1;
else
colors ++;
if (bit > 1)
bit >>= 1;
else
{
bit = 0x80;
cptr ++;
mptr ++;
yptr ++;
kptr ++;
}
}
break;
case 2 :
for (x = 0; x < w; x ++)
{
switch (x & 3)
{
default :
case 0 :
*colors++ = val = (*kptr & 0xc0) >> 6;
k = 85 * val;
*colors++ = val = (*cptr & 0xc0) >> 6;
r = 255 - 85 * val - k;
*colors++ = val = (*mptr & 0xc0) >> 6;
g = 255 - 85 * val - k;
*colors++ = val = (*yptr & 0xc0) >> 6;
b = 255 - 85 * val - k;
break;
case 1 :
*colors++ = val = (*kptr & 0x30) >> 4;
k = 85 * val;
*colors++ = val = (*cptr & 0x30) >> 4;
r = 255 - 85 * val - k;
*colors++ = val = (*mptr & 0x30) >> 4;
g = 255 - 85 * val - k;
*colors++ = val = (*yptr & 0x30) >> 4;
b = 255 - 85 * val - k;
break;
case 2 :
*colors++ = val = (*kptr & 0x0c) >> 2;
k = 85 * val;
*colors++ = val = (*cptr & 0x0c) >> 2;
r = 255 - 85 * val - k;
*colors++ = val = (*mptr & 0x0c) >> 2;
g = 255 - 85 * val - k;
*colors++ = val = (*yptr & 0x0c) >> 2;
b = 255 - 85 * val - k;
break;
case 3 :
*colors++ = val = *kptr & 0x03;
k = 85 * val;
*colors++ = val = *cptr & 0x03;
r = 255 - 85 * val - k;
*colors++ = val = *mptr & 0x03;
g = 255 - 85 * val - k;
*colors++ = val = *yptr & 0x03;
b = 255 - 85 * val - k;
cptr ++;
mptr ++;
yptr ++;
kptr ++;
break;
}
if (r <= 0)
*pixels++ = 0;
else
*pixels++ = r;
if (g <= 0)
*pixels++ = 0;
else
*pixels++ = g;
if (b <= 0)
*pixels++ = 0;
else
*pixels++ = b;
}
break;
case 4 :
for (x = 0; x < w; x ++)
{
switch (x & 1)
{
default :
case 0 :
*colors++ = val = (*kptr & 0xf0) >> 4;
k = 17 * val;
*colors++ = val = (*cptr & 0xf0) >> 4;
r = 255 - 17 * val - k;
*colors++ = val = (*mptr & 0xf0) >> 4;
g = 255 - 17 * val - k;
*colors++ = val = (*yptr & 0xf0) >> 4;
b = 255 - 17 * val - k;
break;
case 1 :
*colors++ = val = *kptr & 0x0f;
k = 17 * val;
*colors++ = val = *cptr & 0x0f;
r = 255 - 17 * val - k;
*colors++ = val = *mptr & 0x0f;
g = 255 - 17 * val - k;
*colors++ = val = *yptr & 0x0f;
b = 255 - 17 * val - k;
cptr ++;
mptr ++;
yptr ++;
kptr ++;
break;
}
if (r <= 0)
*pixels++ = 0;
else
*pixels++ = r;
if (g <= 0)
*pixels++ = 0;
else
*pixels++ = g;
if (b <= 0)
*pixels++ = 0;
else
*pixels++ = b;
}
break;
case 8 :
for (x = w; x > 0; x --)
{
*colors++ = k = *kptr++;
*colors++ = val = *cptr++;
r = 255 - val - k;
*colors++ = val = *mptr++;
g = 255 - val - k;
*colors++ = val = *yptr++;
b = 255 - val - k;
if (r <= 0)
*pixels++ = 0;
else
*pixels++ = r;
if (g <= 0)
*pixels++ = 0;
else
*pixels++ = g;
if (b <= 0)
*pixels++ = 0;
else
*pixels++ = b;
}
break;
case 16 :
for (x = w; x > 0; x --)
{
if (endian_offset)
{
*colors++ = *kptr++;
*colors++ = k = *kptr++;
*colors++ = *cptr++;
*colors++ = val = *cptr++;
r = 255 - val - k;
*colors++ = *mptr++;
*colors++ = val = *mptr++;
g = 255 - val - k;
*colors++ = *yptr++;
*colors++ = val = *yptr++;
b = 255 - val - k;
}
else
{
*colors++ = k = *kptr++;
*colors++ = *kptr++;
*colors++ = val = *cptr++;
r = 255 - val - k;
*colors++ = *cptr++;
*colors++ = val = *mptr++;
g = 255 - val - k;
*colors++ = *mptr++;
*colors++ = val = *yptr++;
b = 255 - val - k;
*colors++ = *yptr++;
}
if (r <= 0)
*pixels++ = 0;
else
*pixels++ = r;
if (g <= 0)
*pixels++ = 0;
else
*pixels++ = g;
if (b <= 0)
*pixels++ = 0;
else
*pixels++ = b;
}
break;
}
}
}
//
// 'convert_kcmycm()' - Convert KCMYcm (1-bit) raster data.
//
static void
convert_kcmycm(
cups_page_header2_t *header, // I - Raster header */
uchar *line, // I - Raster line
uchar *colors, // O - Original pixels
uchar *pixels) // O - RGB pixels
{
int x, // X position in line
w; // Width of line
uchar *cptr, // Cyan pointer
*mptr, // Magenta pointer
*yptr, // Yellow pointer
*kptr, // Black pointer
*lcptr, // Light cyan pointer
*lmptr, // Light magenta pointer
bit; // Current bit
int r, g, b; // Current RGB color
w = header->cupsWidth;
if (header->cupsColorOrder == CUPS_ORDER_CHUNKED)
{
// Chunky
for (x = w; x > 0; x --)
{
bit = *line++;
*colors++ = bit;
if (bit & 0x20)
{
*pixels++ = 0;
*pixels++ = 0;
*pixels++ = 0;
continue;
}
r = g = 255;
if (bit & 0x10)
r -= 255;
if (bit & 0x08)
g -= 255;
if (bit & 0x02)
r -= 127;
if (bit & 0x01)
g -= 127;
if (bit & 0x04)
b = 0;
else
b = 255;
if (r < 0)
*pixels++ = 0;
else
*pixels++ = r;
if (g < 0)
*pixels++ = 0;
else
*pixels++ = g;
// Blue is always in range...
*pixels++ = b;
}
}
else
{
// Banded
int bytespercolor = header->cupsBytesPerLine / 6;
kptr = line;
cptr = line + bytespercolor;
mptr = line + 2 * bytespercolor;
yptr = line + 3 * bytespercolor;
lcptr = line + 4 * bytespercolor;
lmptr = line + 5 * bytespercolor;
for (x = w, bit = 0x80; x > 0; x --)
{
if (*kptr & bit)
{
*colors++ = 1;
*pixels++ = 0;
*pixels++ = 0;
*pixels++ = 0;
}
else
{
colors ++;
r = g = 255;
if (*cptr & bit)
r -= 255;
if (*mptr & bit)
g -= 255;
if (*lcptr & bit)
r -= 127;
if (*lmptr & bit)
g -= 127;
if (*yptr & bit)
b = 0;
else
b = 255;
if (r < 0)
*pixels++ = 0;
else
*pixels++ = r;
if (g < 0)
*pixels++ = 0;
else
*pixels++ = g;
// Blue is always in range...
*pixels++ = b;
}
if (*cptr & bit)
*colors++ = 1;
else
colors ++;
if (*mptr & bit)
*colors++ = 1;
else
colors ++;
if (*yptr & bit)
*colors++ = 1;
else
colors ++;
if (*lcptr & bit)
*colors++ = 1;
else
colors ++;
if (*lmptr & bit)
*colors++ = 1;
else
colors ++;
if (bit > 1)
bit >>= 1;
else
{
bit = 0x80;
cptr ++;
mptr ++;
yptr ++;
kptr ++;
lcptr ++;
lmptr ++;
}
}
}
}
//
// 'convert_lab()' - Convert CIE Lab or ICCn raster data.
//
static void
convert_lab(
cups_page_header2_t *header, // I - Raster header */
uchar *line, // I - Raster line
uchar *colors, // O - Original pixels
uchar *pixels) // O - RGB pixels
{
int x, // X position in line
w, // Width of line
val; // Pixel value
unsigned short *sline; // 16-bit pixels
float lab[3], // Lab color
p, //
xyz[3], // XYZ color
rgb[3]; // RGB color
w = header->cupsWidth;
for (x = w, sline = (unsigned short *)line; x > 0; x --)
{
// Extract the Lab color value...
if (header->cupsBitsPerColor == 8)
{
// 8-bit color values...
*colors++ = val = *line++;
lab[0] = val / 2.55f;
*colors++ = val = *line++;
lab[1] = val - 128.0f;
*colors++ = val = *line++;
lab[2] = val - 128.0f;
}
else
{
// 16-bit color values...
*colors++ = *line++;
*colors++ = *line++;
lab[0] = *sline++ / 655.35f;
*colors++ = *line++;
*colors++ = *line++;
lab[1] = *sline++ / 256.0f - 128.0f;
*colors++ = *line++;
*colors++ = *line++;
lab[2] = *sline++ / 256.0f - 128.0f;
}
// Convert Lab to XYZ...
if (lab[0] < 8)
p = lab[0] / 903.3;
else
p = (lab[0] + 16.0f) / 116.0f;
xyz[0] = D65_X * pow(p + lab[1] * 0.002, 3.0);
xyz[1] = D65_Y * pow((double)p, 3.0);
xyz[2] = D65_Z * pow(p - lab[2] * 0.005, 3.0);
// Convert XYZ to sRGB...
rgb[0] = 3.240479f * xyz[0] - 1.537150f * xyz[1] - 0.498535f * xyz[2];
rgb[1] = -0.969256f * xyz[0] + 1.875992f * xyz[1] + 0.041556f * xyz[2];
rgb[2] = 0.055648f * xyz[0] - 0.204043f * xyz[1] + 1.057311f * xyz[2];
rgb[0] = rgb[0] <= 0.0 ? 0.0 : 1.055f * pow((double)rgb[0], 0.41666) - 0.055f;
rgb[1] = rgb[1] <= 0.0 ? 0.0 : 1.055f * pow((double)rgb[1], 0.41666) - 0.055f;
rgb[2] = rgb[2] <= 0.0 ? 0.0 : 1.055f * pow((double)rgb[2], 0.41666) - 0.055f;
// Save it...
if (rgb[0] <= 0.0f)
*pixels++ = 0;
else if (rgb[0] < 1.0f)
*pixels++ = (int)(255.0f * rgb[0] + 0.5);
else
*pixels++ = 255;
if (rgb[1] <= 0.0f)
*pixels++ = 0;
else if (rgb[1] < 1.0f)
*pixels++ = (int)(255.0f * rgb[1] + 0.5);
else
*pixels++ = 255;
if (rgb[2] <= 0.0f)
*pixels++ = 0;
else if (rgb[2] < 1.0f)
*pixels++ = (int)(255.0f * rgb[2] + 0.5);
else
*pixels++ = 255;
}
}
//
// 'convert_rgb()' - Convert RGB raster data.
//
static void
convert_rgb(
cups_page_header2_t *header, // I - Raster header */
uchar *line, // I - Raster line
uchar *colors, // O - Original pixels
uchar *pixels) // O - RGB pixels
{
int x, // X position in line
w, // Width of line
val; // Pixel value
uchar *rptr, // Red pointer
*gptr, // Green pointer
*bptr, // Blue pointer
bit; // Current bit
w = header->cupsWidth;
if (header->cupsColorOrder == CUPS_ORDER_CHUNKED)
{
// Chunky
switch (header->cupsBitsPerColor)
{
case 1 :
memset(pixels, 0, w * 3);
for (x = w; x > 0; x -= 2, pixels += 6)
{
bit = *line++;
*colors++ = bit >> 4;
if (bit & 0x40)
pixels[0] = 255;
if (bit & 0x20)
pixels[1] = 255;
if (bit & 0x10)
pixels[2] = 255;
if (x > 1)
{
*colors++ = bit & 0x0f;
if (bit & 0x04)
pixels[3] = 255;
if (bit & 0x02)
pixels[4] = 255;
if (bit & 0x01)
pixels[5] = 255;
}
}
break;
case 2 :
for (x = w; x > 0; x --)
{
*colors++ = bit = *line++;
*pixels++ = 85 * ((bit & 0x30) >> 4);
*pixels++ = 85 * ((bit & 0x0c) >> 2);
*pixels++ = 85 * (bit & 0x03);
}
break;
case 4 :
memset(pixels, 0, w * 3);
for (x = w; x > 0; x --, pixels += 3)
{
bit = *line++;
*colors++ = bit;
if (bit & 0x0f)
pixels[0] += 17 * (bit & 0x0f);
bit = *line++;
*colors++ = bit;
if (bit & 0xf0)
pixels[1] += 17 * ((bit & 0xf0) >> 4);
if (bit & 0x0f)
pixels[2] += 17 * (bit & 0x0f);
}
break;
case 8 :
memcpy(colors, line, w * 3);
memcpy(pixels, line, w * 3);
break;
case 16 :
if (endian_offset)
*colors++ = *line++;
for (x = w; x > 0; x --)
{
*colors++ = *pixels++ = *line++;
*colors++ = *line++;
*colors++ = *pixels++ = *line++;
*colors++ = *line++;
*colors++ = *pixels++ = *line++;
if (!endian_offset || x > 1)
*colors++ = *line++;
}
break;
}
}
else
{
// Banded
int bytespercolor = (header->cupsBitsPerColor * header->cupsWidth + 7) / 8;
rptr = line;
gptr = line + bytespercolor;
bptr = line + 2 * bytespercolor;
switch (header->cupsBitsPerColor)
{
case 1 :
memset(pixels, 0, w * 3);
for (x = w, bit = 0x80; x > 0; x --, pixels += 3)
{
if (*rptr & bit)
{
*colors++ = 1;
pixels[0] = 255;
}
else
colors ++;
if (*gptr & bit)
{
*colors++ = 1;
pixels[1] = 255;
}
else
colors ++;
if (*bptr & bit)
{
*colors++ = 1;
pixels[2] = 255;
}
else
colors ++;
if (bit > 1)
bit >>= 1;
else
{
bit = 0x80;
rptr ++;
gptr ++;
bptr ++;
}
}
break;
case 2 :
for (x = 0; x < w; x ++)
{
switch (x & 3)
{
case 0 :
*colors++ = val = (*rptr & 0xc0) >> 6;
*pixels++ = 85 * val;
*colors++ = val = (*gptr & 0xc0) >> 6;
*pixels++ = 85 * val;
*colors++ = val = (*bptr & 0xc0) >> 6;
*pixels++ = 85 * val;
break;
case 1 :
*colors++ = val = (*rptr & 0x30) >> 4;
*pixels++ = 85 * val;
*colors++ = val = (*gptr & 0x30) >> 4;
*pixels++ = 85 * val;
*colors++ = val = (*bptr & 0x30) >> 4;
*pixels++ = 85 * val;
break;
case 2 :
*colors++ = val = (*rptr & 0x0c) >> 2;
*pixels++ = 85 * val;
*colors++ = val = (*gptr & 0x0c) >> 2;
*pixels++ = 85 * val;
*colors++ = val = (*bptr & 0x0c) >> 2;
*pixels++ = 85 * val;
break;
case 3 :
*colors++ = val = *rptr & 0x03;
*pixels++ = 85 * val;
*colors++ = val = *gptr & 0x03;
*pixels++ = 85 * val;
*colors++ = val = *bptr & 0x03;
*pixels++ = 85 * val;
rptr ++;
gptr ++;
bptr ++;
break;
}
}
break;
case 4 :
for (x = 0; x < w; x ++)
{
switch (x & 1)
{
case 0 :
*colors++ = val = (*rptr & 0xf0) >> 4;
*pixels++ = 17 * val;
*colors++ = val = (*gptr & 0xf0) >> 4;
*pixels++ = 17 * val;
*colors++ = val = (*bptr & 0xf0) >> 4;
*pixels++ = 17 * val;
break;
case 1 :
*colors++ = val = *rptr & 0x0f;
*pixels++ = 17 * val;
*colors++ = val = *gptr & 0x0f;
*pixels++ = 17 * val;
*colors++ = val = *bptr & 0x0f;
*pixels++ = 17 * val;
rptr ++;
gptr ++;
bptr ++;
break;
}
}
break;
case 8 :
for (x = w; x > 0; x --)
{
*colors++ = *pixels++ = *rptr++;
*colors++ = *pixels++ = *gptr++;
*colors++ = *pixels++ = *bptr++;
}
break;
case 16 :
if (endian_offset)
{
for (x = w; x > 0; x --)
{
*colors++ = *rptr++;
*colors++ = *pixels++ = *rptr++;
*colors++ = *gptr++;
*colors++ = *pixels++ = *gptr++;
*colors++ = *bptr++;
*colors++ = *pixels++ = *bptr++;
}
}
else
{
for (x = w; x > 0; x --)
{
*colors++ = *pixels++ = *rptr++;
*colors++ = *rptr++;
*colors++ = *pixels++ = *gptr++;
*colors++ = *gptr++;
*colors++ = *pixels++ = *bptr++;
*colors++ = *bptr++;
}
}
break;
}
}
}
//
// 'convert_rgba()' - Convert RGBA raster data.
//
static void
convert_rgba(
cups_page_header2_t *header, // I - Raster header */
int y, // I - Raster Y position
uchar *line, // I - Raster line
uchar *colors, // O - Original pixels
uchar *pixels) // O - RGB pixels
{
int x, // X position in line
w, // Width of line
val; // Pixel value
uchar *rptr, // Red pointer
*gptr, // Green pointer
*bptr, // Blue pointer
*aptr, // Alpha pointer
bit; // Current bit
int r, g, b, a; // Current color
int bg; // Background to blend
w = header->cupsWidth;
y &= 128;
if (header->cupsColorOrder == CUPS_ORDER_CHUNKED)
{
// Chunky
switch (header->cupsBitsPerColor)
{
case 1 :
memset(pixels, 0, w * 3);
for (x = w; x > 0; x -= 2, pixels += 6)
{
bit = *line++;
*colors++ = bit >> 4;
if (bit & 0x10)
{
if (bit & 0x80)
pixels[0] = 255;
if (bit & 0x40)
pixels[1] = 255;
if (bit & 0x20)
pixels[2] = 255;
}
else if ((x & 128) ^ y)
{
pixels[0] = 128;
pixels[1] = 128;
pixels[2] = 128;
}
else
{
pixels[0] = 192;
pixels[1] = 192;
pixels[2] = 192;
}
if (x > 1)
{
*colors++ = bit & 0x0f;
if (bit & 0x01)
{
if (bit & 0x08)
pixels[3] = 255;
if (bit & 0x04)
pixels[4] = 255;
if (bit & 0x02)
pixels[5] = 255;
}
else if (((x - 1) & 128) ^ y)
{
pixels[3] = 128;
pixels[4] = 128;
pixels[5] = 128;
}
else
{
pixels[3] = 192;
pixels[4] = 192;
pixels[5] = 192;
}
}
}
break;
case 2 :
for (x = w; x > 0; x --)
{
*colors++ = bit = *line++;
r = 85 * ((bit & 0xc0) >> 6);
g = 85 * ((bit & 0x30) >> 4);
b = 85 * ((bit & 0x0c) >> 2);
a = 85 * (bit & 0x03);
if (a < 255)
{
if ((x & 128) ^ y)
bg = 128;
else
bg = 192;
if (a == 0)
r = g = b = bg;
else
{
r = (a * r + (255 - a) * bg) / 255;
g = (a * g + (255 - a) * bg) / 255;
b = (a * b + (255 - a) * bg) / 255;
}
}
*pixels++ = r;
*pixels++ = g;
*pixels++ = b;
}
break;
case 4 :
for (x = w; x > 0; x --)
{
*colors++ = bit = *line++;
r = 17 * ((bit & 0xf0) >> 4);
g = 17 * (bit & 0x0f);
*colors++ = bit = *line++;
b = 17 * ((bit & 0xf0) >> 4);
a = 17 * (bit & 0x0f);
if (a < 255)
{
if ((x & 128) ^ y)
bg = 128;
else
bg = 192;
if (a == 0)
r = g = b = bg;
else
{
r = (a * r + (255 - a) * bg) / 255;
g = (a * g + (255 - a) * bg) / 255;
b = (a * b + (255 - a) * bg) / 255;
}
}
*pixels++ = r;
*pixels++ = g;
*pixels++ = b;
}
break;
case 8 :
for (x = w; x > 0; x --)
{
*colors++ = r = *line++;
*colors++ = g = *line++;
*colors++ = b = *line++;
*colors++ = a = *line++;
if (a < 255)
{
if ((x & 128) ^ y)
bg = 128;
else
bg = 192;
if (a == 0)
r = g = b = bg;
else
{
r = (a * r + (255 - a) * bg) / 255;
g = (a * g + (255 - a) * bg) / 255;
b = (a * b + (255 - a) * bg) / 255;
}
}
*pixels++ = r;
*pixels++ = g;
*pixels++ = b;
}
break;
case 16 :
if (endian_offset)
*colors++ = *line++;
for (x = w; x > 0; x --)
{
*colors++ = r = *line++;
*colors++ = *line++;
*colors++ = g = *line++;
*colors++ = *line++;
*colors++ = b = *line++;
*colors++ = *line++;
*colors++ = a = *line++;
if (!endian_offset || x > 1)
*colors++ = *line++;
if (a < 255)
{
if ((x & 128) ^ y)
bg = 128;
else
bg = 192;
if (a == 0)
r = g = b = bg;
else
{
r = (a * r + (255 - a) * bg) / 255;
g = (a * g + (255 - a) * bg) / 255;
b = (a * b + (255 - a) * bg) / 255;
}
}
*pixels++ = r;
*pixels++ = g;
*pixels++ = b;
}
break;
}
}
else
{
// Banded
int bytespercolor = (header->cupsBitsPerColor * header->cupsWidth + 7) / 8;
rptr = line;
gptr = line + bytespercolor;
bptr = line + 2 * bytespercolor;
aptr = line + 3 * bytespercolor;
switch (header->cupsBitsPerColor)
{
case 1 :
memset(pixels, 0, w * 3);
for (x = w, bit = 0x80; x > 0; x --, pixels += 3)
{
if (*rptr & bit)
{
*colors++ = 1;
pixels[0] = 255;
}
else
colors ++;
if (*gptr & bit)
{
*colors++ = 1;
pixels[1] = 255;
}
else
colors ++;
if (*bptr & bit)
{
*colors++ = 1;
pixels[2] = 255;
}
else
colors ++;
if (*aptr & bit)
*colors++ = 1;
else
{
colors ++;
if ((x & 128) ^ y)
{
pixels[0] = 128;
pixels[1] = 128;
pixels[2] = 128;
}
else
{
pixels[0] = 192;
pixels[1] = 192;
pixels[2] = 192;
}
}
if (bit > 1)
bit >>= 1;
else
{
bit = 0x80;
rptr ++;
gptr ++;
bptr ++;
aptr ++;
}
}
break;
case 2 :
for (x = 0; x < w; x ++)
{
switch (x & 3)
{
default :
case 0 :
*colors++ = val = (*rptr & 0xc0) >> 6;
r = 85 * val;
*colors++ = val = (*gptr & 0xc0) >> 6;
g = 85 * val;
*colors++ = val = (*bptr & 0xc0) >> 6;
b = 85 * val;
*colors++ = val = (*aptr & 0xc0) >> 6;
a = 85 * val;
break;
case 1 :
*colors++ = val = (*rptr & 0x30) >> 4;
r = 85 * val;
*colors++ = val = (*gptr & 0x30) >> 4;
g = 85 * val;
*colors++ = val = (*bptr & 0x30) >> 4;
b = 85 * val;
*colors++ = val = (*aptr & 0x30) >> 4;
a = 85 * val;
break;
case 2 :
*colors++ = val = (*rptr & 0x0c) >> 2;
r = 85 * val;
*colors++ = val = (*gptr & 0x0c) >> 2;
g = 85 * val;
*colors++ = val = (*bptr & 0x0c) >> 2;
b = 85 * val;
*colors++ = val = (*aptr & 0x0c) >> 2;
a = 85 * val;
break;
case 3 :
*colors++ = val = *rptr & 0x03;
r = 85 * val;
*colors++ = val = *gptr & 0x03;
g = 85 * val;
*colors++ = val = *bptr & 0x03;
b = 85 * val;
*colors++ = val = *aptr & 0x03;
a = 85 * val;
rptr ++;
gptr ++;
bptr ++;
aptr ++;
break;
}
if (a < 255)
{
if ((x & 128) ^ y)
bg = 128;
else
bg = 192;
if (a == 0)
r = g = b = bg;
else
{
r = (a * r + (255 - a) * bg) / 255;
g = (a * g + (255 - a) * bg) / 255;
b = (a * b + (255 - a) * bg) / 255;
}
}
*pixels++ = r;
*pixels++ = g;
*pixels++ = b;
}
break;
case 4 :
for (x = 0; x < w; x ++)
{
switch (x & 1)
{
default :
case 0 :
*colors++ = val = (*rptr & 0xf0) >> 4;
r = 17 * val;
*colors++ = val = (*gptr & 0xf0) >> 4;
g = 17 * val;
*colors++ = val = (*bptr & 0xf0) >> 4;
b = 17 * val;
*colors++ = val = (*aptr & 0xf0) >> 4;
a = 17 * val;
break;
case 1 :
*colors++ = val = *rptr & 0x0f;
r = 17 * val;
*colors++ = val = *gptr & 0x0f;
g = 17 * val;
*colors++ = val = *bptr & 0x0f;
b = 17 * val;
*colors++ = val = *aptr & 0x0f;
a = 17 * val;
rptr ++;
gptr ++;
bptr ++;
aptr ++;
break;
}
if (a < 255)
{
if ((x & 128) ^ y)
bg = 128;
else
bg = 192;
if (a == 0)
r = g = b = bg;
else
{
r = (a * r + (255 - a) * bg) / 255;
g = (a * g + (255 - a) * bg) / 255;
b = (a * b + (255 - a) * bg) / 255;
}
}
*pixels++ = r;
*pixels++ = g;
*pixels++ = b;
}
break;
case 8 :
for (x = w; x > 0; x --)
{
*colors++ = r = *rptr++;
*colors++ = g = *gptr++;
*colors++ = b = *bptr++;
*colors++ = a = *aptr++;
if (a < 255)
{
if ((x & 128) ^ y)
bg = 128;
else
bg = 192;
if (a == 0)
r = g = b = bg;
else
{
r = (a * r + (255 - a) * bg) / 255;
g = (a * g + (255 - a) * bg) / 255;
b = (a * b + (255 - a) * bg) / 255;
}
}
*pixels++ = r;
*pixels++ = g;
*pixels++ = b;
}
break;
case 16 :
for (x = w; x > 0; x --)
{
if (endian_offset)
{
*colors++ = *rptr++;
*colors++ = r = *rptr++;
*colors++ = *gptr++;
*colors++ = g = *gptr++;
*colors++ = *bptr++;
*colors++ = b = *bptr++;
*colors++ = *aptr++;
*colors++ = a = *aptr++;
}
else
{
*colors++ = r = *rptr++;
*colors++ = *rptr++;
*colors++ = g = *gptr++;
*colors++ = *gptr++;
*colors++ = b = *bptr++;
*colors++ = *bptr++;
*colors++ = a = *aptr++;
*colors++ = *aptr++;
}
if (a < 255)
{
if ((x & 128) ^ y)
bg = 128;
else
bg = 192;
if (a == 0)
r = g = b = bg;
else
{
r = (a * r + (255 - a) * bg) / 255;
g = (a * g + (255 - a) * bg) / 255;
b = (a * b + (255 - a) * bg) / 255;
}
}
*pixels++ = r;
*pixels++ = g;
*pixels++ = b;
}
break;
}
}
}
//
// 'convert_rgbw()' - Convert RGBW raster data.
//
static void
convert_rgbw(
cups_page_header2_t *header, // I - Raster header */
uchar *line, // I - Raster line
uchar *colors, // O - Original pixels
uchar *pixels) // O - RGB pixels
{
int x, // X position in line
w, // Width of line
val; // Pixel value
uchar *rptr, // Red pointer
*gptr, // Green pointer
*bptr, // Blue pointer
*wptr, // White pointer
bit; // Current bit
int r, g, b, white; // Current RGBW color
w = header->cupsWidth;
if (header->cupsColorOrder == CUPS_ORDER_CHUNKED)
{
// Chunky
switch (header->cupsBitsPerColor)
{
case 1 :
memset(pixels, 0, w * 3);
for (x = w; x > 0; x -= 2, pixels += 6)
{
bit = *line++;
*colors++ = bit >> 4;
if (bit & 0x10)
{
if (bit & 0x80)
pixels[0] = 255;
if (bit & 0x40)
pixels[1] = 255;
if (bit & 0x20)
pixels[2] = 255;
}
if (x > 1)
{
*colors++ = bit & 0x0f;
if (bit & 0x01)
{
if (bit & 0x08)
pixels[3] = 255;
if (bit & 0x04)
pixels[4] = 255;
if (bit & 0x02)
pixels[5] = 255;
}
}
}
break;
case 2 :
for (x = w; x > 0; x --)
{
*colors++ = bit = *line++;
white = 85 * (bit & 0x03) - 255;
r = 85 * ((bit & 0xc0) >> 6) + white;
g = 85 * ((bit & 0x30) >> 4) + white;
b = 85 * ((bit & 0x0c) >> 2) + white;
if (r <= 0)
*pixels++ = 0;
else if (r < 255)
*pixels++ = r;
else
*pixels++ = 255;
if (g <= 0)
*pixels++ = 0;
else if (g < 255)
*pixels++ = g;
else
*pixels++ = 255;
if (b <= 0)
*pixels++ = 0;
else if (b < 255)
*pixels++ = b;
else
*pixels++ = 255;
}
break;
case 4 :
for (x = w; x > 0; x --)
{
*colors++ = bit = *line++;
r = 17 * ((bit & 0xf0) >> 4);
g = 17 * (bit & 0x0f);
*colors++ = bit = *line++;
b = 17 * ((bit & 0xf0) >> 4);
white = 17 * (bit & 0x0f) - 255;
r += white;
g += white;
b += white;
if (r <= 0)
*pixels++ = 0;
else if (r < 255)
*pixels++ = r;
else
*pixels++ = 255;
if (g <= 0)
*pixels++ = 0;
else if (g < 255)
*pixels++ = g;
else
*pixels++ = 255;
if (b <= 0)
*pixels++ = 0;
else if (b < 255)
*pixels++ = b;
else
*pixels++ = 255;
}
break;
case 8 :
for (x = w; x > 0; x --)
{
*colors++ = r = *line++;
*colors++ = g = *line++;
*colors++ = b = *line++;
*colors++ = val = *line++;
white = val - 255;
r += white;
g += white;
b += white;
if (r <= 0)
*pixels++ = 0;
else if (r < 255)
*pixels++ = r;
else
*pixels++ = 255;
if (g <= 0)
*pixels++ = 0;
else if (g < 255)
*pixels++ = g;
else
*pixels++ = 255;
if (b <= 0)
*pixels++ = 0;
else if (b < 255)
*pixels++ = b;
else
*pixels++ = 255;
}
break;
case 16 :
if (endian_offset)
*colors++ = *line++;
for (x = w; x > 0; x --)
{
*colors++ = r = *line++;
*colors++ = *line++;
*colors++ = g = *line++;
*colors++ = *line++;
*colors++ = b = *line++;
*colors++ = *line++;
*colors++ = val = *line++;
white = val - 255;
if (!endian_offset || x > 1)
*colors++ = *line++;
r += white;
g += white;
b += white;
if (r <= 0)
*pixels++ = 0;
else if (r < 255)
*pixels++ = r;
else
*pixels++ = 255;
if (g <= 0)
*pixels++ = 0;
else if (g < 255)
*pixels++ = g;
else
*pixels++ = 255;
if (b <= 0)
*pixels++ = 0;
else if (b < 255)
*pixels++ = b;
else
*pixels++ = 255;
}
break;
}
}
else
{
// Banded
int bytespercolor = (header->cupsBitsPerColor * header->cupsWidth + 7) / 8;
rptr = line;
gptr = line + bytespercolor;
bptr = line + 2 * bytespercolor;
wptr = line + 3 * bytespercolor;
switch (header->cupsBitsPerColor)
{
case 1 :
memset(pixels, 0, w * 3);
for (x = w, bit = 0x80; x > 0; x --, pixels += 3)
{
if (*rptr & bit)
*colors++ = 1;
else
colors ++;
if (*gptr & bit)
*colors++ = 1;
else
colors ++;
if (*bptr & bit)
*colors++ = 1;
else
colors ++;
if (*wptr & bit)
{
*colors++ = 1;
if (*rptr & bit)
pixels[0] = 255;
if (*gptr & bit)
pixels[1] = 255;
if (*bptr & bit)
pixels[2] = 255;
}
else
colors ++;
if (bit > 1)
bit >>= 1;
else
{
bit = 0x80;
rptr ++;
gptr ++;
bptr ++;
wptr ++;
}
}
break;
case 2 :
for (x = 0; x < w; x ++)
{
switch (x & 3)
{
default :
case 0 :
*colors++ = val = (*rptr & 0xc0) >> 6;
r = 85 * val;
*colors++ = val = (*gptr & 0xc0) >> 6;
g = 85 * val;
*colors++ = val = (*bptr & 0xc0) >> 6;
b = 85 * val;
*colors++ = val = (*wptr & 0xc0) >> 6;
white = 85 * val - 255;
break;
case 1 :
*colors++ = val = (*rptr & 0x30) >> 4;
r = 85 * val;
*colors++ = val = (*gptr & 0x30) >> 4;
g = 85 * val;
*colors++ = val = (*bptr & 0x30) >> 4;
b = 85 * val;
*colors++ = val = (*wptr & 0x30) >> 4;
white = 85 * val - 255;
break;
case 2 :
*colors++ = val = (*rptr & 0x0c) >> 2;
r = 85 * val;
*colors++ = val = (*gptr & 0x0c) >> 2;
g = 85 * val;
*colors++ = val = (*bptr & 0x0c) >> 2;
b = 85 * val;
*colors++ = val = (*wptr & 0x0c) >> 2;
white = 85 * val - 255;
break;
case 3 :
*colors++ = val = *rptr & 0x03;
r = 85 * val;
*colors++ = val = *gptr & 0x03;
g = 85 * val;
*colors++ = val = *bptr & 0x03;
b = 85 * val;
*colors++ = val = *wptr & 0x03;
white = 85 * val - 255;
rptr ++;
gptr ++;
bptr ++;
wptr ++;
break;
}
r += white;
g += white;
b += white;
if (r <= 0)
*pixels++ = 0;
else if (r < 255)
*pixels++ = r;
else
*pixels++ = 255;
if (g <= 0)
*pixels++ = 0;
else if (g < 255)
*pixels++ = g;
else
*pixels++ = 255;
if (b <= 0)
*pixels++ = 0;
else if (b < 255)
*pixels++ = b;
else
*pixels++ = 255;
}
break;
case 4 :
for (x = 0; x < w; x ++)
{
switch (x & 1)
{
default :
case 0 :
*colors++ = val = (*rptr & 0xf0) >> 4;
r = 17 * val;
*colors++ = val = (*gptr & 0xf0) >> 4;
g = 17 * val;
*colors++ = val = (*bptr & 0xf0) >> 4;
b = 17 * val;
*colors++ = val = (*wptr & 0xf0) >> 4;
white = 17 * val - 255;
break;
case 1 :
*colors++ = val = *rptr & 0x0f;
r = 17 * val;
*colors++ = val = *gptr & 0x0f;
g = 17 * val;
*colors++ = val = *bptr & 0x0f;
b = 17 * val;
*colors++ = val = *wptr & 0x0f;
white = 17 * val - 255;
rptr ++;
gptr ++;
bptr ++;
wptr ++;
break;
}
r += white;
g += white;
b += white;
if (r <= 0)
*pixels++ = 0;
else if (r < 255)
*pixels++ = r;
else
*pixels++ = 255;
if (g <= 0)
*pixels++ = 0;
else if (g < 255)
*pixels++ = g;
else
*pixels++ = 255;
if (b <= 0)
*pixels++ = 0;
else if (b < 255)
*pixels++ = b;
else
*pixels++ = 255;
}
break;
case 8 :
for (x = w; x > 0; x --)
{
*colors++ = r = *rptr++;
*colors++ = g = *gptr++;
*colors++ = b = *bptr++;
*colors++ = val = *wptr++;
white = val - 255;
r += white;
g += white;
b += white;
if (r <= 0)
*pixels++ = 0;
else if (r < 255)
*pixels++ = r;
else
*pixels++ = 255;
if (g <= 0)
*pixels++ = 0;
else if (g < 255)
*pixels++ = g;
else
*pixels++ = 255;
if (b <= 0)
*pixels++ = 0;
else if (b < 255)
*pixels++ = b;
else
*pixels++ = 255;
}
break;
case 16 :
for (x = w; x > 0; x --)
{
if (endian_offset)
{
*colors++ = *rptr++;
*colors++ = r = *rptr++;
*colors++ = *gptr++;
*colors++ = g = *gptr++;
*colors++ = *bptr++;
*colors++ = b = *bptr++;
*colors++ = *wptr++;
*colors++ = val = *wptr++;
white = val - 255;
}
else
{
*colors++ = r = *rptr++;
*colors++ = *rptr++;
*colors++ = g = *gptr++;
*colors++ = *gptr++;
*colors++ = b = *bptr++;
*colors++ = *bptr++;
*colors++ = val = *wptr++;
white = val - 255;
*colors++ = *wptr++;
}
r += white;
g += white;
b += white;
if (r <= 0)
*pixels++ = 0;
else if (r < 255)
*pixels++ = r;
else
*pixels++ = 255;
if (g <= 0)
*pixels++ = 0;
else if (g < 255)
*pixels++ = g;
else
*pixels++ = 255;
if (b <= 0)
*pixels++ = 0;
else if (b < 255)
*pixels++ = b;
else
*pixels++ = 255;
}
break;
}
}
}
//
// 'convert_w()' - Convert grayscale raster data.
//
static void
convert_w(
cups_page_header2_t *header, // I - Raster header */
uchar *line, // I - Raster line
uchar *colors, // O - Original pixels
uchar *pixels) // O - Grayscale pixels
{
int x, // X position in line
w, // Width of line
val; // Pixel value
uchar bit, // Current bit
byte; // Current byte
w = header->cupsWidth;
switch (header->cupsBitsPerColor)
{
case 1 :
for (x = w, bit = 0x80, byte = *line++; x > 0; x --)
{
if (byte & bit)
{
*colors++ = 1;
pixels ++;
}
else
{
colors ++;
*pixels++ = 0;
}
if (bit > 1)
bit >>= 1;
else
{
bit = 0x80;
byte = *line++;
}
}
break;
case 2 :
for (x = w; x > 0; x -= 4)
{
byte = *line++;
*colors++ = val = (byte & 0xc0) >> 6;
*pixels++ = 85 * val;
if (x > 1)
{
*colors++ = val = (byte & 0x30) >> 4;
*pixels++ = 85 * val;
}
if (x > 2)
{
*colors++ = val = (byte & 0x0c) >> 2;
*pixels++ = 85 * val;
}
if (x > 3)
{
*colors++ = val = byte & 0x03;
*pixels++ = 85 * val;
}
}
break;
case 4 :
for (x = w; x > 0; x -= 2)
{
byte = *line++;
*colors++ = val = (byte & 0xf0) >> 4;
*pixels++ = 17 * val;
if (x > 1)
{
*colors++ = val = byte & 0x0f;
*pixels++ = 17 * val;
}
}
break;
case 8 :
memcpy(colors, line, w);
memcpy(pixels, line, w);
break;
case 16 :
if (endian_offset)
{
for (x = w; x > 0; x --)
{
*colors++ = *line++;
*colors++ = *pixels++ = *line++;
}
}
else
{
for (x = w; x > 0; x --)
{
*colors++ = *pixels++ = *line++;
*colors++ = *line++;
}
}
break;
}
}
//
// 'convert_xyz()' - Convert CIE XYZ raster data.
//
static void
convert_xyz(
cups_page_header2_t *header, // I - Raster header */
uchar *line, // I - Raster line
uchar *colors, // O - Original pixels
uchar *pixels) // O - RGB pixels
{
int x, // X position in line
w, // Width of line
val; // Pixel value
unsigned short *sline; // 16-bit pixels
float xyz[3], // XYZ color
rgb[3]; // RGB color
w = header->cupsWidth;
for (x = w, sline = (unsigned short *)line; x > 0; x --)
{
// Extract the Lab color value...
if (header->cupsBitsPerColor == 8)
{
// 8-bit color values...
*colors++ = val = *line++;
xyz[0] = val / 231.8181f;
*colors++ = val = *line++;
xyz[1] = val / 231.8181f;
*colors++ = val = *line++;
xyz[2] = val / 231.8181f;
}
else
{
// 16-bit color values...
*colors++ = *line++;
*colors++ = *line++;
*colors++ = *line++;
*colors++ = *line++;
*colors++ = *line++;
*colors++ = *line++;
xyz[0] = *sline++ / 59577.2727f;
xyz[1] = *sline++ / 59577.2727f;
xyz[2] = *sline++ / 59577.2727f;
}
// Convert XYZ to sRGB...
rgb[0] = 3.240479f * xyz[0] - 1.537150f * xyz[1] - 0.498535f * xyz[2];
rgb[1] = -0.969256f * xyz[0] + 1.875992f * xyz[1] + 0.041556f * xyz[2];
rgb[2] = 0.055648f * xyz[0] - 0.204043f * xyz[1] + 1.057311f * xyz[2];
rgb[0] = rgb[0] <= 0.0 ? 0.0 : 1.055f * pow((double)rgb[0], 0.41666) - 0.055f;
rgb[1] = rgb[1] <= 0.0 ? 0.0 : 1.055f * pow((double)rgb[1], 0.41666) - 0.055f;
rgb[2] = rgb[2] <= 0.0 ? 0.0 : 1.055f * pow((double)rgb[2], 0.41666) - 0.055f;
// Save it...
if (rgb[0] <= 0.0f)
*pixels++ = 0;
else if (rgb[0] < 1.0f)
*pixels++ = (int)(255.0f * rgb[0] + 0.5);
else
*pixels++ = 255;
if (rgb[1] <= 0.0f)
*pixels++ = 0;
else if (rgb[1] < 1.0f)
*pixels++ = (int)(255.0f * rgb[1] + 0.5);
else
*pixels++ = 255;
if (rgb[2] <= 0.0f)
*pixels++ = 0;
else if (rgb[2] < 1.0f)
*pixels++ = (int)(255.0f * rgb[2] + 0.5);
else
*pixels++ = 255;
}
}
//
// 'convert_ymc()' - Convert YMC raster data.
//
static void
convert_ymc(
cups_page_header2_t *header, // I - Raster header */
uchar *line, // I - Raster line
uchar *colors, // O - Original pixels
uchar *pixels) // O - RGB pixels
{
int x, // X position in line
w, // Width of line
val; // Pixel value
uchar *cptr, // Cyan pointer
*mptr, // Magenta pointer
*yptr, // Yellow pointer
bit; // Current bit
w = header->cupsWidth;
if (header->cupsColorOrder == CUPS_ORDER_CHUNKED)
{
// Chunky
switch (header->cupsBitsPerColor)
{
case 1 :
for (x = w; x > 0; x -= 2, pixels += 6)
{
bit = *line++;
*colors++ = bit >> 4;
if (bit & 0x40)
pixels[2] = 0;
if (bit & 0x20)
pixels[1] = 0;
if (bit & 0x10)
pixels[0] = 0;
if (x > 1)
{
*colors++ = bit & 0x0f;
if (bit & 0x04)
pixels[5] = 0;
if (bit & 0x02)
pixels[4] = 0;
if (bit & 0x01)
pixels[3] = 0;
}
}
break;
case 2 :
for (x = w; x > 0; x --, pixels += 3)
{
*colors++ = bit = *line++;
pixels[2] = 255 - 85 * ((bit & 0x30) >> 4);
pixels[1] = 255 - 85 * ((bit & 0x0c) >> 2);
pixels[0] = 255 - 85 * (bit & 0x03);
}
break;
case 4 :
for (x = w; x > 0; x --, pixels += 3)
{
*colors++ = bit = *line++;
pixels[2] = 255 - 17 * (bit & 0x0f);
*colors++ = bit = *line++;
pixels[1] = 255 - 17 * ((bit & 0xf0) >> 4);
pixels[0] = 255 - 17 * (bit & 0x0f);
}
break;
case 8 :
for (x = w; x > 0; x --, pixels += 3)
{
*colors++ = val = *line++;
pixels[2] = 255 - val;
*colors++ = val = *line++;
pixels[1] = 255 - val;
*colors++ = val = *line++;
pixels[0] = 255 - val;
}
break;
case 16 :
if (endian_offset)
{
for (x = w; x > 0; x --, pixels += 3)
{
*colors++ = *line++;
*colors++ = val = *line++;
pixels[2] = 255 - val;
*colors++ = *line++;
*colors++ = val = *line++;
pixels[1] = 255 - val;
*colors++ = *line++;
*colors++ = val = *line++;
pixels[0] = 255 - val;
}
}
else
{
for (x = w; x > 0; x --, pixels += 3)
{
*colors++ = val = *line++;
pixels[2] = 255 - val;
*colors++ = *line++;
*colors++ = val = *line++;
pixels[1] = 255 - val;
*colors++ = *line++;
*colors++ = val = *line++;
pixels[0] = 255 - val;
*colors++ = *line++;
}
}
break;
}
}
else
{
// Banded
int bytespercolor = (header->cupsBitsPerColor * header->cupsWidth + 7) / 8;
yptr = line;
mptr = line + bytespercolor;
cptr = line + 2 * bytespercolor;
switch (header->cupsBitsPerColor)
{
case 1 :
for (x = w, bit = 0x80; x > 0; x --, pixels += 3)
{
if (*yptr & bit)
{
*colors++ = 1;
pixels[2] = 0;
}
else
colors ++;
if (*mptr & bit)
{
*colors++ = 1;
pixels[1] = 0;
}
else
colors ++;
if (*cptr & bit)
{
*colors++ = 1;
pixels[0] = 0;
}
else
colors ++;
if (bit > 1)
bit >>= 1;
else
{
bit = 0x80;
cptr ++;
mptr ++;
yptr ++;
}
}
break;
case 2 :
for (x = 0; x < w; x ++, pixels += 3)
{
switch (x & 3)
{
case 0 :
*colors++ = val = (*yptr & 0xc0) >> 6;
pixels[2] = 255 - 85 * val;
*colors++ = val = (*mptr & 0xc0) >> 6;
pixels[1] = 255 - 85 * val;
*colors++ = val = (*cptr & 0xc0) >> 6;
pixels[0] = 255 - 85 * val;
break;
case 1 :
*colors++ = val = (*yptr & 0x30) >> 4;
pixels[2] = 255 - 85 * val;
*colors++ = val = (*mptr & 0x30) >> 4;
pixels[1] = 255 - 85 * val;
*colors++ = val = (*cptr & 0x30) >> 4;
pixels[0] = 255 - 85 * val;
break;
case 2 :
*colors++ = val = (*yptr & 0x0c) >> 2;
pixels[2] = 255 - 85 * val;
*colors++ = val = (*mptr & 0x0c) >> 2;
pixels[1] = 255 - 85 * val;
*colors++ = val = (*cptr & 0x0c) >> 2;
pixels[0] = 255 - 85 * val;
break;
case 3 :
*colors++ = val = *yptr & 0x03;
pixels[2] = 255 - 85 * val;
*colors++ = val = *mptr & 0x03;
pixels[1] = 255 - 85 * val;
*colors++ = val = *cptr & 0x03;
pixels[0] = 255 - 85 * val;
cptr ++;
mptr ++;
yptr ++;
break;
}
}
break;
case 4 :
for (x = 0; x < w; x ++, pixels += 3)
{
switch (x & 1)
{
case 0 :
*colors++ = val = (*yptr & 0xf0) >> 4;
pixels[2] = 255 - 17 * val;
*colors++ = val = (*mptr & 0xf0) >> 4;
pixels[1] = 255 - 17 * val;
*colors++ = val = (*cptr & 0xf0) >> 4;
pixels[0] = 255 - 17 * val;
break;
case 1 :
*colors++ = val = *yptr & 0x0f;
pixels[2] = 255 - 17 * val;
*colors++ = val = *mptr & 0x0f;
pixels[1] = 255 - 17 * val;
*colors++ = val = *cptr & 0x0f;
pixels[0] = 255 - 17 * val;
cptr ++;
mptr ++;
yptr ++;
break;
}
}
break;
case 8 :
for (x = w; x > 0; x --, pixels += 3)
{
*colors++ = val = *yptr++;
pixels[2] = 255 - val;
*colors++ = val = *mptr++;
pixels[1] = 255 - val;
*colors++ = val = *cptr++;
pixels[0] = 255 - val;
}
break;
case 16 :
if (endian_offset)
{
for (x = w; x > 0; x --, pixels += 3)
{
*colors++ = *yptr++;
*colors++ = val = *yptr++;
pixels[2] = 255 - val;
*colors++ = *mptr++;
*colors++ = val = *mptr++;
pixels[1] = 255 - val;
*colors++ = *cptr++;
*colors++ = val = *cptr++;
pixels[0] = 255 - val;
}
}
else
{
for (x = w; x > 0; x --, pixels += 3)
{
*colors++ = val = *yptr++;
pixels[2] = 255 - val;
*colors++ = *yptr++;
*colors++ = val = *mptr++;
pixels[1] = 255 - val;
*colors++ = *mptr++;
*colors++ = val = *cptr++;
pixels[0] = 255 - val;
*colors++ = *cptr++;
}
}
break;
}
}
}
//
// 'convert_ymck()' - Convert YMCK, GMCK, or GMCS raster data.
//
static void
convert_ymck(
cups_page_header2_t *header, // I - Raster header */
uchar *line, // I - Raster line
uchar *colors, // O - Original pixels
uchar *pixels) // O - RGB pixels
{
int x, // X position in line
w, // Width of line
val; // Pixel value
uchar *cptr, // Cyan pointer
*mptr, // Magenta pointer
*yptr, // Yellow pointer
*kptr, // Black pointer
bit; // Current bit
int r, g, b, k; // Current RGB color + K
w = header->cupsWidth;
if (header->cupsColorOrder == CUPS_ORDER_CHUNKED)
{
// Chunky
switch (header->cupsBitsPerColor)
{
case 1 :
for (x = w; x > 0; x -= 2, pixels += 6)
{
bit = *line++;
*colors++ = bit >> 4;
if (bit & 0x10)
{
pixels[0] = 0;
pixels[1] = 0;
pixels[2] = 0;
}
else
{
if (bit & 0x80)
pixels[2] = 0;
if (bit & 0x40)
pixels[1] = 0;
if (bit & 0x20)
pixels[0] = 0;
}
if (x > 1)
{
*colors++ = bit & 0x0f;
if (bit & 0x01)
{
pixels[3] = 0;
pixels[4] = 0;
pixels[5] = 0;
}
else
{
if (bit & 0x08)
pixels[5] = 0;
if (bit & 0x04)
pixels[4] = 0;
if (bit & 0x02)
pixels[3] = 0;
}
}
}
break;
case 2 :
for (x = w; x > 0; x --)
{
*colors++ = bit = *line++;
k = 85 * (bit & 0x03);
b = 255 - 85 * ((bit & 0xc0) >> 6) - k;
g = 255 - 85 * ((bit & 0x30) >> 4) - k;
r = 255 - 85 * ((bit & 0x0c) >> 2) - k;
if (r < 0)
*pixels++ = 0;
else
*pixels++ = r;
if (g < 0)
*pixels++ = 0;
else
*pixels++ = g;
if (b < 0)
*pixels++ = 0;
else
*pixels++ = b;
}
break;
case 4 :
for (x = w; x > 0; x --)
{
*colors++ = bit = *line++;
b = 255 - 17 * ((bit & 0xf0) >> 4);
g = 255 - 17 * (bit & 0x0f);
*colors++ = bit = *line++;
r = 255 - 17 * ((bit & 0xf0) >> 4);
k = 17 * (bit & 0x0f);
r -= k;
g -= k;
b -= k;
if (r < 0)
*pixels++ = 0;
else
*pixels++ = r;
if (g < 0)
*pixels++ = 0;
else
*pixels++ = g;
if (b < 0)
*pixels++ = 0;
else
*pixels++ = b;
}
break;
case 8 :
for (x = w; x > 0; x --)
{
*colors++ = val = *line++;
b = 255 - val;
*colors++ = val = *line++;
g = 255 - val;
*colors++ = val = *line++;
r = 255 - val;
*colors++ = k = *line++;
r -= k;
g -= k;
b -= k;
if (r < 0)
*pixels++ = 0;
else
*pixels++ = r;
if (g < 0)
*pixels++ = 0;
else
*pixels++ = g;
if (b < 0)
*pixels++ = 0;
else
*pixels++ = b;
}
break;
case 16 :
for (x = w; x > 0; x --)
{
if (endian_offset)
{
*colors++ = *line++;
*colors++ = val = *line++;
b = 255 - val;
*colors++ = *line++;
*colors++ = val = *line++;
g = 255 - val;
*colors++ = *line++;
*colors++ = val = *line++;
r = 255 - val;
*colors++ = *line++;
*colors++ = k = *line++;
}
else
{
*colors++ = val = *line++;
b = 255 - val;
*colors++ = *line++;
*colors++ = val = *line++;
g = 255 - val;
*colors++ = *line++;
*colors++ = val = *line++;
r = 255 - val;
*colors++ = *line++;
*colors++ = k = *line++;
*colors++ = *line++;
}
r -= k;
g -= k;
b -= k;
if (r < 0)
*pixels++ = 0;
else
*pixels++ = r;
if (g < 0)
*pixels++ = 0;
else
*pixels++ = g;
if (b < 0)
*pixels++ = 0;
else
*pixels++ = b;
}
break;
}
}
else
{
// Banded
int bytespercolor = (header->cupsBitsPerColor * header->cupsWidth + 7) / 8;
yptr = line;
mptr = line + bytespercolor;
cptr = line + 2 * bytespercolor;
kptr = line + 3 * bytespercolor;
switch (header->cupsBitsPerColor)
{
case 1 :
for (x = w, bit = 0x80; x > 0; x --, pixels += 3)
{
if (*yptr & bit)
*colors++ = 1;
else
colors ++;
if (*mptr & bit)
*colors++ = 1;
else
colors ++;
if (*cptr & bit)
*colors++ = 1;
else
colors ++;
if (*kptr & bit)
{
*colors++ = 1;
pixels[0] = 0;
pixels[1] = 0;
pixels[2] = 0;
}
else
{
colors ++;
if (*cptr & bit)
pixels[0] = 0;
if (*mptr & bit)
pixels[1] = 0;
if (*yptr & bit)
pixels[2] = 0;
}
if (bit > 1)
bit >>= 1;
else
{
bit = 0x80;
cptr ++;
mptr ++;
yptr ++;
kptr ++;
}
}
break;
case 2 :
for (x = 0; x < w; x ++)
{
switch (x & 3)
{
default :
case 0 :
val = (*kptr & 0xc0) >> 6;
k = 85 * val;
*colors++ = val = (*yptr & 0xc0) >> 6;
b = 255 - 85 * val - k;
*colors++ = val = (*mptr & 0xc0) >> 6;
g = 255 - 85 * val - k;
*colors++ = val = (*cptr & 0xc0) >> 6;
r = 255 - 85 * val - k;
*colors++ = val;
break;
case 1 :
val = (*kptr & 0x30) >> 4;
k = 85 * val;
*colors++ = val = (*yptr & 0x30) >> 4;
b = 255 - 85 * val - k;
*colors++ = val = (*mptr & 0x30) >> 4;
g = 255 - 85 * val - k;
*colors++ = val = (*cptr & 0x30) >> 4;
r = 255 - 85 * val - k;
*colors++ = val;
break;
case 2 :
val = (*kptr & 0x0c) >> 2;
k = 85 * val;
*colors++ = val = (*yptr & 0x0c) >> 2;
b = 255 - 85 * val - k;
*colors++ = val = (*mptr & 0x0c) >> 2;
g = 255 - 85 * val - k;
*colors++ = val = (*cptr & 0x0c) >> 2;
r = 255 - 85 * val - k;
*colors++ = val;
break;
case 3 :
val = *kptr & 0x03;
k = 85 * val;
*colors++ = val = *yptr & 0x03;
b = 255 - 85 * val - k;
*colors++ = val = *mptr & 0x03;
g = 255 - 85 * val - k;
*colors++ = val = *cptr & 0x03;
r = 255 - 85 * val - k;
*colors++ = val;
cptr ++;
mptr ++;
yptr ++;
kptr ++;
break;
}
if (r <= 0)
*pixels++ = 0;
else
*pixels++ = r;
if (g <= 0)
*pixels++ = 0;
else
*pixels++ = g;
if (b <= 0)
*pixels++ = 0;
else
*pixels++ = b;
}
break;
case 4 :
for (x = 0; x < w; x ++)
{
switch (x & 1)
{
default :
case 0 :
val = (*kptr & 0xf0) >> 4;
k = 17 * val;
*colors++ = val = (*yptr & 0xf0) >> 4;
b = 255 - 17 * val - k;
*colors++ = val = (*mptr & 0xf0) >> 4;
g = 255 - 17 * val - k;
*colors++ = val = (*cptr & 0xf0) >> 4;
r = 255 - 17 * val - k;
*colors++ = val;
break;
case 1 :
val = *kptr & 0x0f;
k = 17 * val;
*colors++ = val = *yptr & 0x0f;
b = 255 - 17 * val - k;
*colors++ = val = *mptr & 0x0f;
g = 255 - 17 * val - k;
*colors++ = val = *cptr & 0x0f;
r = 255 - 17 * val - k;
*colors++ = val;
cptr ++;
mptr ++;
yptr ++;
kptr ++;
break;
}
if (r <= 0)
*pixels++ = 0;
else
*pixels++ = r;
if (g <= 0)
*pixels++ = 0;
else
*pixels++ = g;
if (b <= 0)
*pixels++ = 0;
else
*pixels++ = b;
}
break;
case 8 :
for (x = w; x > 0; x --)
{
k = *kptr++;
*colors++ = val = *yptr++;
b = 255 - val - k;
*colors++ = val = *mptr++;
g = 255 - val - k;
*colors++ = val = *cptr++;
r = 255 - val - k;
*colors++ = k;
if (r <= 0)
*pixels++ = 0;
else
*pixels++ = r;
if (g <= 0)
*pixels++ = 0;
else
*pixels++ = g;
if (b <= 0)
*pixels++ = 0;
else
*pixels++ = b;
}
break;
case 16 :
for (x = w; x > 0; x --)
{
if (endian_offset)
{
*colors++ = *cptr++;
*colors++ = val = *cptr++;
r = 255 - val;
*colors++ = *mptr++;
*colors++ = val = *mptr++;
g = 255 - val;
*colors++ = *yptr++;
*colors++ = val = *yptr++;
b = 255 - val;
*colors++ = *kptr++;
*colors++ = k = *kptr++;
}
else
{
*colors++ = val = *cptr++;
r = 255 - val;
*colors++ = *cptr++;
*colors++ = val = *mptr++;
g = 255 - val;
*colors++ = *mptr++;
*colors++ = val = *yptr++;
b = 255 - val;
*colors++ = *yptr++;
*colors++ = k = *kptr++;
*colors++ = *kptr++;
}
r -= k;
g -= k;
b -= k;
if (r <= 0)
*pixels++ = 0;
else
*pixels++ = r;
if (g <= 0)
*pixels++ = 0;
else
*pixels++ = g;
if (b <= 0)
*pixels++ = 0;
else
*pixels++ = b;
}
break;
}
}
}
/*
* 'raster_cb()' - Read data from a gzFile.
*/
static ssize_t /* O - Bytes read or -1 on error */
raster_cb(gzFile ctx, /* I - File pointer */
unsigned char *buffer, /* I - Buffer */
size_t length) /* I - Bytes to read */
{
return ((ssize_t)gzread(ctx, buffer, (unsigned)length));
}
RasterDisplay.h 0000664 0000000 0000000 00000006645 14074577431 0014044 0 ustar 00root root 0000000 0000000 //
// CUPS raster file display widget header file.
//
// Copyright 2002-2018 by Michael R Sweet.
//
// Licensed under Apache License v2.0. See the file "LICENSE" for more
// information.
//
#ifndef RasterDisplay_h
# define RasterDisplay_h
//
// Include necessary headers...
//
# include "raster.h"
# include
# include
# include
# include
// Maximum pages
# define RASTER_MAX_PAGES 1000
//
// Display control modes...
//
enum
{
RASTER_MODE_PAN,
RASTER_MODE_ZOOM_IN,
RASTER_MODE_ZOOM_OUT,
RASTER_MODE_CLICK
};
//
// RasterDisplay widget...
//
class RasterDisplay : public Fl_Group
{
cups_raster_t *ras_; // Raster stream
const char *filename_; // Filename
gzFile fp_; // File pointer
int page_, // Current page number
num_pages_; // Number of pages
z_off_t pages_[RASTER_MAX_PAGES];
// Page offsets
cups_page_header2_t header_; // Page header for current page
int bpc_, // Bytes per color
bpp_; // Bytes per pixel
uchar *pixels_; // Pixel buffer
long alloc_pixels_; // Number of bytes allocated
uchar *colors_; // Color data buffer
long alloc_colors_; // Numebr of colors allocated
float factor_; // Zoom factor
int xsize_; // Bresenheim variables
int xstep_; // ...
int xmod_; // ...
int ysize_; // ...
Fl_Scrollbar xscrollbar_; // Horizontal scrollbar
Fl_Scrollbar yscrollbar_; // Vertical scrollbar
int mode_; // Viewing mode
int start_ex_, // Start position (mouse coords)
start_ey_;
int start_x_, // Start position (image coords)
start_y_;
int mouse_x_, // Current position (image coords)
mouse_y_;
int last_x_, // Previous position (image coords)
last_y_;
uchar device_colors_[15][3];
// CMY device colors
static void image_cb(void *p, int X, int Y, int W, uchar *D);
void load_colors();
void save_colors();
static void scrollbar_cb(Fl_Widget *w, void *d);
void update_mouse_xy();
void update_scrollbars();
protected:
void draw();
public:
RasterDisplay(int X, int Y, int W, int H, const char *L = 0);
~RasterDisplay();
int bytes_per_color() const { return bpc_; }
int bytes_per_pixel() const { return bpp_; }
int close_file();
void device_color(int n, Fl_Color c) { uchar r,g,b; Fl::get_color(c, r, g, b); device_colors_[n][0] = 255-r; device_colors_[n][1] = 255-g; device_colors_[n][2] = 255-b; save_colors();}
Fl_Color device_color(int n) { return (fl_rgb_color(255-device_colors_[n][0], 255-device_colors_[n][1], 255-device_colors_[n][2])); }
uchar *get_color(int X, int Y);
uchar *get_pixel(int X, int Y);
int handle(int event);
cups_page_header2_t *header() { return &header_; }
int is_subtractive();
int load_page();
void mode(int m) { mode_ = m; }
int mode() const { return mode_; }
int mouse_x() const { return mouse_x_; }
int mouse_y() const { return mouse_y_; }
int num_pages() const { return num_pages_; }
int page(void);
void page(int number);
void position(int X, int Y);
void resize(int X, int Y, int W, int H);
void scale(float factor);
float scale() const { return factor_; }
int start_x() const { return start_x_; }
int start_y() const { return start_y_; }
int open_file(const char *filename);
int xposition() { return xscrollbar_.value(); }
int yposition() { return yscrollbar_.value(); }
};
#endif // !RasterDisplay_h
RasterView.app/ 0000775 0000000 0000000 00000000000 14074577431 0013744 5 ustar 00root root 0000000 0000000 RasterView.app/Contents/ 0000775 0000000 0000000 00000000000 14074577431 0015541 5 ustar 00root root 0000000 0000000 RasterView.app/Contents/Info.plist 0000664 0000000 0000000 00000003432 14074577431 0017513 0 ustar 00root root 0000000 0000000
CFBundleInfoDictionaryVersion
6.0
CFBundleExecutable
rasterview
CFBundleIdentifier
org.msweet.rasterview
CFBundleVersion
1.8
CFBundleDevelopmentRegion
English
NSHumanReadableCopyright
Copyright © 2002-2021 by Michael R Sweet
CFAppleHelpAnchor
help
CFBundleName
RasterView
CFBundlePackageType
APPL
CFBundleSignature
CUPS
CFBundleIconFile
rasterview.icns
CFBundleShortVersionString
1.8
CFBundleGetInfoString
1.8, Copyright © 2002-2021 by Michael R Sweet
CFBundleDocumentTypes
CFBundleTypeExtensions
apple
apple.gz
pwg
pwg.gz
ras
ras.gz
urf
urf.gz
CFBundleTypeIconFile
rasterview.icns
CFBundleTypeName
CUPS Raster File
CFBundleTypeOSTypes
CUPR
CFBundleTypeRole
Editor
RasterView.app/Contents/PkgInfo 0000664 0000000 0000000 00000000011 14074577431 0017011 0 ustar 00root root 0000000 0000000 CUPSCUPR
RasterView.app/Contents/Resources/ 0000775 0000000 0000000 00000000000 14074577431 0017513 5 ustar 00root root 0000000 0000000 RasterView.app/Contents/Resources/rasterview.icns 0000664 0000000 0000000 00000314070 14074577431 0022571 0 ustar 00root root 0000000 0000000 icns 8TOC pis32 gs8mk il32 l8mk ic11 ic12 it32 t8mk @ic08 ic13 ic09 8[ic14 8[ic10 is32 g @ @ &