📄 tif_getimage.c
字号:
DECLAREContigPutFunc(putcontig8bitYCbCr44tile){ YCbCrSetup; uint32* cp1 = cp+w+toskew; uint32* cp2 = cp1+w+toskew; uint32* cp3 = cp2+w+toskew; int32 incr = 3*w+4*toskew; (void) y; /* adjust fromskew */ fromskew = (fromskew * 18) / 4; if ((h & 3) == 0 && (w & 3) == 0) { for (; h >= 4; h -= 4) { x = w>>2; do { int Cb = pp[16]; int Cr = pp[17]; YCbCrtoRGB(cp [0], pp[ 0]); YCbCrtoRGB(cp [1], pp[ 1]); YCbCrtoRGB(cp [2], pp[ 2]); YCbCrtoRGB(cp [3], pp[ 3]); YCbCrtoRGB(cp1[0], pp[ 4]); YCbCrtoRGB(cp1[1], pp[ 5]); YCbCrtoRGB(cp1[2], pp[ 6]); YCbCrtoRGB(cp1[3], pp[ 7]); YCbCrtoRGB(cp2[0], pp[ 8]); YCbCrtoRGB(cp2[1], pp[ 9]); YCbCrtoRGB(cp2[2], pp[10]); YCbCrtoRGB(cp2[3], pp[11]); YCbCrtoRGB(cp3[0], pp[12]); YCbCrtoRGB(cp3[1], pp[13]); YCbCrtoRGB(cp3[2], pp[14]); YCbCrtoRGB(cp3[3], pp[15]); cp += 4, cp1 += 4, cp2 += 4, cp3 += 4; pp += 18; } while (--x); cp += incr, cp1 += incr, cp2 += incr, cp3 += incr; pp += fromskew; } } else { while (h > 0) { for (x = w; x > 0;) { int Cb = pp[16]; int Cr = pp[17]; switch (x) { default: switch (h) { default: YCbCrtoRGB(cp3[3], pp[15]); /* FALLTHROUGH */ case 3: YCbCrtoRGB(cp2[3], pp[11]); /* FALLTHROUGH */ case 2: YCbCrtoRGB(cp1[3], pp[ 7]); /* FALLTHROUGH */ case 1: YCbCrtoRGB(cp [3], pp[ 3]); /* FALLTHROUGH */ } /* FALLTHROUGH */ case 3: switch (h) { default: YCbCrtoRGB(cp3[2], pp[14]); /* FALLTHROUGH */ case 3: YCbCrtoRGB(cp2[2], pp[10]); /* FALLTHROUGH */ case 2: YCbCrtoRGB(cp1[2], pp[ 6]); /* FALLTHROUGH */ case 1: YCbCrtoRGB(cp [2], pp[ 2]); /* FALLTHROUGH */ } /* FALLTHROUGH */ case 2: switch (h) { default: YCbCrtoRGB(cp3[1], pp[13]); /* FALLTHROUGH */ case 3: YCbCrtoRGB(cp2[1], pp[ 9]); /* FALLTHROUGH */ case 2: YCbCrtoRGB(cp1[1], pp[ 5]); /* FALLTHROUGH */ case 1: YCbCrtoRGB(cp [1], pp[ 1]); /* FALLTHROUGH */ } /* FALLTHROUGH */ case 1: switch (h) { default: YCbCrtoRGB(cp3[0], pp[12]); /* FALLTHROUGH */ case 3: YCbCrtoRGB(cp2[0], pp[ 8]); /* FALLTHROUGH */ case 2: YCbCrtoRGB(cp1[0], pp[ 4]); /* FALLTHROUGH */ case 1: YCbCrtoRGB(cp [0], pp[ 0]); /* FALLTHROUGH */ } /* FALLTHROUGH */ } if (x < 4) { cp += x; cp1 += x; cp2 += x; cp3 += x; x = 0; } else { cp += 4; cp1 += 4; cp2 += 4; cp3 += 4; x -= 4; } pp += 18; } if (h <= 4) break; h -= 4; cp += incr, cp1 += incr, cp2 += incr, cp3 += incr; pp += fromskew; } }}/* * 8-bit packed YCbCr samples w/ 4,2 subsampling => RGB */DECLAREContigPutFunc(putcontig8bitYCbCr42tile){ YCbCrSetup; uint32* cp1 = cp+w+toskew; int32 incr = 2*toskew+w; (void) y; fromskew = (fromskew * 10) / 4; if ((h & 3) == 0 && (w & 1) == 0) { for (; h >= 2; h -= 2) { x = w>>2; do { int Cb = pp[8]; int Cr = pp[9]; YCbCrtoRGB(cp [0], pp[0]); YCbCrtoRGB(cp [1], pp[1]); YCbCrtoRGB(cp [2], pp[2]); YCbCrtoRGB(cp [3], pp[3]); YCbCrtoRGB(cp1[0], pp[4]); YCbCrtoRGB(cp1[1], pp[5]); YCbCrtoRGB(cp1[2], pp[6]); YCbCrtoRGB(cp1[3], pp[7]); cp += 4, cp1 += 4; pp += 10; } while (--x); cp += incr, cp1 += incr; pp += fromskew; } } else { while (h > 0) { for (x = w; x > 0;) { int Cb = pp[8]; int Cr = pp[9]; switch (x) { default: switch (h) { default: YCbCrtoRGB(cp1[3], pp[ 7]); /* FALLTHROUGH */ case 1: YCbCrtoRGB(cp [3], pp[ 3]); /* FALLTHROUGH */ } /* FALLTHROUGH */ case 3: switch (h) { default: YCbCrtoRGB(cp1[2], pp[ 6]); /* FALLTHROUGH */ case 1: YCbCrtoRGB(cp [2], pp[ 2]); /* FALLTHROUGH */ } /* FALLTHROUGH */ case 2: switch (h) { default: YCbCrtoRGB(cp1[1], pp[ 5]); /* FALLTHROUGH */ case 1: YCbCrtoRGB(cp [1], pp[ 1]); /* FALLTHROUGH */ } /* FALLTHROUGH */ case 1: switch (h) { default: YCbCrtoRGB(cp1[0], pp[ 4]); /* FALLTHROUGH */ case 1: YCbCrtoRGB(cp [0], pp[ 0]); /* FALLTHROUGH */ } /* FALLTHROUGH */ } if (x < 4) { cp += x; cp1 += x; x = 0; } else { cp += 4; cp1 += 4; x -= 4; } pp += 10; } if (h <= 2) break; h -= 2; cp += incr, cp1 += incr; pp += fromskew; } }}/* * 8-bit packed YCbCr samples w/ 4,1 subsampling => RGB */DECLAREContigPutFunc(putcontig8bitYCbCr41tile){ YCbCrSetup; (void) y; /* XXX adjust fromskew */ do { x = w>>2; do { int Cb = pp[4]; int Cr = pp[5]; YCbCrtoRGB(cp [0], pp[0]); YCbCrtoRGB(cp [1], pp[1]); YCbCrtoRGB(cp [2], pp[2]); YCbCrtoRGB(cp [3], pp[3]); cp += 4; pp += 6; } while (--x); if( (w&3) != 0 ) { int Cb = pp[4]; int Cr = pp[5]; switch( (w&3) ) { case 3: YCbCrtoRGB(cp [2], pp[2]); case 2: YCbCrtoRGB(cp [1], pp[1]); case 1: YCbCrtoRGB(cp [0], pp[0]); case 0: break; } cp += (w&3); pp += 6; } cp += toskew; pp += fromskew; } while (--h);}/* * 8-bit packed YCbCr samples w/ 2,2 subsampling => RGB */DECLAREContigPutFunc(putcontig8bitYCbCr22tile){ YCbCrSetup; uint32* cp1 = cp+w+toskew; int32 incr = 2*toskew+w; (void) y; fromskew = (fromskew * 6) / 2; if ((h & 1) == 0 && (w & 1) == 0) { for (; h >= 2; h -= 2) { x = w>>1; do { int Cb = pp[4]; int Cr = pp[5]; YCbCrtoRGB(cp [0], pp[0]); YCbCrtoRGB(cp [1], pp[1]); YCbCrtoRGB(cp1[0], pp[2]); YCbCrtoRGB(cp1[1], pp[3]); cp += 2, cp1 += 2; pp += 6; } while (--x); cp += incr, cp1 += incr; pp += fromskew; } } else { while (h > 0) { for (x = w; x > 0;) { int Cb = pp[4]; int Cr = pp[5]; switch (x) { default: switch (h) { default: YCbCrtoRGB(cp1[1], pp[ 3]); /* FALLTHROUGH */ case 1: YCbCrtoRGB(cp [1], pp[ 1]); /* FALLTHROUGH */ } /* FALLTHROUGH */ case 1: switch (h) { default: YCbCrtoRGB(cp1[0], pp[ 2]); /* FALLTHROUGH */ case 1: YCbCrtoRGB(cp [0], pp[ 0]); /* FALLTHROUGH */ } /* FALLTHROUGH */ } if (x < 2) { cp += x; cp1 += x; x = 0; } else { cp += 2; cp1 += 2; x -= 2; } pp += 6; } if (h <= 2) break; h -= 2; cp += incr, cp1 += incr; pp += fromskew; } }}/* * 8-bit packed YCbCr samples w/ 2,1 subsampling => RGB */DECLAREContigPutFunc(putcontig8bitYCbCr21tile){ YCbCrSetup; (void) y; fromskew = (fromskew * 4) / 2; do { x = w>>1; do { int Cb = pp[2]; int Cr = pp[3]; YCbCrtoRGB(cp[0], pp[0]); YCbCrtoRGB(cp[1], pp[1]); cp += 2; pp += 4; } while (--x); if( (w&1) != 0 ) { int Cb = pp[2]; int Cr = pp[3]; YCbCrtoRGB(cp [0], pp[0]); cp += 1; pp += 4; } cp += toskew; pp += fromskew; } while (--h);}/* * 8-bit packed YCbCr samples w/ no subsampling => RGB */DECLAREContigPutFunc(putcontig8bitYCbCr11tile){ YCbCrSetup; (void) y; fromskew *= 3; do { x = w; /* was x = w>>1; patched 2000/09/25 warmerda@home.com */ do { int Cb = pp[1]; int Cr = pp[2]; YCbCrtoRGB(*cp++, pp[0]); pp += 3; } while (--x); cp += toskew; pp += fromskew; } while (--h);}#undef YCbCrSetup#undef YCbCrtoRGB#define LumaRed coeffs[0]#define LumaGreen coeffs[1]#define LumaBlue coeffs[2]#define SHIFT 16#define FIX(x) ((int32)((x) * (1L<<SHIFT) + 0.5))#define ONE_HALF ((int32)(1<<(SHIFT-1)))/* * Initialize the YCbCr->RGB conversion tables. The conversion * is done according to the 6.0 spec: * * R = Y + Cr*(2 - 2*LumaRed) * B = Y + Cb*(2 - 2*LumaBlue) * G = Y * - LumaBlue*Cb*(2-2*LumaBlue)/LumaGreen * - LumaRed*Cr*(2-2*LumaRed)/LumaGreen * * To avoid floating point arithmetic the fractional constants that * come out of the equations are represented as fixed point values * in the range 0...2^16. We also eliminate multiplications by * pre-calculating possible values indexed by Cb and Cr (this code * assumes conversion is being done for 8-bit samples). */static voidTIFFYCbCrToRGBInit(TIFFYCbCrToRGB* ycbcr, TIFF* tif){ TIFFRGBValue* clamptab; float* coeffs; int i; clamptab = (TIFFRGBValue*)( (tidata_t) ycbcr+TIFFroundup(sizeof (TIFFYCbCrToRGB), sizeof (long))); _TIFFmemset(clamptab, 0, 256); /* v < 0 => 0 */ ycbcr->clamptab = (clamptab += 256); for (i = 0; i < 256; i++) clamptab[i] = i; _TIFFmemset(clamptab+256, 255, 2*256); /* v > 255 => 255 */ TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRCOEFFICIENTS, &coeffs); _TIFFmemcpy(ycbcr->coeffs, coeffs, 3*sizeof (float)); { float f1 = 2-2*LumaRed; int32 D1 = FIX(f1); float f2 = LumaRed*f1/LumaGreen; int32 D2 = -FIX(f2); float f3 = 2-2*LumaBlue; int32 D3 = FIX(f3); float f4 = LumaBlue*f3/LumaGreen; int32 D4 = -FIX(f4); int x; ycbcr->Cr_r_tab = (int*) (clamptab + 3*256); ycbcr->Cb_b_tab = ycbcr->Cr_r_tab + 256; ycbcr->Cr_g_tab = (int32*) (ycbcr->Cb_b_tab + 256); ycbcr->Cb_g_tab = ycbcr->Cr_g_tab + 256; /* * i is the actual input pixel value in the range 0..255 * Cb and Cr values are in the range -128..127 (actually * they are in a range defined by the ReferenceBlackWhite * tag) so there is some range shifting to do here when * constructing tables indexed by the raw pixel data. * * XXX handle ReferenceBlackWhite correctly to calculate * Cb/Cr values to use in constructing the tables. */ for (i = 0, x = -128; i < 256; i++, x++) { ycbcr->Cr_r_tab[i] = (int)((D1*x + ONE_HALF)>>SHIFT); ycbcr->Cb_b_tab[i] = (int)((D3*x + ONE_HALF)>>SHIFT); ycbcr->Cr_g_tab[i] = D2*x; ycbcr->Cb_g_tab[i] = D4*x + ONE_HALF; } }}#undef SHIFT#undef ONE_HALF#undef FIX#undef LumaBlue#undef LumaGreen#undef LumaRedstatic tileContigRoutineinitYCbCrConversion(TIFFRGBAImage* img){ uint16 hs, vs; if (img->ycbcr == NULL) { img->ycbcr = (TIFFYCbCrToRGB*) _TIFFmalloc( TIFFroundup(sizeof (TIFFYCbCrToRGB), sizeof (long)) + 4*256*sizeof (TIFFRGBValue) + 2*256*sizeof (int) + 2*256*sizeof (int32) ); if (img->ycbcr == NULL) { TIFFError(TIFFFileName(img->tif), "No space for YCbCr->RGB conversion state"); return (NULL); } TIFFYCbCrToRGBInit(img->ycbcr, img->tif); } else { float* coeffs; TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRCOEFFICIENTS, &coeffs); if (_TIFFmemcmp(coeffs, img->ycbcr->coeffs, 3*sizeof (float)) != 0) TIFFYCbCrToRGBInit(img->ycbcr, img->tif); } /* * The 6.0 spec says that subsampling must be * one of 1, 2, or 4, and that vertical subsampling * must always be <= horizontal subsampling; so * there are only a few possibilities and we just * enumerate the cases. */ TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING, &hs, &vs); switch ((hs<<4)|vs) { case 0x44: return (putcontig8bitYCbCr44tile); case 0x42: return (putcontig8bitYCbCr42tile); case 0x41: return (putcontig8bitYCbCr41tile); case 0x22: return (putcontig8bitYCbCr22tile); case 0x21: return (putcontig8bitYCbCr21tile); case 0x11: return (putcontig8bitYCbCr11tile); } return (NULL);}/* * Greyscale images with less than 8 bits/sample are handled * with a table to avoid lots of shifts and masks. The table * is setup so that put*bwtile (below) can retrieve 8/bitspersample * pixel values simply by indexing into the table with one * number. */static intmakebwmap(TIFFRGBAImage* img){ TIFFRGBValue* Map = img->Map; int bitspersample = img->bitspersample; int nsamples = 8 / bitspersample; int i; uint32* p; if( nsamples == 0 ) nsamples = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -