Combine new tile* API methods

Use v7.40.0+ libvips loader methods

Separate Openslide as input vs Deep Zoom as output

Split tile-based tests into new file

Added assertions for generated tile size
This commit is contained in:
Lovell Fuller
2015-03-12 15:39:27 +00:00
parent 2d1e6f2644
commit 5781a23a4d
11 changed files with 314 additions and 215 deletions

View File

@@ -37,96 +37,61 @@ namespace sharp {
*/
ImageType DetermineImageType(void *buffer, size_t const length) {
ImageType imageType = ImageType::UNKNOWN;
#if (VIPS_MAJOR_VERSION >= 8)
if (vips_foreign_is_a_buffer("jpegload_buffer", buffer, length)) {
imageType = ImageType::JPEG;
} else if (vips_foreign_is_a_buffer("pngload_buffer", buffer, length)) {
imageType = ImageType::PNG;
} else if (vips_foreign_is_a_buffer("webpload_buffer", buffer, length)) {
imageType = ImageType::WEBP;
} else if (vips_foreign_is_a_buffer("tiffload_buffer", buffer, length)) {
imageType = ImageType::TIFF;
} else if(vips_foreign_is_a_buffer("magickload_buffer", buffer, length)) {
imageType = ImageType::MAGICK;
}
#else
const char* loader = vips_foreign_find_load_buffer(buffer, length);
if (loader != NULL) {
if (!strcmp(loader, "VipsForeignLoadJpegBuffer")) {
char const *load = vips_foreign_find_load_buffer(buffer, length);
if (load != NULL) {
std::string loader = load;
if (EndsWith(loader, "JpegBuffer")) {
imageType = ImageType::JPEG;
} else if (!strcmp(loader, "VipsForeignLoadPngBuffer")) {
} else if (EndsWith(loader, "PngBuffer")) {
imageType = ImageType::PNG;
} else if (!strcmp(loader, "VipsForeignLoadWebpBuffer")) {
} else if (EndsWith(loader, "WebpBuffer")) {
imageType = ImageType::WEBP;
} else if (!strcmp(loader, "VipsForeignLoadTiffBuffer")) {
} else if (EndsWith(loader, "TiffBuffer")) {
imageType = ImageType::TIFF;
} else if (!strcmp(loader, "VipsForeignLoadMagickBuffer")) {
} else if (EndsWith(loader, "MagickBuffer")) {
imageType = ImageType::MAGICK;
}
}
#endif
return imageType;
}
/*
Initialise and return a VipsImage from a buffer. Supports JPEG, PNG, WebP and TIFF.
*/
VipsImage* InitImage(ImageType imageType, void *buffer, size_t const length, VipsAccess const access) {
VipsImage *image = NULL;
if (imageType == ImageType::JPEG) {
vips_jpegload_buffer(buffer, length, &image, "access", access, NULL);
} else if (imageType == ImageType::PNG) {
vips_pngload_buffer(buffer, length, &image, "access", access, NULL);
} else if (imageType == ImageType::WEBP) {
vips_webpload_buffer(buffer, length, &image, "access", access, NULL);
} else if (imageType == ImageType::TIFF) {
vips_tiffload_buffer(buffer, length, &image, "access", access, NULL);
#if (VIPS_MAJOR_VERSION >= 8)
} else if (imageType == ImageType::MAGICK) {
vips_magickload_buffer(buffer, length, &image, "access", access, NULL);
#endif
}
return image;
VipsImage* InitImage(void *buffer, size_t const length, VipsAccess const access) {
return vips_image_new_from_buffer(buffer, length, NULL, "access", access, NULL);
}
/*
Inpect the first 2-4 bytes of a file to determine image format
Determine image format, reads the first few bytes of the file
*/
ImageType DetermineImageType(char const *file) {
ImageType imageType = ImageType::UNKNOWN;
if (vips_foreign_is_a("jpegload", file)) {
imageType = ImageType::JPEG;
} else if (vips_foreign_is_a("pngload", file)) {
imageType = ImageType::PNG;
} else if (vips_foreign_is_a("webpload", file)) {
imageType = ImageType::WEBP;
} else if (vips_foreign_is_a("tiffload", file)) {
imageType = ImageType::TIFF;
} else if(vips_foreign_is_a("magickload", file)) {
imageType = ImageType::MAGICK;
char const *load = vips_foreign_find_load(file);
if (load != NULL) {
std::string loader = load;
if (EndsWith(loader, "JpegFile")) {
imageType = ImageType::JPEG;
} else if (EndsWith(loader, "Png")) {
imageType = ImageType::PNG;
} else if (EndsWith(loader, "WebpFile")) {
imageType = ImageType::WEBP;
} else if (EndsWith(loader, "Openslide")) {
imageType = ImageType::OPENSLIDE;
} else if (EndsWith(loader, "TiffFile")) {
imageType = ImageType::TIFF;
} else if (EndsWith(loader, "MagickFile")) {
imageType = ImageType::MAGICK;
}
}
return imageType;
}
/*
Initialise and return a VipsImage from a file.
*/
VipsImage* InitImage(ImageType imageType, char const *file, VipsAccess const access) {
VipsImage *image = NULL;
if (imageType == ImageType::JPEG) {
vips_jpegload(file, &image, "access", access, NULL);
} else if (imageType == ImageType::PNG) {
vips_pngload(file, &image, "access", access, NULL);
} else if (imageType == ImageType::WEBP) {
vips_webpload(file, &image, "access", access, NULL);
} else if (imageType == ImageType::TIFF) {
vips_tiffload(file, &image, "access", access, NULL);
} else if (imageType == ImageType::MAGICK) {
vips_magickload(file, &image, "access", access, NULL);
}
return image;
VipsImage* InitImage(char const *file, VipsAccess const access) {
return vips_image_new_from_file(file, "access", access, NULL);
}
/*

View File

@@ -10,7 +10,7 @@ namespace sharp {
WEBP,
TIFF,
MAGICK,
DZ
OPENSLIDE
};
// How many tasks are in the queue?
@@ -39,12 +39,12 @@ namespace sharp {
/*
Initialise and return a VipsImage from a buffer. Supports JPEG, PNG, WebP and TIFF.
*/
VipsImage* InitImage(ImageType imageType, void *buffer, size_t const length, VipsAccess const access);
VipsImage* InitImage(void *buffer, size_t const length, VipsAccess const access);
/*
Initialise and return a VipsImage from a file.
*/
VipsImage* InitImage(ImageType imageType, char const *file, VipsAccess const access);
VipsImage* InitImage(char const *file, VipsAccess const access);
/*
Does this image have an embedded profile?

View File

@@ -61,7 +61,7 @@ class MetadataWorker : public NanAsyncWorker {
// From buffer
imageType = DetermineImageType(baton->bufferIn, baton->bufferInLength);
if (imageType != ImageType::UNKNOWN) {
image = InitImage(imageType, baton->bufferIn, baton->bufferInLength, VIPS_ACCESS_RANDOM);
image = InitImage(baton->bufferIn, baton->bufferInLength, VIPS_ACCESS_RANDOM);
if (image == NULL) {
(baton->err).append("Input buffer has corrupt header");
imageType = ImageType::UNKNOWN;
@@ -73,7 +73,7 @@ class MetadataWorker : public NanAsyncWorker {
// From file
imageType = DetermineImageType(baton->fileIn.c_str());
if (imageType != ImageType::UNKNOWN) {
image = InitImage(imageType, baton->fileIn.c_str(), VIPS_ACCESS_RANDOM);
image = InitImage(baton->fileIn.c_str(), VIPS_ACCESS_RANDOM);
if (image == NULL) {
(baton->err).append("Input file has corrupt header");
imageType = ImageType::UNKNOWN;
@@ -90,7 +90,7 @@ class MetadataWorker : public NanAsyncWorker {
case ImageType::WEBP: baton->format = "webp"; break;
case ImageType::TIFF: baton->format = "tiff"; break;
case ImageType::MAGICK: baton->format = "magick"; break;
case ImageType::DZ: baton->format = "dzi"; break;
case ImageType::OPENSLIDE: baton->format = "openslide"; break;
case ImageType::UNKNOWN: break;
}
// VipsImage attributes

View File

@@ -172,7 +172,7 @@ class ResizeWorker : public NanAsyncWorker {
// From buffer
inputImageType = DetermineImageType(baton->bufferIn, baton->bufferInLength);
if (inputImageType != ImageType::UNKNOWN) {
image = InitImage(inputImageType, baton->bufferIn, baton->bufferInLength, baton->accessMethod);
image = InitImage(baton->bufferIn, baton->bufferInLength, baton->accessMethod);
if (image != NULL) {
// Listen for "postclose" signal to delete input buffer
g_signal_connect(image, "postclose", G_CALLBACK(DeleteBuffer), baton->bufferIn);
@@ -190,7 +190,7 @@ class ResizeWorker : public NanAsyncWorker {
// From file
inputImageType = DetermineImageType(baton->fileIn.c_str());
if (inputImageType != ImageType::UNKNOWN) {
image = InitImage(inputImageType, baton->fileIn.c_str(), baton->accessMethod);
image = InitImage(baton->fileIn.c_str(), baton->accessMethod);
if (image == NULL) {
(baton->err).append("Input file has corrupt header");
inputImageType = ImageType::UNKNOWN;
@@ -801,7 +801,7 @@ class ResizeWorker : public NanAsyncWorker {
return Error(baton, hook);
}
baton->outputFormat = "tiff";
} else if (outputDz || matchInput) {
} else if (outputDz) {
// Write DZ to file
std::string filename_no_extension = baton->output.substr(0, baton->output.length() - 4);
if (vips_dzsave(image, filename_no_extension.c_str(), "strip", !baton->withMetadata,
@@ -845,11 +845,6 @@ class ResizeWorker : public NanAsyncWorker {
info->Set(NanNew<String>("width"), NanNew<Uint32>(static_cast<uint32_t>(width)));
info->Set(NanNew<String>("height"), NanNew<Uint32>(static_cast<uint32_t>(height)));
if (baton->outputFormat == "dz" ) {
info->Set(NanNew<String>("tileSize"), NanNew<Uint32>(static_cast<uint32_t>(baton->tileSize)));
info->Set(NanNew<String>("tileOverlap"), NanNew<Uint32>(static_cast<uint32_t>(baton->tileOverlap)));
}
if (baton->bufferOutLength > 0) {
// Copy data to new Buffer
argv[1] = NanNewBufferHandle(static_cast<char*>(baton->bufferOut), baton->bufferOutLength);