Extract a full-scale image from a SVS file

2019-07-30 08:12发布

I am trying to extract the first page of a SVS file using Libtiff. The SVS file uses JPEG2000 compression for this image.

My plan is:

  1. extracting raw tiles from the first page of the SVS, and
  2. decoding it using OpenJPEG.

Below is what I tried to extract raw tiles from the SVS. I only got a 43KB output file from 152MB svs file (it failed to extract the raw tiles).

I hope someone could let me know how to extract tiles from a SVS file.

int main()
{
    const char* filename = "input.svs";
    TIFF* tiff_in = TIFFOpen(filename, "r");
    TIFF* tiff_out = TIFFOpen("output.raw", "w");
    if (tiff_in) {
        uint32 imageWidth, imageLength;
        uint32 tileWidth, tileLength;
        uint32 tileCount, tileByteCounts;
        uint32 samplePerPixel, bitsPerSample;
        uint32 orientation, planarConfig, photoMetric;
        uint32 xResolution, yResolution;
        uint32 x, y;
        ttile_t tile;
        // get fileds from the input file
        TIFFGetField(tiff_in, TIFFTAG_IMAGEWIDTH, &imageWidth);
        TIFFGetField(tiff_in, TIFFTAG_IMAGELENGTH, &imageLength);
        TIFFGetField(tiff_in, TIFFTAG_TILEWIDTH, &tileWidth);
        TIFFGetField(tiff_in, TIFFTAG_TILELENGTH, &tileLength);
        TIFFGetField(tiff_in, TIFFTAG_SAMPLESPERPIXEL, &samplePerPixel);
        TIFFGetField(tiff_in, TIFFTAG_BITSPERSAMPLE, &bitsPerSample);
        TIFFGetField(tiff_in, TIFFTAG_TILEBYTECOUNTS, &tileByteCounts);
        TIFFGetField(tiff_in, TIFFTAG_ORIENTATION, &orientation);
        TIFFGetField(tiff_in, TIFFTAG_PLANARCONFIG, &planarConfig);
        TIFFGetField(tiff_in, TIFFTAG_PHOTOMETRIC, &photoMetric);
        TIFFGetField(tiff_in, TIFFTAG_XRESOLUTION, &xResolution);
        TIFFGetField(tiff_in, TIFFTAG_YRESOLUTION, &yResolution);

        // set files to the output file
        TIFFSetField(tiff_out, TIFFTAG_IMAGEWIDTH, imageWidth);
        TIFFSetField(tiff_out, TIFFTAG_IMAGELENGTH, imageLength);
        TIFFSetField(tiff_out, TIFFTAG_TILEWIDTH, tileWidth);
        TIFFSetField(tiff_out, TIFFTAG_TILELENGTH, tileLength);
        TIFFSetField(tiff_out, TIFFTAG_SAMPLESPERPIXEL, samplePerPixel);
        TIFFSetField(tiff_out, TIFFTAG_BITSPERSAMPLE, bitsPerSample);
        TIFFSetField(tiff_out, TIFFTAG_PLANARCONFIG, planarConfig);
        TIFFSetField(tiff_out, TIFFTAG_PHOTOMETRIC, photoMetric);
        TIFFSetField(tiff_out, TIFFTAG_XRESOLUTION, xResolution);
        TIFFSetField(tiff_out, TIFFTAG_YRESOLUTION, yResolution);
        //TIFFSetField(tiff_out, TIFFTAG_ROWSPERSTRIP, 1);

        tdata_t buf = _TIFFmalloc(TIFFTileSize(tiff_in));
        for (int tile = 0; tile < TIFFNumberOfTiles(tiff_in); tile++)
        {
            TIFFReadRawTile(tiff_in, tile, buf, (tsize_t)-1);
            TIFFWriteRawTile(tiff_out, tile, buf, (tsize_t)sizeof(buf));
        }
        _TIFFfree(buf);
        TIFFClose(tiff_in);
        TIFFClose(tiff_out);
    }
    return 0;
}

标签: c tiff libtiff
1条回答
成全新的幸福
2楼-- · 2019-07-30 09:04

You are writing tiles with 8 bytes each. sizeof(buf) is the size in bytes of the pointer buf. You want to use the number of bytes actually read, which is returned by TIFFReadRawTile:

tsize_t size = TIFFReadRawTile(tiff_in, tile, buf, (tsize_t)-1);
TIFFWriteRawTile(tiff_out, tile, buf, size);

Note that here you are copying the JPEG2000-compressed data to the output file. You'll have to decompress this data using OpenJPEG, then write data of the size of the uncompressed tile, which is tileWidth * tileLength * samplePerPixel * bitsPerSample / 8 in the contiguous planar configuration, or tileWidth * tileLength * bitsPerSample / 8 in the separate planar configuration.


When using TIFFGetField and TIFFSetField, you need to check the return values. A 0 is returned if an error occurred. You cannot depend on values that were not read properly.

Other errors and warnings are typically printed to stderr. If you are developing under Windows, these will typically not be shown. I recommend that you look into TIFFSetErrorHandler and TIFFSetWarningHandler, setting suitable message display functions here will help you immensely during development.

查看更多
登录 后发表回答