File: | libs/tiff-4.0.2/tools/rgb2ycbcr.c |
Location: | line 268, column 18 |
Description: | Division by zero |
1 | /* $Id: rgb2ycbcr.c,v 1.14 2011-05-31 17:03:16 bfriesen Exp $ */ | |||
2 | ||||
3 | /* | |||
4 | * Copyright (c) 1991-1997 Sam Leffler | |||
5 | * Copyright (c) 1991-1997 Silicon Graphics, Inc. | |||
6 | * | |||
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. | |||
14 | * | |||
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. | |||
18 | * | |||
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 | |||
24 | * OF THIS SOFTWARE. | |||
25 | */ | |||
26 | ||||
27 | #include "tif_config.h" | |||
28 | ||||
29 | #include <stdio.h> | |||
30 | #include <string.h> | |||
31 | #include <stdlib.h> | |||
32 | ||||
33 | #ifdef HAVE_UNISTD_H1 | |||
34 | # include <unistd.h> | |||
35 | #endif | |||
36 | ||||
37 | #ifdef NEED_LIBPORT | |||
38 | # include "libport.h" | |||
39 | #endif | |||
40 | ||||
41 | #include "tiffiop.h" | |||
42 | #include "tiffio.h" | |||
43 | ||||
44 | #define streq(a,b)(__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (a) && __builtin_constant_p (b) && (__s1_len = __builtin_strlen (a), __s2_len = __builtin_strlen (b), (!( (size_t)(const void *)((a) + 1) - (size_t)(const void *)(a) == 1) || __s1_len >= 4) && (!((size_t)(const void *) ((b) + 1) - (size_t)(const void *)(b) == 1) || __s2_len >= 4)) ? __builtin_strcmp (a, b) : (__builtin_constant_p (a) && ((size_t)(const void *)((a) + 1) - (size_t)(const void *)(a) == 1) && (__s1_len = __builtin_strlen (a), __s1_len < 4) ? (__builtin_constant_p (b) && ((size_t)(const void *)((b) + 1) - (size_t)(const void *)(b) == 1) ? __builtin_strcmp (a, b) : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (b); int __result = (((const unsigned char *) (const char *) (a))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (a))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (a))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (a))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (b) && ((size_t)(const void *)((b) + 1) - (size_t)(const void *)(b) == 1) && (__s2_len = __builtin_strlen (b) , __s2_len < 4) ? (__builtin_constant_p (a) && ((size_t )(const void *)((a) + 1) - (size_t)(const void *)(a) == 1) ? __builtin_strcmp (a, b) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (a); int __result = (((const unsigned char *) (const char *) (b))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (b))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (b))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (b))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (a, b)))); }) == 0) (strcmp(a,b)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (a) && __builtin_constant_p (b) && (__s1_len = __builtin_strlen (a), __s2_len = __builtin_strlen (b), (!( (size_t)(const void *)((a) + 1) - (size_t)(const void *)(a) == 1) || __s1_len >= 4) && (!((size_t)(const void *) ((b) + 1) - (size_t)(const void *)(b) == 1) || __s2_len >= 4)) ? __builtin_strcmp (a, b) : (__builtin_constant_p (a) && ((size_t)(const void *)((a) + 1) - (size_t)(const void *)(a) == 1) && (__s1_len = __builtin_strlen (a), __s1_len < 4) ? (__builtin_constant_p (b) && ((size_t)(const void *)((b) + 1) - (size_t)(const void *)(b) == 1) ? __builtin_strcmp (a, b) : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (b); int __result = (((const unsigned char *) (const char *) (a))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (a))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (a))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (a))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (b) && ((size_t)(const void *)((b) + 1) - (size_t)(const void *)(b) == 1) && (__s2_len = __builtin_strlen (b) , __s2_len < 4) ? (__builtin_constant_p (a) && ((size_t )(const void *)((a) + 1) - (size_t)(const void *)(a) == 1) ? __builtin_strcmp (a, b) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (a); int __result = (((const unsigned char *) (const char *) (b))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (b))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (b))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (b))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (a, b)))); }) == 0) | |||
45 | #define CopyField(tag, v)if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v) \ | |||
46 | if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v) | |||
47 | ||||
48 | #ifndef howmany | |||
49 | #define howmany(x, y)(((x)+((y)-1))/(y)) (((x)+((y)-1))/(y)) | |||
50 | #endif | |||
51 | #define roundup(x, y)((((x)+((y)-1))/(y))*((uint32)(y))) (howmany(x,y)(((x)+((y)-1))/(y))*((uint32)(y))) | |||
52 | ||||
53 | #define LumaRed ycbcrCoeffs[0] | |||
54 | #define LumaGreen ycbcrCoeffs[1] | |||
55 | #define LumaBlue ycbcrCoeffs[2] | |||
56 | ||||
57 | uint16 compression = COMPRESSION_PACKBITS32773; | |||
58 | uint32 rowsperstrip = (uint32) -1; | |||
59 | ||||
60 | uint16 horizSubSampling = 2; /* YCbCr horizontal subsampling */ | |||
61 | uint16 vertSubSampling = 2; /* YCbCr vertical subsampling */ | |||
62 | float ycbcrCoeffs[3] = { .299F, .587F, .114F }; | |||
63 | /* default coding range is CCIR Rec 601-1 with no headroom/footroom */ | |||
64 | float refBlackWhite[6] = { 0.F, 255.F, 128.F, 255.F, 128.F, 255.F }; | |||
65 | ||||
66 | static int tiffcvt(TIFF* in, TIFF* out); | |||
67 | static void usage(int code); | |||
68 | static void setupLumaTables(void); | |||
69 | ||||
70 | int | |||
71 | main(int argc, char* argv[]) | |||
72 | { | |||
73 | TIFF *in, *out; | |||
74 | int c; | |||
75 | extern int optind; | |||
76 | extern char *optarg; | |||
77 | ||||
78 | while ((c = getopt(argc, argv, "c:h:r:v:z")) != -1) | |||
79 | switch (c) { | |||
80 | case 'c': | |||
81 | if (streq(optarg, "none")(__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (optarg) && __builtin_constant_p ("none") && (__s1_len = __builtin_strlen (optarg), __s2_len = __builtin_strlen ("none"), (!((size_t)(const void *)((optarg) + 1) - (size_t) (const void *)(optarg) == 1) || __s1_len >= 4) && ( !((size_t)(const void *)(("none") + 1) - (size_t)(const void * )("none") == 1) || __s2_len >= 4)) ? __builtin_strcmp (optarg , "none") : (__builtin_constant_p (optarg) && ((size_t )(const void *)((optarg) + 1) - (size_t)(const void *)(optarg ) == 1) && (__s1_len = __builtin_strlen (optarg), __s1_len < 4) ? (__builtin_constant_p ("none") && ((size_t )(const void *)(("none") + 1) - (size_t)(const void *)("none" ) == 1) ? __builtin_strcmp (optarg, "none") : (__extension__ ( { const unsigned char *__s2 = (const unsigned char *) (const char *) ("none"); int __result = (((const unsigned char *) (const char *) (optarg))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (optarg))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (optarg))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (optarg))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p ("none") && ((size_t)(const void *)(("none") + 1) - ( size_t)(const void *)("none") == 1) && (__s2_len = __builtin_strlen ("none"), __s2_len < 4) ? (__builtin_constant_p (optarg) && ((size_t)(const void *)((optarg) + 1) - (size_t)(const void * )(optarg) == 1) ? __builtin_strcmp (optarg, "none") : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (optarg); int __result = (((const unsigned char *) ( const char *) ("none"))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) ("none"))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) ("none"))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) ("none"))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (optarg, "none")))); }) == 0)) | |||
82 | compression = COMPRESSION_NONE1; | |||
83 | else if (streq(optarg, "packbits")(__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (optarg) && __builtin_constant_p ("packbits") && (__s1_len = __builtin_strlen (optarg), __s2_len = __builtin_strlen ("packbits"), (!((size_t)(const void *)((optarg) + 1) - (size_t )(const void *)(optarg) == 1) || __s1_len >= 4) && (!((size_t)(const void *)(("packbits") + 1) - (size_t)(const void *)("packbits") == 1) || __s2_len >= 4)) ? __builtin_strcmp (optarg, "packbits") : (__builtin_constant_p (optarg) && ((size_t)(const void *)((optarg) + 1) - (size_t)(const void * )(optarg) == 1) && (__s1_len = __builtin_strlen (optarg ), __s1_len < 4) ? (__builtin_constant_p ("packbits") && ((size_t)(const void *)(("packbits") + 1) - (size_t)(const void *)("packbits") == 1) ? __builtin_strcmp (optarg, "packbits") : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) ("packbits"); int __result = (((const unsigned char *) (const char *) (optarg))[0] - __s2[0]); if ( __s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (optarg))[1] - __s2[1]); if ( __s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (optarg))[2] - __s2[2]); if ( __s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (optarg))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p ("packbits") && ((size_t)(const void *)(("packbits") + 1) - (size_t)(const void *)("packbits") == 1) && (__s2_len = __builtin_strlen ("packbits"), __s2_len < 4) ? (__builtin_constant_p (optarg ) && ((size_t)(const void *)((optarg) + 1) - (size_t) (const void *)(optarg) == 1) ? __builtin_strcmp (optarg, "packbits" ) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (optarg); int __result = (((const unsigned char *) (const char *) ("packbits"))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) ("packbits"))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) ("packbits"))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) ("packbits"))[3] - __s2[3]); } } __result ; })))) : __builtin_strcmp (optarg, "packbits")))); }) == 0)) | |||
84 | compression = COMPRESSION_PACKBITS32773; | |||
85 | else if (streq(optarg, "lzw")(__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (optarg) && __builtin_constant_p ("lzw") && ( __s1_len = __builtin_strlen (optarg), __s2_len = __builtin_strlen ("lzw"), (!((size_t)(const void *)((optarg) + 1) - (size_t)( const void *)(optarg) == 1) || __s1_len >= 4) && ( !((size_t)(const void *)(("lzw") + 1) - (size_t)(const void * )("lzw") == 1) || __s2_len >= 4)) ? __builtin_strcmp (optarg , "lzw") : (__builtin_constant_p (optarg) && ((size_t )(const void *)((optarg) + 1) - (size_t)(const void *)(optarg ) == 1) && (__s1_len = __builtin_strlen (optarg), __s1_len < 4) ? (__builtin_constant_p ("lzw") && ((size_t) (const void *)(("lzw") + 1) - (size_t)(const void *)("lzw") == 1) ? __builtin_strcmp (optarg, "lzw") : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) ("lzw"); int __result = (((const unsigned char *) (const char *) (optarg))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) ( optarg))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) ( optarg))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (optarg ))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p ( "lzw") && ((size_t)(const void *)(("lzw") + 1) - (size_t )(const void *)("lzw") == 1) && (__s2_len = __builtin_strlen ("lzw"), __s2_len < 4) ? (__builtin_constant_p (optarg) && ((size_t)(const void *)((optarg) + 1) - (size_t)(const void * )(optarg) == 1) ? __builtin_strcmp (optarg, "lzw") : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (optarg); int __result = (((const unsigned char *) ( const char *) ("lzw"))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) ("lzw"))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) ("lzw"))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) ("lzw"))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (optarg, "lzw")))); }) == 0)) | |||
86 | compression = COMPRESSION_LZW5; | |||
87 | else if (streq(optarg, "jpeg")(__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (optarg) && __builtin_constant_p ("jpeg") && (__s1_len = __builtin_strlen (optarg), __s2_len = __builtin_strlen ("jpeg"), (!((size_t)(const void *)((optarg) + 1) - (size_t) (const void *)(optarg) == 1) || __s1_len >= 4) && ( !((size_t)(const void *)(("jpeg") + 1) - (size_t)(const void * )("jpeg") == 1) || __s2_len >= 4)) ? __builtin_strcmp (optarg , "jpeg") : (__builtin_constant_p (optarg) && ((size_t )(const void *)((optarg) + 1) - (size_t)(const void *)(optarg ) == 1) && (__s1_len = __builtin_strlen (optarg), __s1_len < 4) ? (__builtin_constant_p ("jpeg") && ((size_t )(const void *)(("jpeg") + 1) - (size_t)(const void *)("jpeg" ) == 1) ? __builtin_strcmp (optarg, "jpeg") : (__extension__ ( { const unsigned char *__s2 = (const unsigned char *) (const char *) ("jpeg"); int __result = (((const unsigned char *) (const char *) (optarg))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (optarg))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (optarg))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (optarg))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p ("jpeg") && ((size_t)(const void *)(("jpeg") + 1) - ( size_t)(const void *)("jpeg") == 1) && (__s2_len = __builtin_strlen ("jpeg"), __s2_len < 4) ? (__builtin_constant_p (optarg) && ((size_t)(const void *)((optarg) + 1) - (size_t)(const void * )(optarg) == 1) ? __builtin_strcmp (optarg, "jpeg") : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (optarg); int __result = (((const unsigned char *) ( const char *) ("jpeg"))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) ("jpeg"))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) ("jpeg"))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) ("jpeg"))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (optarg, "jpeg")))); }) == 0)) | |||
88 | compression = COMPRESSION_JPEG7; | |||
89 | else if (streq(optarg, "zip")(__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (optarg) && __builtin_constant_p ("zip") && ( __s1_len = __builtin_strlen (optarg), __s2_len = __builtin_strlen ("zip"), (!((size_t)(const void *)((optarg) + 1) - (size_t)( const void *)(optarg) == 1) || __s1_len >= 4) && ( !((size_t)(const void *)(("zip") + 1) - (size_t)(const void * )("zip") == 1) || __s2_len >= 4)) ? __builtin_strcmp (optarg , "zip") : (__builtin_constant_p (optarg) && ((size_t )(const void *)((optarg) + 1) - (size_t)(const void *)(optarg ) == 1) && (__s1_len = __builtin_strlen (optarg), __s1_len < 4) ? (__builtin_constant_p ("zip") && ((size_t) (const void *)(("zip") + 1) - (size_t)(const void *)("zip") == 1) ? __builtin_strcmp (optarg, "zip") : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) ("zip"); int __result = (((const unsigned char *) (const char *) (optarg))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) ( optarg))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) ( optarg))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (optarg ))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p ( "zip") && ((size_t)(const void *)(("zip") + 1) - (size_t )(const void *)("zip") == 1) && (__s2_len = __builtin_strlen ("zip"), __s2_len < 4) ? (__builtin_constant_p (optarg) && ((size_t)(const void *)((optarg) + 1) - (size_t)(const void * )(optarg) == 1) ? __builtin_strcmp (optarg, "zip") : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (optarg); int __result = (((const unsigned char *) ( const char *) ("zip"))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) ("zip"))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) ("zip"))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) ("zip"))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (optarg, "zip")))); }) == 0)) | |||
90 | compression = COMPRESSION_ADOBE_DEFLATE8; | |||
91 | else | |||
92 | usage(-1); | |||
93 | break; | |||
94 | case 'h': | |||
95 | horizSubSampling = atoi(optarg); | |||
96 | break; | |||
97 | case 'v': | |||
98 | vertSubSampling = atoi(optarg); | |||
99 | break; | |||
100 | case 'r': | |||
101 | rowsperstrip = atoi(optarg); | |||
102 | break; | |||
103 | case 'z': /* CCIR Rec 601-1 w/ headroom/footroom */ | |||
104 | refBlackWhite[0] = 16.; | |||
105 | refBlackWhite[1] = 235.; | |||
106 | refBlackWhite[2] = 128.; | |||
107 | refBlackWhite[3] = 240.; | |||
108 | refBlackWhite[4] = 128.; | |||
109 | refBlackWhite[5] = 240.; | |||
110 | break; | |||
111 | case '?': | |||
112 | usage(0); | |||
113 | /*NOTREACHED*/ | |||
114 | } | |||
115 | if (argc - optind < 2) | |||
116 | usage(-1); | |||
117 | out = TIFFOpen(argv[argc-1], "w"); | |||
118 | if (out == NULL((void*)0)) | |||
119 | return (-2); | |||
120 | setupLumaTables(); | |||
121 | for (; optind < argc-1; optind++) { | |||
122 | in = TIFFOpen(argv[optind], "r"); | |||
123 | if (in != NULL((void*)0)) { | |||
124 | do { | |||
125 | if (!tiffcvt(in, out) || | |||
126 | !TIFFWriteDirectory(out)) { | |||
127 | (void) TIFFClose(out); | |||
128 | return (1); | |||
129 | } | |||
130 | } while (TIFFReadDirectory(in)); | |||
131 | (void) TIFFClose(in); | |||
132 | } | |||
133 | } | |||
134 | (void) TIFFClose(out); | |||
135 | return (0); | |||
136 | } | |||
137 | ||||
138 | float *lumaRed; | |||
139 | float *lumaGreen; | |||
140 | float *lumaBlue; | |||
141 | float D1, D2; | |||
142 | int Yzero; | |||
143 | ||||
144 | static float* | |||
145 | setupLuma(float c) | |||
146 | { | |||
147 | float *v = (float *)_TIFFmalloc(256 * sizeof (float)); | |||
148 | int i; | |||
149 | for (i = 0; i < 256; i++) | |||
150 | v[i] = c * i; | |||
151 | return (v); | |||
152 | } | |||
153 | ||||
154 | static unsigned | |||
155 | V2Code(float f, float RB, float RW, int CR) | |||
156 | { | |||
157 | unsigned int c = (unsigned int)((((f)*(RW-RB)/CR)+RB)+.5); | |||
158 | return (c > 255 ? 255 : c); | |||
159 | } | |||
160 | ||||
161 | static void | |||
162 | setupLumaTables(void) | |||
163 | { | |||
164 | lumaRed = setupLuma(LumaRed); | |||
165 | lumaGreen = setupLuma(LumaGreen); | |||
166 | lumaBlue = setupLuma(LumaBlue); | |||
167 | D1 = 1.F/(2.F - 2.F*LumaBlue); | |||
168 | D2 = 1.F/(2.F - 2.F*LumaRed); | |||
169 | Yzero = V2Code(0, refBlackWhite[0], refBlackWhite[1], 255); | |||
170 | } | |||
171 | ||||
172 | static void | |||
173 | cvtClump(unsigned char* op, uint32* raster, uint32 ch, uint32 cw, uint32 w) | |||
174 | { | |||
175 | float Y, Cb = 0, Cr = 0; | |||
176 | uint32 j, k; | |||
177 | /* | |||
178 | * Convert ch-by-cw block of RGB | |||
179 | * to YCbCr and sample accordingly. | |||
180 | */ | |||
181 | for (k = 0; k < ch; k++) { | |||
182 | for (j = 0; j < cw; j++) { | |||
183 | uint32 RGB = (raster - k*w)[j]; | |||
184 | Y = lumaRed[TIFFGetR(RGB)((RGB) & 0xff)] + | |||
185 | lumaGreen[TIFFGetG(RGB)(((RGB) >> 8) & 0xff)] + | |||
186 | lumaBlue[TIFFGetB(RGB)(((RGB) >> 16) & 0xff)]; | |||
187 | /* accumulate chrominance */ | |||
188 | Cb += (TIFFGetB(RGB)(((RGB) >> 16) & 0xff) - Y) * D1; | |||
189 | Cr += (TIFFGetR(RGB)((RGB) & 0xff) - Y) * D2; | |||
190 | /* emit luminence */ | |||
191 | *op++ = V2Code(Y, | |||
192 | refBlackWhite[0], refBlackWhite[1], 255); | |||
193 | } | |||
194 | for (; j < horizSubSampling; j++) | |||
195 | *op++ = Yzero; | |||
196 | } | |||
197 | for (; k < vertSubSampling; k++) { | |||
198 | for (j = 0; j < horizSubSampling; j++) | |||
199 | *op++ = Yzero; | |||
200 | } | |||
201 | /* emit sampled chrominance values */ | |||
202 | *op++ = V2Code(Cb / (ch*cw), refBlackWhite[2], refBlackWhite[3], 127); | |||
203 | *op++ = V2Code(Cr / (ch*cw), refBlackWhite[4], refBlackWhite[5], 127); | |||
204 | } | |||
205 | #undef LumaRed | |||
206 | #undef LumaGreen | |||
207 | #undef LumaBlue | |||
208 | #undef V2Code | |||
209 | ||||
210 | /* | |||
211 | * Convert a strip of RGB data to YCbCr and | |||
212 | * sample to generate the output data. | |||
213 | */ | |||
214 | static void | |||
215 | cvtStrip(unsigned char* op, uint32* raster, uint32 nrows, uint32 width) | |||
216 | { | |||
217 | uint32 x; | |||
218 | int clumpSize = vertSubSampling * horizSubSampling + 2; | |||
219 | uint32 *tp; | |||
220 | ||||
221 | for (; nrows >= vertSubSampling; nrows -= vertSubSampling) { | |||
222 | tp = raster; | |||
223 | for (x = width; x >= horizSubSampling; x -= horizSubSampling) { | |||
224 | cvtClump(op, tp, | |||
225 | vertSubSampling, horizSubSampling, width); | |||
226 | op += clumpSize; | |||
227 | tp += horizSubSampling; | |||
228 | } | |||
229 | if (x > 0) { | |||
230 | cvtClump(op, tp, vertSubSampling, x, width); | |||
231 | op += clumpSize; | |||
232 | } | |||
233 | raster -= vertSubSampling*width; | |||
234 | } | |||
235 | if (nrows > 0) { | |||
236 | tp = raster; | |||
237 | for (x = width; x >= horizSubSampling; x -= horizSubSampling) { | |||
238 | cvtClump(op, tp, nrows, horizSubSampling, width); | |||
239 | op += clumpSize; | |||
240 | tp += horizSubSampling; | |||
241 | } | |||
242 | if (x > 0) | |||
243 | cvtClump(op, tp, nrows, x, width); | |||
244 | } | |||
245 | } | |||
246 | ||||
247 | static int | |||
248 | cvtRaster(TIFF* tif, uint32* raster, uint32 width, uint32 height) | |||
249 | { | |||
250 | uint32 y; | |||
251 | tstrip_t strip = 0; | |||
252 | tsize_t cc, acc; | |||
253 | unsigned char* buf; | |||
254 | uint32 rwidth = roundup(width, horizSubSampling)((((width)+((horizSubSampling)-1))/(horizSubSampling))*((uint32 )(horizSubSampling))); | |||
255 | uint32 rheight = roundup(height, vertSubSampling)((((height)+((vertSubSampling)-1))/(vertSubSampling))*((uint32 )(vertSubSampling))); | |||
256 | uint32 nrows = (rowsperstrip > rheight ? rheight : rowsperstrip); | |||
257 | uint32 rnrows = roundup(nrows,vertSubSampling)((((nrows)+((vertSubSampling)-1))/(vertSubSampling))*((uint32 )(vertSubSampling))); | |||
258 | ||||
259 | cc = rnrows*rwidth + | |||
260 | 2*((rnrows*rwidth) / (horizSubSampling*vertSubSampling)); | |||
261 | buf = (unsigned char*)_TIFFmalloc(cc); | |||
262 | // FIXME unchecked malloc | |||
263 | for (y = height; (int32) y > 0; y -= nrows) { | |||
264 | uint32 nr = (y > nrows ? nrows : y); | |||
265 | cvtStrip(buf, raster + (y-1)*width, nr, width); | |||
266 | nr = roundup(nr, vertSubSampling)((((nr)+((vertSubSampling)-1))/(vertSubSampling))*((uint32)(vertSubSampling ))); | |||
267 | acc = nr*rwidth + | |||
268 | 2*((nr*rwidth)/(horizSubSampling*vertSubSampling)); | |||
| ||||
269 | if (!TIFFWriteEncodedStrip(tif, strip++, buf, acc)) { | |||
270 | _TIFFfree(buf); | |||
271 | return (0); | |||
272 | } | |||
273 | } | |||
274 | _TIFFfree(buf); | |||
275 | return (1); | |||
276 | } | |||
277 | ||||
278 | static int | |||
279 | tiffcvt(TIFF* in, TIFF* out) | |||
280 | { | |||
281 | uint32 width, height; /* image width & height */ | |||
282 | uint32* raster; /* retrieve RGBA image */ | |||
283 | uint16 shortv; | |||
284 | float floatv; | |||
285 | char *stringv; | |||
286 | uint32 longv; | |||
287 | int result; | |||
288 | size_t pixel_count; | |||
289 | ||||
290 | TIFFGetField(in, TIFFTAG_IMAGEWIDTH256, &width); | |||
291 | TIFFGetField(in, TIFFTAG_IMAGELENGTH257, &height); | |||
292 | pixel_count = width * height; | |||
293 | ||||
294 | /* XXX: Check the integer overflow. */ | |||
295 | if (!width || !height || pixel_count / width != height) { | |||
| ||||
296 | TIFFError(TIFFFileName(in), | |||
297 | "Malformed input file; " | |||
298 | "can't allocate buffer for raster of %lux%lu size", | |||
299 | (unsigned long)width, (unsigned long)height); | |||
300 | return 0; | |||
301 | } | |||
302 | ||||
303 | raster = (uint32*)_TIFFCheckMalloc(in, pixel_count, sizeof(uint32), | |||
304 | "raster buffer"); | |||
305 | if (raster == 0) { | |||
306 | TIFFError(TIFFFileName(in), | |||
307 | "Failed to allocate buffer (%lu elements of %lu each)", | |||
308 | (unsigned long)pixel_count, | |||
309 | (unsigned long)sizeof(uint32)); | |||
310 | return (0); | |||
311 | } | |||
312 | ||||
313 | if (!TIFFReadRGBAImage(in, width, height, raster, 0)) { | |||
314 | _TIFFfree(raster); | |||
315 | return (0); | |||
316 | } | |||
317 | ||||
318 | CopyField(TIFFTAG_SUBFILETYPE, longv)if (TIFFGetField(in, 254, &longv)) TIFFSetField(out, 254, longv); | |||
319 | TIFFSetField(out, TIFFTAG_IMAGEWIDTH256, width); | |||
320 | TIFFSetField(out, TIFFTAG_IMAGELENGTH257, height); | |||
321 | TIFFSetField(out, TIFFTAG_BITSPERSAMPLE258, 8); | |||
322 | TIFFSetField(out, TIFFTAG_COMPRESSION259, compression); | |||
323 | TIFFSetField(out, TIFFTAG_PHOTOMETRIC262, PHOTOMETRIC_YCBCR6); | |||
324 | if (compression == COMPRESSION_JPEG7) | |||
325 | TIFFSetField(out, TIFFTAG_JPEGCOLORMODE65538, JPEGCOLORMODE_RAW0x0000); | |||
326 | CopyField(TIFFTAG_FILLORDER, shortv)if (TIFFGetField(in, 266, &shortv)) TIFFSetField(out, 266 , shortv); | |||
327 | TIFFSetField(out, TIFFTAG_ORIENTATION274, ORIENTATION_TOPLEFT1); | |||
328 | TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL277, 3); | |||
329 | CopyField(TIFFTAG_XRESOLUTION, floatv)if (TIFFGetField(in, 282, &floatv)) TIFFSetField(out, 282 , floatv); | |||
330 | CopyField(TIFFTAG_YRESOLUTION, floatv)if (TIFFGetField(in, 283, &floatv)) TIFFSetField(out, 283 , floatv); | |||
331 | CopyField(TIFFTAG_RESOLUTIONUNIT, shortv)if (TIFFGetField(in, 296, &shortv)) TIFFSetField(out, 296 , shortv); | |||
332 | TIFFSetField(out, TIFFTAG_PLANARCONFIG284, PLANARCONFIG_CONTIG1); | |||
333 | { char buf[2048]; | |||
334 | char *cp = strrchr(TIFFFileName(in), '/'); | |||
335 | sprintf(buf, "YCbCr conversion of %s", cp ? cp+1 : TIFFFileName(in)); | |||
336 | TIFFSetField(out, TIFFTAG_IMAGEDESCRIPTION270, buf); | |||
337 | } | |||
338 | TIFFSetField(out, TIFFTAG_SOFTWARE305, TIFFGetVersion()); | |||
339 | CopyField(TIFFTAG_DOCUMENTNAME, stringv)if (TIFFGetField(in, 269, &stringv)) TIFFSetField(out, 269 , stringv); | |||
340 | ||||
341 | TIFFSetField(out, TIFFTAG_REFERENCEBLACKWHITE532, refBlackWhite); | |||
342 | TIFFSetField(out, TIFFTAG_YCBCRSUBSAMPLING530, | |||
343 | horizSubSampling, vertSubSampling); | |||
344 | TIFFSetField(out, TIFFTAG_YCBCRPOSITIONING531, YCBCRPOSITION_CENTERED1); | |||
345 | TIFFSetField(out, TIFFTAG_YCBCRCOEFFICIENTS529, ycbcrCoeffs); | |||
346 | rowsperstrip = TIFFDefaultStripSize(out, rowsperstrip); | |||
347 | TIFFSetField(out, TIFFTAG_ROWSPERSTRIP278, rowsperstrip); | |||
348 | ||||
349 | result = cvtRaster(out, raster, width, height); | |||
350 | _TIFFfree(raster); | |||
351 | return result; | |||
352 | } | |||
353 | ||||
354 | char* stuff[] = { | |||
355 | "usage: rgb2ycbcr [-c comp] [-r rows] [-h N] [-v N] input... output\n", | |||
356 | "where comp is one of the following compression algorithms:\n", | |||
357 | " jpeg\t\tJPEG encoding\n", | |||
358 | " lzw\t\tLempel-Ziv & Welch encoding\n", | |||
359 | " zip\t\tdeflate encoding\n", | |||
360 | " packbits\tPackBits encoding (default)\n", | |||
361 | " none\t\tno compression\n", | |||
362 | "and the other options are:\n", | |||
363 | " -r\trows/strip\n", | |||
364 | " -h\thorizontal sampling factor (1,2,4)\n", | |||
365 | " -v\tvertical sampling factor (1,2,4)\n", | |||
366 | NULL((void*)0) | |||
367 | }; | |||
368 | ||||
369 | static void | |||
370 | usage(int code) | |||
371 | { | |||
372 | char buf[BUFSIZ8192]; | |||
373 | int i; | |||
374 | ||||
375 | setbuf(stderrstderr, buf); | |||
376 | ||||
377 | fprintf(stderrstderr, "%s\n\n", TIFFGetVersion()); | |||
378 | for (i = 0; stuff[i] != NULL((void*)0); i++) | |||
379 | fprintf(stderrstderr, "%s\n", stuff[i]); | |||
380 | exit(code); | |||
381 | } | |||
382 | ||||
383 | /* vim: set ts=8 sts=8 sw=8 noet: */ | |||
384 | /* | |||
385 | * Local Variables: | |||
386 | * mode: c | |||
387 | * c-basic-offset: 8 | |||
388 | * fill-column: 78 | |||
389 | * End: | |||
390 | */ |