]>
git.saurik.com Git - wxWidgets.git/blob - src/tiff/tools/tiff2rgba.c
4 * Copyright (c) 1991-1997 Sam Leffler
5 * Copyright (c) 1991-1997 Silicon Graphics, Inc.
7 * Permission to use, copy, modify, distribute, and sell this software and
8 * its documentation for any purpose is hereby granted without fee, provided
9 * that (i) the above copyright notices and this permission notice appear in
10 * all copies of the software and related documentation, and (ii) the names of
11 * Sam Leffler and Silicon Graphics may not be used in any advertising or
12 * publicity relating to the software without the specific, prior written
13 * permission of Sam Leffler and Silicon Graphics.
15 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
17 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
19 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
20 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
21 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
22 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
23 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
27 #include "tif_config.h"
44 #define streq(a,b) (strcmp(a,b) == 0)
45 #define CopyField(tag, v) \
46 if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
49 #define howmany(x, y) (((x)+((y)-1))/(y))
51 #define roundup(x, y) (howmany(x,y)*((uint32)(y)))
53 uint16 compression
= COMPRESSION_PACKBITS
;
54 uint32 rowsperstrip
= (uint32
) -1;
55 int process_by_block
= 0; /* default is whole image at once */
57 int bigtiff_output
= 0;
60 static int tiffcvt(TIFF
* in
, TIFF
* out
);
61 static void usage(int code
);
64 main(int argc
, char* argv
[])
71 while ((c
= getopt(argc
, argv
, "c:r:t:bn8")) != -1)
78 if (streq(optarg
, "none"))
79 compression
= COMPRESSION_NONE
;
80 else if (streq(optarg
, "packbits"))
81 compression
= COMPRESSION_PACKBITS
;
82 else if (streq(optarg
, "lzw"))
83 compression
= COMPRESSION_LZW
;
84 else if (streq(optarg
, "jpeg"))
85 compression
= COMPRESSION_JPEG
;
86 else if (streq(optarg
, "zip"))
87 compression
= COMPRESSION_DEFLATE
;
93 rowsperstrip
= atoi(optarg
);
97 rowsperstrip
= atoi(optarg
);
113 if (argc
- optind
< 2)
116 out
= TIFFOpen(argv
[argc
-1], bigtiff_output
?"w8":"w");
120 for (; optind
< argc
-1; optind
++) {
121 in
= TIFFOpen(argv
[optind
], "r");
124 if (!tiffcvt(in
, out
) ||
125 !TIFFWriteDirectory(out
)) {
126 (void) TIFFClose(out
);
127 (void) TIFFClose(in
);
130 } while (TIFFReadDirectory(in
));
131 (void) TIFFClose(in
);
134 (void) TIFFClose(out
);
139 cvt_by_tile( TIFF
*in
, TIFF
*out
)
142 uint32
* raster
; /* retrieve RGBA image */
143 uint32 width
, height
; /* image width & height */
144 uint32 tile_width
, tile_height
;
149 TIFFGetField(in
, TIFFTAG_IMAGEWIDTH
, &width
);
150 TIFFGetField(in
, TIFFTAG_IMAGELENGTH
, &height
);
152 if( !TIFFGetField(in
, TIFFTAG_TILEWIDTH
, &tile_width
)
153 || !TIFFGetField(in
, TIFFTAG_TILELENGTH
, &tile_height
) ) {
154 TIFFError(TIFFFileName(in
), "Source image not tiled");
158 TIFFSetField(out
, TIFFTAG_TILEWIDTH
, tile_width
);
159 TIFFSetField(out
, TIFFTAG_TILELENGTH
, tile_height
);
162 * Allocate tile buffer
164 raster
= (uint32
*)_TIFFmalloc(tile_width
* tile_height
* sizeof (uint32
));
166 TIFFError(TIFFFileName(in
), "No space for raster buffer");
171 * Allocate a scanline buffer for swapping during the vertical
174 wrk_line
= (uint32
*)_TIFFmalloc(tile_width
* sizeof (uint32
));
176 TIFFError(TIFFFileName(in
), "No space for raster scanline buffer");
181 * Loop over the tiles.
183 for( row
= 0; ok
&& row
< height
; row
+= tile_height
)
185 for( col
= 0; ok
&& col
< width
; col
+= tile_width
)
189 /* Read the tile into an RGBA array */
190 if (!TIFFReadRGBATile(in
, col
, row
, raster
)) {
197 * XXX: raster array has 4-byte unsigned integer type, that is why
198 * we should rearrange it here.
201 TIFFSwabArrayOfLong(raster
, tile_width
* tile_height
);
205 * For some reason the TIFFReadRGBATile() function chooses the
206 * lower left corner as the origin. Vertically mirror scanlines.
208 for( i_row
= 0; i_row
< tile_height
/ 2; i_row
++ )
210 uint32
*top_line
, *bottom_line
;
212 top_line
= raster
+ tile_width
* i_row
;
213 bottom_line
= raster
+ tile_width
* (tile_height
-i_row
-1);
215 _TIFFmemcpy(wrk_line
, top_line
, 4*tile_width
);
216 _TIFFmemcpy(top_line
, bottom_line
, 4*tile_width
);
217 _TIFFmemcpy(bottom_line
, wrk_line
, 4*tile_width
);
221 * Write out the result in a tile.
224 if( TIFFWriteEncodedTile( out
,
225 TIFFComputeTile( out
, col
, row
, 0, 0),
227 4 * tile_width
* tile_height
) == -1 )
236 _TIFFfree( wrk_line
);
242 cvt_by_strip( TIFF
*in
, TIFF
*out
)
245 uint32
* raster
; /* retrieve RGBA image */
246 uint32 width
, height
; /* image width & height */
251 TIFFGetField(in
, TIFFTAG_IMAGEWIDTH
, &width
);
252 TIFFGetField(in
, TIFFTAG_IMAGELENGTH
, &height
);
254 if( !TIFFGetField(in
, TIFFTAG_ROWSPERSTRIP
, &rowsperstrip
) ) {
255 TIFFError(TIFFFileName(in
), "Source image not in strips");
259 TIFFSetField(out
, TIFFTAG_ROWSPERSTRIP
, rowsperstrip
);
262 * Allocate strip buffer
264 raster
= (uint32
*)_TIFFmalloc(width
* rowsperstrip
* sizeof (uint32
));
266 TIFFError(TIFFFileName(in
), "No space for raster buffer");
271 * Allocate a scanline buffer for swapping during the vertical
274 wrk_line
= (uint32
*)_TIFFmalloc(width
* sizeof (uint32
));
276 TIFFError(TIFFFileName(in
), "No space for raster scanline buffer");
281 * Loop over the strips.
283 for( row
= 0; ok
&& row
< height
; row
+= rowsperstrip
)
285 int rows_to_write
, i_row
;
287 /* Read the strip into an RGBA array */
288 if (!TIFFReadRGBAStrip(in
, row
, raster
)) {
294 * XXX: raster array has 4-byte unsigned integer type, that is why
295 * we should rearrange it here.
298 TIFFSwabArrayOfLong(raster
, width
* rowsperstrip
);
302 * Figure out the number of scanlines actually in this strip.
304 if( row
+ rowsperstrip
> height
)
305 rows_to_write
= height
- row
;
307 rows_to_write
= rowsperstrip
;
310 * For some reason the TIFFReadRGBAStrip() function chooses the
311 * lower left corner as the origin. Vertically mirror scanlines.
314 for( i_row
= 0; i_row
< rows_to_write
/ 2; i_row
++ )
316 uint32
*top_line
, *bottom_line
;
318 top_line
= raster
+ width
* i_row
;
319 bottom_line
= raster
+ width
* (rows_to_write
-i_row
-1);
321 _TIFFmemcpy(wrk_line
, top_line
, 4*width
);
322 _TIFFmemcpy(top_line
, bottom_line
, 4*width
);
323 _TIFFmemcpy(bottom_line
, wrk_line
, 4*width
);
327 * Write out the result in a strip
330 if( TIFFWriteEncodedStrip( out
, row
/ rowsperstrip
, raster
,
331 4 * rows_to_write
* width
) == -1 )
339 _TIFFfree( wrk_line
);
347 * read the whole image into one big RGBA buffer and then write out
348 * strips from that. This is using the traditional TIFFReadRGBAImage()
353 cvt_whole_image( TIFF
*in
, TIFF
*out
)
356 uint32
* raster
; /* retrieve RGBA image */
357 uint32 width
, height
; /* image width & height */
361 TIFFGetField(in
, TIFFTAG_IMAGEWIDTH
, &width
);
362 TIFFGetField(in
, TIFFTAG_IMAGELENGTH
, &height
);
363 pixel_count
= width
* height
;
365 /* XXX: Check the integer overflow. */
366 if (!width
|| !height
|| pixel_count
/ width
!= height
) {
367 TIFFError(TIFFFileName(in
),
368 "Malformed input file; can't allocate buffer for raster of %lux%lu size",
369 (unsigned long)width
, (unsigned long)height
);
373 rowsperstrip
= TIFFDefaultStripSize(out
, rowsperstrip
);
374 TIFFSetField(out
, TIFFTAG_ROWSPERSTRIP
, rowsperstrip
);
376 raster
= (uint32
*)_TIFFCheckMalloc(in
, pixel_count
, sizeof(uint32
), "raster buffer");
378 TIFFError(TIFFFileName(in
), "Failed to allocate buffer (%lu elements of %lu each)",
379 (unsigned long)pixel_count
, (unsigned long)sizeof(uint32
));
383 /* Read the image in one chunk into an RGBA array */
384 if (!TIFFReadRGBAImageOriented(in
, width
, height
, raster
,
385 ORIENTATION_TOPLEFT
, 0)) {
391 * XXX: raster array has 4-byte unsigned integer type, that is why
392 * we should rearrange it here.
395 TIFFSwabArrayOfLong(raster
, width
* height
);
399 * Do we want to strip away alpha components?
403 size_t count
= pixel_count
;
404 unsigned char *src
, *dst
;
406 src
= dst
= (unsigned char *) raster
;
418 * Write out the result in strips
420 for (row
= 0; row
< height
; row
+= rowsperstrip
)
422 unsigned char * raster_strip
;
428 raster_strip
= ((unsigned char *) raster
) + 3 * row
* width
;
433 raster_strip
= (unsigned char *) (raster
+ row
* width
);
437 if( row
+ rowsperstrip
> height
)
438 rows_to_write
= height
- row
;
440 rows_to_write
= rowsperstrip
;
442 if( TIFFWriteEncodedStrip( out
, row
/ rowsperstrip
, raster_strip
,
443 bytes_per_pixel
* rows_to_write
* width
) == -1 )
457 tiffcvt(TIFF
* in
, TIFF
* out
)
459 uint32 width
, height
; /* image width & height */
466 TIFFGetField(in
, TIFFTAG_IMAGEWIDTH
, &width
);
467 TIFFGetField(in
, TIFFTAG_IMAGELENGTH
, &height
);
469 CopyField(TIFFTAG_SUBFILETYPE
, longv
);
470 TIFFSetField(out
, TIFFTAG_IMAGEWIDTH
, width
);
471 TIFFSetField(out
, TIFFTAG_IMAGELENGTH
, height
);
472 TIFFSetField(out
, TIFFTAG_BITSPERSAMPLE
, 8);
473 TIFFSetField(out
, TIFFTAG_COMPRESSION
, compression
);
474 TIFFSetField(out
, TIFFTAG_PHOTOMETRIC
, PHOTOMETRIC_RGB
);
476 CopyField(TIFFTAG_FILLORDER
, shortv
);
477 TIFFSetField(out
, TIFFTAG_ORIENTATION
, ORIENTATION_TOPLEFT
);
480 TIFFSetField(out
, TIFFTAG_SAMPLESPERPIXEL
, 3);
482 TIFFSetField(out
, TIFFTAG_SAMPLESPERPIXEL
, 4);
486 v
[0] = EXTRASAMPLE_ASSOCALPHA
;
487 TIFFSetField(out
, TIFFTAG_EXTRASAMPLES
, 1, v
);
490 CopyField(TIFFTAG_XRESOLUTION
, floatv
);
491 CopyField(TIFFTAG_YRESOLUTION
, floatv
);
492 CopyField(TIFFTAG_RESOLUTIONUNIT
, shortv
);
493 TIFFSetField(out
, TIFFTAG_PLANARCONFIG
, PLANARCONFIG_CONTIG
);
494 TIFFSetField(out
, TIFFTAG_SOFTWARE
, TIFFGetVersion());
495 CopyField(TIFFTAG_DOCUMENTNAME
, stringv
);
497 if( process_by_block
&& TIFFIsTiled( in
) )
498 return( cvt_by_tile( in
, out
) );
499 else if( process_by_block
)
500 return( cvt_by_strip( in
, out
) );
502 return( cvt_whole_image( in
, out
) );
505 static char* stuff
[] = {
506 "usage: tiff2rgba [-c comp] [-r rows] [-b] [-n] [-8] input... output",
507 "where comp is one of the following compression algorithms:",
508 " jpeg\t\tJPEG encoding",
509 " zip\t\tLempel-Ziv & Welch encoding",
510 " lzw\t\tLempel-Ziv & Welch encoding",
511 " packbits\tPackBits encoding",
512 " none\t\tno compression",
513 "and the other options are:",
515 " -b (progress by block rather than as a whole image)",
516 " -n don't emit alpha component.",
517 " -8 write BigTIFF file instead of ClassicTIFF",
528 fprintf(stderr
, "%s\n\n", TIFFGetVersion());
529 for (i
= 0; stuff
[i
] != NULL
; i
++)
530 fprintf(stderr
, "%s\n", stuff
[i
]);
534 /* vim: set ts=8 sts=8 sw=8 noet: */