mirror of
https://github.com/mickael-kerjean/filestash.git
synced 2024-04-21 12:32:08 +00:00
feature (thumbnail): support for tiff
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <tiffio.h>
|
||||
#include <webp/encode.h>
|
||||
#include "utils.h"
|
||||
|
||||
#define BUF_SIZE 1024 * 128
|
||||
|
||||
int tiff_to_webp(int inputDesc, int outputDesc, int targetSize) {
|
||||
#ifdef HAS_DEBUG
|
||||
clock_t t;
|
||||
t = clock();
|
||||
#endif
|
||||
int status = 0;
|
||||
FILE* input = fdopen(inputDesc, "r");
|
||||
FILE* output = fdopen(outputDesc, "wb");
|
||||
if (!input || !output) {
|
||||
return 1;
|
||||
}
|
||||
if (targetSize < 0) targetSize = -targetSize;
|
||||
|
||||
// STEP1: write input to a file as libgiff didn't work out well with the file descriptor
|
||||
char fname_in[32] = "/tmp/filestash.XXXXXX";
|
||||
int _mkstemp_in = mkstemp(fname_in);
|
||||
if (!_mkstemp_in) {
|
||||
ERROR("mkstemp_in");
|
||||
return 1;
|
||||
}
|
||||
FILE* f_in = fdopen(_mkstemp_in, "wb");
|
||||
if (!f_in) {
|
||||
ERROR("fdopen");
|
||||
return 1;
|
||||
}
|
||||
char content[BUF_SIZE];
|
||||
int read;
|
||||
while ((read = fread(content, sizeof(char), BUF_SIZE, input))) {
|
||||
fwrite(content, read, sizeof(char), f_in);
|
||||
}
|
||||
fclose(f_in);
|
||||
DEBUG("setup");
|
||||
|
||||
// STEP2: decode tiff image
|
||||
TIFF* tif = TIFFOpen(fname_in, "rb");
|
||||
if (!tif) {
|
||||
status = 1;
|
||||
goto CLEANUP_AND_ABORT;
|
||||
}
|
||||
DEBUG("init0");
|
||||
uint32_t w, h;
|
||||
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
|
||||
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
|
||||
uint32_t* raster = (uint32_t*)_TIFFmalloc(w * h * sizeof(uint32_t));
|
||||
if (!raster) {
|
||||
TIFFClose(tif);
|
||||
status = 1;
|
||||
goto CLEANUP_AND_ABORT;
|
||||
}
|
||||
DEBUG("init1");
|
||||
if (!TIFFReadRGBAImageOriented(tif, w, h, raster, ORIENTATION_TOPLEFT, 0)) {
|
||||
TIFFClose(tif);
|
||||
status = 1;
|
||||
goto CLEANUP_AND_ABORT_A;
|
||||
}
|
||||
TIFFClose(tif);
|
||||
DEBUG("read");
|
||||
|
||||
// STEP3: resize image
|
||||
uint8_t* thumbnail_buffer = (uint8_t*)malloc(targetSize * targetSize * 4);
|
||||
if (!thumbnail_buffer) {
|
||||
status = 1;
|
||||
goto CLEANUP_AND_ABORT_A;
|
||||
}
|
||||
for (int y = 0; y < targetSize; ++y) {
|
||||
for (int x = 0; x < targetSize; ++x) {
|
||||
int srcX = x * w / targetSize;
|
||||
int srcY = y * h / targetSize;
|
||||
uint32_t pixel = raster[srcY * w + srcX];
|
||||
thumbnail_buffer[(y * targetSize + x) * 3 + 0] = TIFFGetR(pixel);
|
||||
thumbnail_buffer[(y * targetSize + x) * 3 + 1] = TIFFGetG(pixel);
|
||||
thumbnail_buffer[(y * targetSize + x) * 3 + 2] = TIFFGetB(pixel);
|
||||
}
|
||||
}
|
||||
DEBUG("resized");
|
||||
|
||||
// STEP4: encode output image
|
||||
size_t webp_output_size;
|
||||
uint8_t* webp_output_data = NULL;
|
||||
if (!(webp_output_size = WebPEncodeRGB(thumbnail_buffer, targetSize, targetSize, targetSize * 3, 75, &webp_output_data))) {
|
||||
status = 1;
|
||||
goto CLEANUP_AND_ABORT_B;
|
||||
}
|
||||
DEBUG("encoded");
|
||||
fwrite(webp_output_data, webp_output_size, 1, output);
|
||||
fflush(output);
|
||||
WebPFree(webp_output_data);
|
||||
DEBUG("done");
|
||||
|
||||
CLEANUP_AND_ABORT_B:
|
||||
free(thumbnail_buffer);
|
||||
CLEANUP_AND_ABORT_A:
|
||||
_TIFFfree(raster);
|
||||
CLEANUP_AND_ABORT:
|
||||
remove(fname_in);
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package plg_image_c
|
||||
|
||||
// #include "image_tiff.h"
|
||||
// #cgo LDFLAGS: -l:libwebp.a -ltiff
|
||||
import "C"
|
||||
|
||||
func tiff(input uintptr, output uintptr, size int) {
|
||||
C.tiff_to_webp(C.int(input), C.int(output), C.int(size))
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
int tiff_to_webp(int inputDesc, int outputDesc, int targetSize);
|
||||
@@ -31,7 +31,7 @@ func init() {
|
||||
Hooks.Register.Thumbnailer("image/gif", &transcoder{runner(gif), "image/webp", -300})
|
||||
Hooks.Register.Thumbnailer("image/heic", &transcoder{runner(heif), "image/jpeg", -200})
|
||||
Hooks.Register.Thumbnailer("image/webp", &transcoder{runner(webp), "image/webp", -200})
|
||||
|
||||
Hooks.Register.Thumbnailer("image/tiff", &transcoder{runner(tiff), "image/webp", -200})
|
||||
rawMimeType := []string{
|
||||
"image/x-canon-cr2", "image/x-tif", "image/x-canon-cr2", "image/x-canon-crw",
|
||||
"image/x-nikon-nef", "image/x-nikon-nrw", "image/x-sony-arw", "image/x-sony-sr2",
|
||||
|
||||
Reference in New Issue
Block a user