]>
git.saurik.com Git - wxWidgets.git/blob - src/tiff/tools/tiff2rgba.c
3 * Copyright (c) 1991-1997 Sam Leffler
4 * Copyright (c) 1991-1997 Silicon Graphics, Inc.
6 * Permission to use, copy, modify, distribute, and sell this software and
7 * its documentation for any purpose is hereby granted without fee, provided
8 * that (i) the above copyright notices and this permission notice appear in
9 * all copies of the software and related documentation, and (ii) the names of
10 * Sam Leffler and Silicon Graphics may not be used in any advertising or
11 * publicity relating to the software without the specific, prior written
12 * permission of Sam Leffler and Silicon Graphics.
14 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
15 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
16 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
18 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
19 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
20 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
21 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
22 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
26 #include "tif_config.h"
43 #define streq(a,b) (strcmp(a,b) == 0)
44 #define CopyField(tag, v) \
45 if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
48 #define howmany(x, y) (((x)+((y)-1))/(y))
50 #define roundup(x, y) (howmany(x,y)*((uint32)(y)))
52 uint16 compression
= COMPRESSION_PACKBITS
;
53 uint32 rowsperstrip
= (uint32
) -1;
54 int process_by_block
= 0; /* default is whole image at once */
56 int bigtiff_output
= 0;
59 static int tiffcvt(TIFF
* in
, TIFF
* out
);
60 static void usage(int code
);
63 main(int argc
, char* argv
[])
70 while ((c
= getopt(argc
, argv
, "c:r:t:bn8")) != -1)
77 if (streq(optarg
, "none"))
78 compression
= COMPRESSION_NONE
;
79 else if (streq(optarg
, "packbits"))
80 compression
= COMPRESSION_PACKBITS
;
81 else if (streq(optarg
, "lzw"))
82 compression
= COMPRESSION_LZW
;
83 else if (streq(optarg
, "jpeg"))
84 compression
= COMPRESSION_JPEG
;
85 else if (streq(optarg
, "zip"))
86 compression
= COMPRESSION_DEFLATE
;
92 rowsperstrip
= atoi(optarg
);
96 rowsperstrip
= atoi(optarg
);
112 if (argc
- optind
< 2)
115 out
= TIFFOpen(argv
[argc
-1], bigtiff_output
?"w8":"w");
119 for (; optind
< argc
-1; optind
++) {
120 in
= TIFFOpen(argv
[optind
], "r");
123 if (!tiffcvt(in
, out
) ||
124 !TIFFWriteDirectory(out
)) {
125 (void) TIFFClose(out
);
126 (void) TIFFClose(in
);
129 } while (TIFFReadDirectory(in
));
130 (void) TIFFClose(in
);
133 (void) TIFFClose(out
);
138 cvt_by_tile( TIFF
*in
, TIFF
*out
)
141 uint32
* raster
; /* retrieve RGBA image */
142 uint32 width
, height
; /* image width & height */
143 uint32 tile_width
, tile_height
;
148 TIFFGetField(in
, TIFFTAG_IMAGEWIDTH
, &width
);
149 TIFFGetField(in
, TIFFTAG_IMAGELENGTH
, &height
);
151 if( !TIFFGetField(in
, TIFFTAG_TILEWIDTH
, &tile_width
)
152 || !TIFFGetField(in
, TIFFTAG_TILELENGTH
, &tile_height
) ) {
153 TIFFError(TIFFFileName(in
), "Source image not tiled");
157 TIFFSetField(out
, TIFFTAG_TILEWIDTH
, tile_width
);
158 TIFFSetField(out
, TIFFTAG_TILELENGTH
, tile_height
);
161 * Allocate tile buffer
163 raster
= (uint32
*)_TIFFmalloc(tile_width
* tile_height
* sizeof (uint32
));
165 TIFFError(TIFFFileName(in
), "No space for raster buffer");
170 * Allocate a scanline buffer for swapping during the vertical
173 wrk_line
= (uint32
*)_TIFFmalloc(tile_width
* sizeof (uint32
));
175 TIFFError(TIFFFileName(in
), "No space for raster scanline buffer");
180 * Loop over the tiles.
182 for( row
= 0; ok
&& row
< height
; row
+= tile_height
)
184 for( col
= 0; ok
&& col
< width
; col
+= tile_width
)
188 /* Read the tile into an RGBA array */
189 if (!TIFFReadRGBATile(in
, col
, row
, raster
)) {
196 * XXX: raster array has 4-byte unsigned integer type, that is why
197 * we should rearrange it here.
200 TIFFSwabArrayOfLong(raster
, tile_width
* tile_height
);
204 * For some reason the TIFFReadRGBATile() function chooses the
205 * lower left corner as the origin. Vertically mirror scanlines.
207 for( i_row
= 0; i_row
< tile_height
/ 2; i_row
++ )
209 uint32
*top_line
, *bottom_line
;
211 top_line
= raster
+ tile_width
* i_row
;
212 bottom_line
= raster
+ tile_width
* (tile_height
-i_row
-1);
214 _TIFFmemcpy(wrk_line
, top_line
, 4*tile_width
);
215 _TIFFmemcpy(top_line
, bottom_line
, 4*tile_width
);
216 _TIFFmemcpy(bottom_line
, wrk_line
, 4*tile_width
);
220 * Write out the result in a tile.
223 if( TIFFWriteEncodedTile( out
,
224 TIFFComputeTile( out
, col
, row
, 0, 0),
226 4 * tile_width
* tile_height
) == -1 )
235 _TIFFfree( wrk_line
);
241 cvt_by_strip( TIFF
*in
, TIFF
*out
)
244 uint32
* raster
; /* retrieve RGBA image */
245 uint32 width
, height
; /* image width & height */
250 TIFFGetField(in
, TIFFTAG_IMAGEWIDTH
, &width
);
251 TIFFGetField(in
, TIFFTAG_IMAGELENGTH
, &height
);
253 if( !TIFFGetField(in
, TIFFTAG_ROWSPERSTRIP
, &rowsperstrip
) ) {
254 TIFFError(TIFFFileName(in
), "Source image not in strips");
258 TIFFSetField(out
, TIFFTAG_ROWSPERSTRIP
, rowsperstrip
);
261 * Allocate strip buffer
263 raster
= (uint32
*)_TIFFmalloc(width
* rowsperstrip
* sizeof (uint32
));
265 TIFFError(TIFFFileName(in
), "No space for raster buffer");
270 * Allocate a scanline buffer for swapping during the vertical
273 wrk_line
= (uint32
*)_TIFFmalloc(width
* sizeof (uint32
));
275 TIFFError(TIFFFileName(in
), "No space for raster scanline buffer");
280 * Loop over the strips.
282 for( row
= 0; ok
&& row
< height
; row
+= rowsperstrip
)
284 int rows_to_write
, i_row
;
286 /* Read the strip into an RGBA array */
287 if (!TIFFReadRGBAStrip(in
, row
, raster
)) {
293 * XXX: raster array has 4-byte unsigned integer type, that is why
294 * we should rearrange it here.
297 TIFFSwabArrayOfLong(raster
, width
* rowsperstrip
);
301 * Figure out the number of scanlines actually in this strip.
303 if( row
+ rowsperstrip
> height
)
304 rows_to_write
= height
- row
;
306 rows_to_write
= rowsperstrip
;
309 * For some reason the TIFFReadRGBAStrip() function chooses the
310 * lower left corner as the origin. Vertically mirror scanlines.
313 for( i_row
= 0; i_row
< rows_to_write
/ 2; i_row
++ )
315 uint32
*top_line
, *bottom_line
;
317 top_line
= raster
+ width
* i_row
;
318 bottom_line
= raster
+ width
* (rows_to_write
-i_row
-1);
320 _TIFFmemcpy(wrk_line
, top_line
, 4*width
);
321 _TIFFmemcpy(top_line
, bottom_line
, 4*width
);
322 _TIFFmemcpy(bottom_line
, wrk_line
, 4*width
);
326 * Write out the result in a strip
329 if( TIFFWriteEncodedStrip( out
, row
/ rowsperstrip
, raster
,
330 4 * rows_to_write
* width
) == -1 )
338 _TIFFfree( wrk_line
);
346 * read the whole image into one big RGBA buffer and then write out
347 * strips from that. This is using the traditional TIFFReadRGBAImage()
352 cvt_whole_image( TIFF
*in
, TIFF
*out
)
355 uint32
* raster
; /* retrieve RGBA image */
356 uint32 width
, height
; /* image width & height */
360 TIFFGetField(in
, TIFFTAG_IMAGEWIDTH
, &width
);
361 TIFFGetField(in
, TIFFTAG_IMAGELENGTH
, &height
);
362 pixel_count
= width
* height
;
364 /* XXX: Check the integer overflow. */
365 if (!width
|| !height
|| pixel_count
/ width
!= height
) {
366 TIFFError(TIFFFileName(in
),
367 "Malformed input file; can't allocate buffer for raster of %lux%lu size",
368 (unsigned long)width
, (unsigned long)height
);
372 rowsperstrip
= TIFFDefaultStripSize(out
, rowsperstrip
);
373 TIFFSetField(out
, TIFFTAG_ROWSPERSTRIP
, rowsperstrip
);
375 raster
= (uint32
*)_TIFFCheckMalloc(in
, pixel_count
, sizeof(uint32
), "raster buffer");
377 TIFFError(TIFFFileName(in
), "Failed to allocate buffer (%lu elements of %lu each)",
378 (unsigned long)pixel_count
, (unsigned long)sizeof(uint32
));
382 /* Read the image in one chunk into an RGBA array */
383 if (!TIFFReadRGBAImageOriented(in
, width
, height
, raster
,
384 ORIENTATION_TOPLEFT
, 0)) {
390 * XXX: raster array has 4-byte unsigned integer type, that is why
391 * we should rearrange it here.
394 TIFFSwabArrayOfLong(raster
, width
* height
);
398 * Do we want to strip away alpha components?
402 size_t count
= pixel_count
;
403 unsigned char *src
, *dst
;
405 src
= dst
= (unsigned char *) raster
;
417 * Write out the result in strips
419 for (row
= 0; row
< height
; row
+= rowsperstrip
)
421 unsigned char * raster_strip
;
427 raster_strip
= ((unsigned char *) raster
) + 3 * row
* width
;
432 raster_strip
= (unsigned char *) (raster
+ row
* width
);
436 if( row
+ rowsperstrip
> height
)
437 rows_to_write
= height
- row
;
439 rows_to_write
= rowsperstrip
;
441 if( TIFFWriteEncodedStrip( out
, row
/ rowsperstrip
, raster_strip
,
442 bytes_per_pixel
* rows_to_write
* width
) == -1 )
456 tiffcvt(TIFF
* in
, TIFF
* out
)
458 uint32 width
, height
; /* image width & height */
465 TIFFGetField(in
, TIFFTAG_IMAGEWIDTH
, &width
);
466 TIFFGetField(in
, TIFFTAG_IMAGELENGTH
, &height
);
468 CopyField(TIFFTAG_SUBFILETYPE
, longv
);
469 TIFFSetField(out
, TIFFTAG_IMAGEWIDTH
, width
);
470 TIFFSetField(out
, TIFFTAG_IMAGELENGTH
, height
);
471 TIFFSetField(out
, TIFFTAG_BITSPERSAMPLE
, 8);
472 TIFFSetField(out
, TIFFTAG_COMPRESSION
, compression
);
473 TIFFSetField(out
, TIFFTAG_PHOTOMETRIC
, PHOTOMETRIC_RGB
);
475 CopyField(TIFFTAG_FILLORDER
, shortv
);
476 TIFFSetField(out
, TIFFTAG_ORIENTATION
, ORIENTATION_TOPLEFT
);
479 TIFFSetField(out
, TIFFTAG_SAMPLESPERPIXEL
, 3);
481 TIFFSetField(out
, TIFFTAG_SAMPLESPERPIXEL
, 4);
485 v
[0] = EXTRASAMPLE_ASSOCALPHA
;
486 TIFFSetField(out
, TIFFTAG_EXTRASAMPLES
, 1, v
);
489 CopyField(TIFFTAG_XRESOLUTION
, floatv
);
490 CopyField(TIFFTAG_YRESOLUTION
, floatv
);
491 CopyField(TIFFTAG_RESOLUTIONUNIT
, shortv
);
492 TIFFSetField(out
, TIFFTAG_PLANARCONFIG
, PLANARCONFIG_CONTIG
);
493 TIFFSetField(out
, TIFFTAG_SOFTWARE
, TIFFGetVersion());
494 CopyField(TIFFTAG_DOCUMENTNAME
, stringv
);
496 if( process_by_block
&& TIFFIsTiled( in
) )
497 return( cvt_by_tile( in
, out
) );
498 else if( process_by_block
)
499 return( cvt_by_strip( in
, out
) );
501 return( cvt_whole_image( in
, out
) );
504 static char* stuff
[] = {
505 "usage: tiff2rgba [-c comp] [-r rows] [-b] [-n] [-8] input... output",
506 "where comp is one of the following compression algorithms:",
507 " jpeg\t\tJPEG encoding",
508 " zip\t\tLempel-Ziv & Welch encoding",
509 " lzw\t\tLempel-Ziv & Welch encoding",
510 " packbits\tPackBits encoding",
511 " none\t\tno compression",
512 "and the other options are:",
514 " -b (progress by block rather than as a whole image)",
515 " -n don't emit alpha component.",
516 " -8 write BigTIFF file instead of ClassicTIFF",
527 fprintf(stderr
, "%s\n\n", TIFFGetVersion());
528 for (i
= 0; stuff
[i
] != NULL
; i
++)
529 fprintf(stderr
, "%s\n", stuff
[i
]);
533 /* vim: set ts=8 sts=8 sw=8 noet: */