cantaloupe
cantaloupe copied to clipboard
Stream JPEG-compressed tiles from tiled TIFFs
Requesting 512×512 tiles with 16 client processes in parallel from pyramidal jpeg tiff with 512×512 tile size from our dual Xeon Gold 6246 server we're getting approx. 140 MPixel/s.
Now did some trace:
Responded to GET … 30 msec (median)
e.i.l.c.r.ImageRepresentation [ImageRepresentation.java:207] …
Java2dProcessor processed in 20 msec (median)
But… the tiff already has jpeg tiles of the size wanted and we're requesting those with no overhang. So why Java2dProcessor? Couldn't cantaloupe just pass through the data with minimal modification to the client → 0 msec?
Otherwise the performance is limited to 512²px/0,02s = 13.1 MPixel/s per core.
With .jpg tile files (extracted from ptif) we're getting approx. 3 GPixel/s (https). Is there a Javascript wrapper to simulate IIIF (for scaling, cropping, etc) on the browser?
Is there a Javascript wrapper to simulate IIIF (for scaling, cropping, etc) on the browser?
You could take a look at https://github.com/samvera-labs/serverless-iiif and https://www.npmjs.com/package/iiif-processor, and see if either of those is helpful.
I don't think it's possible using the Image I/O API to read the JPEG tile data without decompressing it, but it's a neat idea. I will keep it in mind as a potential enhancement.
My way (with a lot assumptions) to extract jpeg tiles in c:
uint32 jpegtables_len;
void *jpegtables;
if(TIFFGetField(tif, TIFFTAG_JPEGTABLES, &jpegtables_len, &jpegtables)==1) {
FILE *fw=fopen("x.jpg", "w");
FIF(!fw);
FIF(fwrite(jpegtables, 1, 2, fw)!=2); // nur SOI
uint8 jfif[]={0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01, 0x01, 0x01, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x00};
FIF(fwrite(jfif, 1, sizeof(jfif), fw)!=sizeof(jfif));
FIF(fwrite(jpegtables+2, 1, jpegtables_len-2-2, fw)!=jpegtables_len-2-2); // without EOI
tsize_t ts = TIFFTileSize(tif);
tdata_t tile = malloc(ts);
FIF(tile==NULL);
tsize_t bytecount = TIFFReadRawTile(tif, TIFFComputeTile(tif, x, y, 0, 0), tile, ts);
FIF(bytecount > ts);
printf("tables:%d tile:%ld\n", jpegtables_len, bytecount);
FIF(fwrite(tile+2, 1, bytecount-2, fw)!=bytecount-2); // tile starts with SOI = ff d8 — skip.
free(tile);
FIF(fwrite(jpegtables+jpegtables_len-2, 1, 2, fw)!=2); // EOI;
TIFFClose(tif);
fclose(fw);
Would be cool if ptif generaters (like vips) would arrange tiles in Hilbert or Z space filling curve for disk locality.
tiff-java has List<Long> getTileOffsets()
and List<Number> getTileByteCounts()
in Class FileDirectory