📄 tif_getimage.c
字号:
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: case 16: 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); /* treat 16 bit the same as eight bit */ if( img->bitspersample == 16 ) range = (int32) 255; 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 <= 16 && (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 16: put = put16bitbwtile; break; 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++ ) { memmove( 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 + -