📄 tif_getimage.c
字号:
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; img->BWmap = (uint32**) _TIFFmalloc( 256*sizeof (uint32 *)+(256*nsamples*sizeof(uint32))); if (img->BWmap == NULL) { TIFFError(TIFFFileName(img->tif), "No space for B&W mapping table"); return (0); } p = (uint32*)(img->BWmap + 256); for (i = 0; i < 256; i++) { TIFFRGBValue c; img->BWmap[i] = p; switch (bitspersample) {#define GREY(x) c = Map[x]; *p++ = PACK(c,c,c); case 1: GREY(i>>7); GREY((i>>6)&1); GREY((i>>5)&1); GREY((i>>4)&1); GREY((i>>3)&1); GREY((i>>2)&1); GREY((i>>1)&1); GREY(i&1); break; case 2: GREY(i>>6); GREY((i>>4)&3); GREY((i>>2)&3); GREY(i&3); break; case 4: GREY(i>>4); GREY(i&0xf); break; case 8: GREY(i); break; }#undef GREY } return (1);}/* * Construct a mapping table to convert from the range * of the data samples to [0,255] --for display. This * process also handles inverting B&W images when needed. */ static intsetupMap(TIFFRGBAImage* img){ int32 x, range; range = (int32)((1L<<img->bitspersample)-1); img->Map = (TIFFRGBValue*) _TIFFmalloc((range+1) * sizeof (TIFFRGBValue)); if (img->Map == NULL) { TIFFError(TIFFFileName(img->tif), "No space for photometric conversion table"); return (0); } if (img->photometric == PHOTOMETRIC_MINISWHITE) { for (x = 0; x <= range; x++) img->Map[x] = (TIFFRGBValue) (((range - x) * 255) / range); } else { for (x = 0; x <= range; x++) img->Map[x] = (TIFFRGBValue) ((x * 255) / range); } if (img->bitspersample <= 8 && (img->photometric == PHOTOMETRIC_MINISBLACK || img->photometric == PHOTOMETRIC_MINISWHITE)) { /* * Use photometric mapping table to construct * unpacking tables for samples <= 8 bits. */ if (!makebwmap(img)) return (0); /* no longer need Map, free it */ _TIFFfree(img->Map), img->Map = NULL; } return (1);}static intcheckcmap(TIFFRGBAImage* img){ uint16* r = img->redcmap; uint16* g = img->greencmap; uint16* b = img->bluecmap; long n = 1L<<img->bitspersample; while (n-- > 0) if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256) return (16); return (8);}static voidcvtcmap(TIFFRGBAImage* img){ uint16* r = img->redcmap; uint16* g = img->greencmap; uint16* b = img->bluecmap; long i; for (i = (1L<<img->bitspersample)-1; i >= 0; i--) {#define CVT(x) ((uint16)((x)>>8)) r[i] = CVT(r[i]); g[i] = CVT(g[i]); b[i] = CVT(b[i]);#undef CVT }}/* * Palette images with <= 8 bits/sample are handled * with a table to avoid lots of shifts and masks. The table * is setup so that put*cmaptile (below) can retrieve 8/bitspersample * pixel values simply by indexing into the table with one * number. */static intmakecmap(TIFFRGBAImage* img){ int bitspersample = img->bitspersample; int nsamples = 8 / bitspersample; uint16* r = img->redcmap; uint16* g = img->greencmap; uint16* b = img->bluecmap; uint32 *p; int i; img->PALmap = (uint32**) _TIFFmalloc( 256*sizeof (uint32 *)+(256*nsamples*sizeof(uint32))); if (img->PALmap == NULL) { TIFFError(TIFFFileName(img->tif), "No space for Palette mapping table"); return (0); } p = (uint32*)(img->PALmap + 256); for (i = 0; i < 256; i++) { TIFFRGBValue c; img->PALmap[i] = p;#define CMAP(x) c = x; *p++ = PACK(r[c]&0xff, g[c]&0xff, b[c]&0xff); switch (bitspersample) { case 1: CMAP(i>>7); CMAP((i>>6)&1); CMAP((i>>5)&1); CMAP((i>>4)&1); CMAP((i>>3)&1); CMAP((i>>2)&1); CMAP((i>>1)&1); CMAP(i&1); break; case 2: CMAP(i>>6); CMAP((i>>4)&3); CMAP((i>>2)&3); CMAP(i&3); break; case 4: CMAP(i>>4); CMAP(i&0xf); break; case 8: CMAP(i); break; }#undef CMAP } return (1);}/* * Construct any mapping table used * by the associated put routine. */static intbuildMap(TIFFRGBAImage* img){ switch (img->photometric) { case PHOTOMETRIC_RGB: case PHOTOMETRIC_YCBCR: case PHOTOMETRIC_SEPARATED: if (img->bitspersample == 8) break; /* fall thru... */ case PHOTOMETRIC_MINISBLACK: case PHOTOMETRIC_MINISWHITE: if (!setupMap(img)) return (0); break; case PHOTOMETRIC_PALETTE: /* * Convert 16-bit colormap to 8-bit (unless it looks * like an old-style 8-bit colormap). */ if (checkcmap(img) == 16) cvtcmap(img); else TIFFWarning(TIFFFileName(img->tif), "Assuming 8-bit colormap"); /* * Use mapping table and colormap to construct * unpacking tables for samples < 8 bits. */ if (img->bitspersample <= 8 && !makecmap(img)) return (0); break; } return (1);}/* * Select the appropriate conversion routine for packed data. */static intpickTileContigCase(TIFFRGBAImage* img){ tileContigRoutine put = 0; if (buildMap(img)) { switch (img->photometric) { case PHOTOMETRIC_RGB: switch (img->bitspersample) { case 8: if (!img->Map) { if (img->alpha == EXTRASAMPLE_ASSOCALPHA) put = putRGBAAcontig8bittile; else if (img->alpha == EXTRASAMPLE_UNASSALPHA) put = putRGBUAcontig8bittile; else put = putRGBcontig8bittile; } else put = putRGBcontig8bitMaptile; break; case 16: put = putRGBcontig16bittile; if (!img->Map) { if (img->alpha == EXTRASAMPLE_ASSOCALPHA) put = putRGBAAcontig16bittile; else if (img->alpha == EXTRASAMPLE_UNASSALPHA) put = putRGBUAcontig16bittile; } break; } break; case PHOTOMETRIC_SEPARATED: if (img->bitspersample == 8) { if (!img->Map) put = putRGBcontig8bitCMYKtile; else put = putRGBcontig8bitCMYKMaptile; } break; case PHOTOMETRIC_PALETTE: switch (img->bitspersample) { case 8: put = put8bitcmaptile; break; case 4: put = put4bitcmaptile; break; case 2: put = put2bitcmaptile; break; case 1: put = put1bitcmaptile; break; } break; case PHOTOMETRIC_MINISWHITE: case PHOTOMETRIC_MINISBLACK: switch (img->bitspersample) { case 8: put = putgreytile; break; case 4: put = put4bitbwtile; break; case 2: put = put2bitbwtile; break; case 1: put = put1bitbwtile; break; } break; case PHOTOMETRIC_YCBCR: if (img->bitspersample == 8) put = initYCbCrConversion(img); break; } } return ((img->put.contig = put) != 0);}/* * Select the appropriate conversion routine for unpacked data. * * NB: we assume that unpacked single channel data is directed * to the "packed routines. */static intpickTileSeparateCase(TIFFRGBAImage* img){ tileSeparateRoutine put = 0; if (buildMap(img)) { switch (img->photometric) { case PHOTOMETRIC_RGB: switch (img->bitspersample) { case 8: if (!img->Map) { if (img->alpha == EXTRASAMPLE_ASSOCALPHA) put = putRGBAAseparate8bittile; else if (img->alpha == EXTRASAMPLE_UNASSALPHA) put = putRGBUAseparate8bittile; else put = putRGBseparate8bittile; } else put = putRGBseparate8bitMaptile; break; case 16: put = putRGBseparate16bittile; if (!img->Map) { if (img->alpha == EXTRASAMPLE_ASSOCALPHA) put = putRGBAAseparate16bittile; else if (img->alpha == EXTRASAMPLE_UNASSALPHA) put = putRGBUAseparate16bittile; } break; } break; } } return ((img->put.separate = put) != 0);}/* * Read a whole strip off data from the file, and convert to RGBA form. * If this is the last strip, then it will only contain the portion of * the strip that is actually within the image space. The result is * organized in bottom to top form. */intTIFFReadRGBAStrip(TIFF* tif, uint32 row, uint32 * raster ){ char emsg[1024]; TIFFRGBAImage img; int ok; uint32 rowsperstrip, rows_to_read; if( TIFFIsTiled( tif ) ) { TIFFError(TIFFFileName(tif), "Can't use TIFFReadRGBAStrip() with tiled file."); return (0); } TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); if( (row % rowsperstrip) != 0 ) { TIFFError(TIFFFileName(tif), "Row passed to TIFFReadRGBAStrip() must be first in a strip."); return (0); } if (TIFFRGBAImageBegin(&img, tif, 0, emsg)) { img.row_offset = row; img.col_offset = 0; if( row + rowsperstrip > img.height ) rows_to_read = img.height - row; else rows_to_read = rowsperstrip; ok = TIFFRGBAImageGet(&img, raster, img.width, rows_to_read ); TIFFRGBAImageEnd(&img); } else { TIFFError(TIFFFileName(tif), emsg); ok = 0; } return (ok);}/* * Read a whole tile off data from the file, and convert to RGBA form. * The returned RGBA data is organized from bottom to top of tile, * and may include zeroed areas if the tile extends off the image. */intTIFFReadRGBATile(TIFF* tif, uint32 col, uint32 row, uint32 * raster){ char emsg[1024]; TIFFRGBAImage img; int ok; uint32 tile_xsize, tile_ysize; uint32 read_xsize, read_ysize; uint32 i_row; /* * Verify that our request is legal - on a tile file, and on a * tile boundary. */ if( !TIFFIsTiled( tif ) ) { TIFFError(TIFFFileName(tif), "Can't use TIFFReadRGBATile() with stripped file."); return (0); } TIFFGetFieldDefaulted(tif, TIFFTAG_TILEWIDTH, &tile_xsize); TIFFGetFieldDefaulted(tif, TIFFTAG_TILELENGTH, &tile_ysize); if( (col % tile_xsize) != 0 || (row % tile_ysize) != 0 ) { TIFFError(TIFFFileName(tif), "Row/col passed to TIFFReadRGBATile() must be top" "left corner of a tile."); return (0); } /* * Setup the RGBA reader. */ if ( !TIFFRGBAImageBegin(&img, tif, 0, emsg)) { TIFFError(TIFFFileName(tif), emsg); return( 0 ); } /* * The TIFFRGBAImageGet() function doesn't allow us to get off the * edge of the image, even to fill an otherwise valid tile. So we * figure out how much we can read, and fix up the tile buffer to * a full tile configuration afterwards. */ if( row + tile_ysize > img.height ) read_ysize = img.height - row; else read_ysize = tile_ysize; if( col + tile_xsize > img.width ) read_xsize = img.width - col; else read_xsize = tile_xsize; /* * Read the chunk of imagery. */ img.row_offset = row; img.col_offset = col; ok = TIFFRGBAImageGet(&img, raster, read_xsize, read_ysize ); TIFFRGBAImageEnd(&img); /* * If our read was incomplete we will need to fix up the tile by * shifting the data around as if a full tile of data is being returned. * * This is all the more complicated because the image is organized in * bottom to top format. */ if( read_xsize == tile_xsize && read_ysize == tile_ysize ) return( ok ); for( i_row = 0; i_row < read_ysize; i_row++ ) { _TIFFmemcpy( raster + (tile_ysize - i_row - 1) * tile_xsize, raster + (read_ysize - i_row - 1) * read_xsize, read_xsize * sizeof(uint32) ); _TIFFmemset( raster + (tile_ysize - i_row - 1) * tile_xsize+read_xsize, 0, sizeof(uint32) * (tile_xsize - read_xsize) ); } for( i_row = read_ysize; i_row < tile_ysize; i_row++ ) { _TIFFmemset( raster + (tile_ysize - i_row - 1) * tile_xsize, 0, sizeof(uint32) * tile_xsize ); } return (ok);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -