| 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 | */ |