📄 tif_getimage.c
字号:
for (x = w; x-- > 0;) { av = *a++; rv = (*r++ * av) / 255; gv = (*g++ * av) / 255; bv = (*b++ * av) / 255; *cp++ = PACK4(rv,gv,bv,av); } SKEW4(r, g, b, a, fromskew); cp += toskew; }}/* * 16-bit unpacked samples => RGB */DECLARESepPutFunc(putRGBseparate16bittile){ uint16 *wr = (uint16*) r; uint16 *wg = (uint16*) g; uint16 *wb = (uint16*) b; (void) img; (void) y; (void) a; while (h-- > 0) { for (x = 0; x < w; x++) *cp++ = PACKW(*wr++, *wg++, *wb++); SKEW(wr, wg, wb, fromskew); cp += toskew; }}/* * 16-bit unpacked samples => RGBA w/ associated alpha */DECLARESepPutFunc(putRGBAAseparate16bittile){ uint16 *wr = (uint16*) r; uint16 *wg = (uint16*) g; uint16 *wb = (uint16*) b; uint16 *wa = (uint16*) a; (void) img; (void) y; while (h-- > 0) { for (x = 0; x < w; x++) *cp++ = PACKW4(*wr++, *wg++, *wb++, *wa++); SKEW4(wr, wg, wb, wa, fromskew); cp += toskew; }}/* * 16-bit unpacked samples => RGBA w/ unassociated alpha */DECLARESepPutFunc(putRGBUAseparate16bittile){ uint16 *wr = (uint16*) r; uint16 *wg = (uint16*) g; uint16 *wb = (uint16*) b; uint16 *wa = (uint16*) a; (void) img; (void) y; while (h-- > 0) { uint32 r,g,b,a; /* * We shift alpha down four bits just in case unsigned * arithmetic doesn't handle the full range. * We still have plenty of accuracy, since the output is 8 bits. * So we have (r * 0xffff) * (a * 0xfff)) = r*a * (0xffff*0xfff) * Since we want r*a * 0xff for eight bit output, * we divide by (0xffff * 0xfff) / 0xff == 0x10eff. */ for (x = w; x-- > 0;) { a = *wa++ >> 4; r = (*wr++ * a) / 0x10eff; g = (*wg++ * a) / 0x10eff; b = (*wb++ * a) / 0x10eff; *cp++ = PACK4(r,g,b,a); } SKEW4(wr, wg, wb, wa, fromskew); cp += toskew; }}/* * YCbCr -> RGB conversion and packing routines. The colorspace * conversion algorithm comes from the IJG v5a code; see below * for more information on how it works. */#define YCbCrtoRGB(dst, yc) { \ int Y = (yc); \ dst = PACK( \ clamptab[Y+Crrtab[Cr]], \ clamptab[Y + (int)((Cbgtab[Cb]+Crgtab[Cr])>>16)], \ clamptab[Y+Cbbtab[Cb]]); \}#define YCbCrSetup \ TIFFYCbCrToRGB* ycbcr = img->ycbcr; \ int* Crrtab = ycbcr->Cr_r_tab; \ int* Cbbtab = ycbcr->Cb_b_tab; \ int32* Crgtab = ycbcr->Cr_g_tab; \ int32* Cbgtab = ycbcr->Cb_g_tab; \ TIFFRGBValue* clamptab = ycbcr->clamptab/* * 8-bit packed YCbCr samples => RGB * This function is generic for different sampling sizes, * and can handle blocks sizes that aren't multiples of the * sampling size. However, it is substantially less optimized * than the specific sampling cases. It is used as a fallback * for difficult blocks. */#ifdef notdefstatic void putcontig8bitYCbCrGenericTile( TIFFRGBAImage* img, uint32* cp, uint32 x, uint32 y, uint32 w, uint32 h, int32 fromskew, int32 toskew, u_char* pp, int h_group, int v_group ){ YCbCrSetup; uint32* cp1 = cp+w+toskew; uint32* cp2 = cp1+w+toskew; uint32* cp3 = cp2+w+toskew; int32 incr = 3*w+4*toskew; int Cb, Cr; int group_size = v_group * h_group + 2; (void) y; fromskew = (fromskew * group_size) / h_group; for( yy = 0; yy < h; yy++ ) { u_char *pp_line; int y_line_group = yy / v_group; int y_remainder = yy - y_line_group * v_group; pp_line = pp + v_line_group * for( xx = 0; xx < w; xx++ ) { Cb = pp } } for (; h >= 4; h -= 4) { x = w>>2; do { Cb = pp[16]; 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; }}#endif/* * 8-bit packed YCbCr samples w/ 4,4 subsampling => RGB */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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -