Re: Creating Really Big TIFF's
Re: Creating Really Big TIFF's
- Subject: Re: Creating Really Big TIFF's
- From: Thomas Finley <email@hidden>
- Date: Thu, 10 Jul 2003 13:53:25 -0400
On Thursday, July 10, 2003, at 07:47 AM, Robert Clair wrote:
Since this is potentially hundreds of Mbytes, just making an NSImage
with
a correct size NSImageRep, drawing on it and using -TiffRepresentation
isn't going to fly. (Can't assume the user has a G5 with 8 gig
of memory :-) )
It may with virtual memory if it is indeed hundreds and _not_ thousands
of megabytes, of course, but it would be deathly slow and best avoided
since it is unnecessary.
The last time I had to do something like this (years go, X11, Sun)
I banded the image, created PostScript files for the bands and
then post-processed them through a hacked up version of
GhostScript to produce targa files (what was needed for the job)
and some code to sew the tga's together.
Gross. :)
Is there some way to make Cocoa do the banding ? It must
be able to do something like this because you can print. I suspect
what I need is a dummy printer that specifies the page size and
resolution
and accepts the pixels, which it will stream to a file. Raw pixels and
fixing up into tiff or whatever as a post process is OK.
Any suggestions on where to look for the info ?
Given how you're going about this, the easiest way I can think of is to
_not_ use Cocoa's image hadling for this sort of job. Install
something like libtiff, which will allow you to write segmented tiffs
without needing to hold absolutely everything in memory. Provided you
can easily segment the image, this is a very trivial procedure; much
easier than hacking ghostscript and sewing together different image
files yourself, at any rate. :)
I installed my libtiff via fink. Linking of libraries defaults to
dynamic of course; if this is something you're going to be distributing
to other people that you can't depend on having libtiff, you can build
by including the libraries for libtiff.a, libjpeg.a as you would any
object file when you build your app, and link in -lz.) See
http://www.libtiff.org/ for more info, including copyright restrictions
(happily very unrestrictive). Tutorials abound on the web by searching
for libtiff on Google.
The source following is an example use of libtiff. It writes out the
images in strips (horizontal bars, the first at the top, the last on
the bottom), so that you need hold only the data for one strip in
memory at a time. The strips are 8 pixels heigh. Each strip is set to
a different solid color (red, green, blue, and repeat) and written to
the TIFF file handle. I tried to make my program more obvious and
concise than speedily efficient. In addition to strips (segmented
along y axis) you can use tiles (segmented along x and y axis).
You may find it better to use tiles, not strips. Tiles are like
strips, except, as their name implies, they're segmented in the x and y
axes and not just the y axis like strips. See the libtiff docs for
more info.
Note that, with the right format flags for NSBitmapImageRep (to match 8
bits per sample and 3 sample per pixel and the rest), you could pass
its [rep bitmapData] instead of "raster" for each strip, and use
Cocoa's image and graphics routines for creating the pixel data for
each strip (or tile) and use libtiff for writing each strip (or tile).
==========
#include <stdio.h>
#include <tiffio.h>
#define WIDTH 150
#define HEIGHT 200
#define SAMPLES 3
#define ROWSPERSTRIP 8
uint8 Colors[] = { 255, 0, 0, /* Red */
0, 160, 0, /* Green */
0, 0, 200 }; /* Blue. */
unsigned DifferentColors = 3;
int main() {
tstrip_t s, strips; /* These are really just unsigned ints. */
tsize_t stripSize = WIDTH*ROWSPERSTRIP*SAMPLES; /* size_ts, really. */
TIFF *image;
/* Create the tiff to write to. */
if ((image = TIFFOpen("testwrite.tiff", "w")) == NULL) {
fprintf(stderr, "Could not open file to write.\n");
exit(1);
}
/* Set tags. */
TIFFSetField(image, TIFFTAG_IMAGEWIDTH, WIDTH);
TIFFSetField(image, TIFFTAG_IMAGELENGTH, HEIGHT);
TIFFSetField(image, TIFFTAG_BITSPERSAMPLE, 8);
TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, 3);
TIFFSetField(image, TIFFTAG_ROWSPERSTRIP, ROWSPERSTRIP);
TIFFSetField(image, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
TIFFSetField(image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
TIFFSetField(image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
/* You say you want 600 dpi */
TIFFSetField(image, TIFFTAG_XRESOLUTION, 600.0);
TIFFSetField(image, TIFFTAG_YRESOLUTION, 600.0);
TIFFSetField(image, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
/* Write the info to a file. */
strips = HEIGHT / ROWSPERSTRIP;
for (s=0; s<strips; s++) {
/* Create the strip... sets a strip to a single block of color */
unsigned i, currentColor = s % DifferentColors; /* Which color? */
uint8 raster[WIDTH * ROWSPERSTRIP * SAMPLES]; /* Buffer for strip */
for (i=0; i<stripSize; i++) /* Set pixels. */
raster[i] = Colors[(currentColor*SAMPLES) + (i%SAMPLES)];
/* Write the current strip to the file */
if (TIFFWriteEncodedStrip(image, s, raster, stripSize) != stripSize)
fprintf(stderr, "Could not write %d bytes on strip %d",
stripSize, s);
}
/* Close it up. */
TIFFClose(image);
return 0;
}
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.