mirror of
https://github.com/mickael-kerjean/filestash
synced 2025-12-06 00:15:11 +01:00
feature (plg_image_thumbnail): more efficient image thumbnailing
This commit is contained in:
parent
ee15742fae
commit
468251d69a
26 changed files with 58 additions and 42 deletions
1
Makefile
1
Makefile
|
|
@ -2,7 +2,6 @@ all:
|
|||
make build_init
|
||||
make build_frontend
|
||||
GOARCH=amd64 GOOS=linux make build_backend
|
||||
# GOARCH=arm GOARM=7 GOOS=linux make build_backend
|
||||
|
||||
build_init:
|
||||
go generate -x ./server/...
|
||||
|
|
|
|||
Binary file not shown.
1
server/plugin/plg_image_thumbnail/dist/jpeg_linux_amd64.bin.sha256
vendored
Normal file
1
server/plugin/plg_image_thumbnail/dist/jpeg_linux_amd64.bin.sha256
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
db54aaaa47c9b08763d804e6a6e5f4bc0513512283e940bbbc9c0eb4948b3330
|
||||
Binary file not shown.
1
server/plugin/plg_image_thumbnail/dist/jpeg_linux_arm.bin.sha256
vendored
Normal file
1
server/plugin/plg_image_thumbnail/dist/jpeg_linux_arm.bin.sha256
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
3356b3016e1b45654889399e78fee04eaeb29a03d0d7f8ab2465609cbf1ec20d
|
||||
Binary file not shown.
1
server/plugin/plg_image_thumbnail/dist/png_linux_amd64.bin.sha256
vendored
Normal file
1
server/plugin/plg_image_thumbnail/dist/png_linux_amd64.bin.sha256
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
d1d02d84c18e18ce639afaf35335a476eea5deebc5aa31aeb45f052abcd1f31d
|
||||
Binary file not shown.
1
server/plugin/plg_image_thumbnail/dist/png_linux_arm.bin.sha256
vendored
Normal file
1
server/plugin/plg_image_thumbnail/dist/png_linux_arm.bin.sha256
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
2a377fad44b4dd63581c7e5ec736705c4700ff278fec8c477685ca45953da57b
|
||||
BIN
server/plugin/plg_image_thumbnail/dist/raw_linux_amd64.bin
vendored
Executable file
BIN
server/plugin/plg_image_thumbnail/dist/raw_linux_amd64.bin
vendored
Executable file
Binary file not shown.
1
server/plugin/plg_image_thumbnail/dist/raw_linux_amd64.bin.sha256
vendored
Normal file
1
server/plugin/plg_image_thumbnail/dist/raw_linux_amd64.bin.sha256
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
1e0ea798cadb3ed4af0e562e4044acae98f4c6db822b354d3623039e5b42ece9
|
||||
BIN
server/plugin/plg_image_thumbnail/dist/raw_linux_arm.bin
vendored
Executable file
BIN
server/plugin/plg_image_thumbnail/dist/raw_linux_arm.bin
vendored
Executable file
Binary file not shown.
1
server/plugin/plg_image_thumbnail/dist/raw_linux_arm.bin.sha256
vendored
Normal file
1
server/plugin/plg_image_thumbnail/dist/raw_linux_arm.bin.sha256
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
198cc17684799587cee23fee02df161822cc26a34dfed3ac70a3e29632813ab8
|
||||
|
|
@ -29,7 +29,7 @@ func init() {
|
|||
} {
|
||||
Hooks.Register.Thumbnailer(mType, thumbnailBuilder{thumbnailRaw})
|
||||
}
|
||||
// TODO: Hooks.Register.ProcessFileContentBeforeSend for raw files rendering
|
||||
Hooks.Register.ProcessFileContentBeforeSend(renderRaw)
|
||||
}
|
||||
|
||||
func thumbnailPng(reader io.ReadCloser, ctx *App, res *http.ResponseWriter, req *http.Request) (io.ReadCloser, error) {
|
||||
|
|
@ -72,9 +72,17 @@ func thumbnailRaw(reader io.ReadCloser, ctx *App, res *http.ResponseWriter, req
|
|||
}
|
||||
|
||||
func renderRaw(reader io.ReadCloser, ctx *App, res *http.ResponseWriter, req *http.Request) (io.ReadCloser, error) {
|
||||
query := req.URL.Query()
|
||||
if query.Get("thumbnail") == "true" {
|
||||
return reader, nil
|
||||
} else if isRaw(GetMimeType(query.Get("path"))) == false {
|
||||
return reader, nil
|
||||
} else if query.Get("size") == "" {
|
||||
return reader, nil
|
||||
}
|
||||
|
||||
h := (*res).Header()
|
||||
r, err := createThumbnailForRaw(reader)
|
||||
// r, err := createExtractForRaw(reader)
|
||||
r, err := createRenderingForRaw(reader, query.Get("size"))
|
||||
if err != nil {
|
||||
h.Set("Content-Type", "image/png")
|
||||
return NewReadCloserFromBytes(placeholder), nil
|
||||
|
|
@ -134,16 +142,15 @@ func (this *ThumbnailExecutable) verify() bool {
|
|||
return this.isValid
|
||||
}
|
||||
|
||||
func (this *ThumbnailExecutable) Execute(reader io.ReadCloser) (io.ReadCloser, error) {
|
||||
func (this *ThumbnailExecutable) Execute(reader io.ReadCloser, params ...string) (io.ReadCloser, error) {
|
||||
if this.verify() == false {
|
||||
Log.Error("plg_image_thumbnail::execution abort after verification on '%s'", this.Name)
|
||||
reader.Close()
|
||||
return nil, ErrFilesystemError
|
||||
}
|
||||
// TODO: rate limit this
|
||||
var buf bytes.Buffer
|
||||
var errBuff bytes.Buffer
|
||||
cmd := exec.Command("/tmp/" + this.Name)
|
||||
cmd := exec.Command("/tmp/"+this.Name, params...)
|
||||
cmd.Stdin = reader
|
||||
cmd.Stdout = &buf
|
||||
cmd.Stderr = &errBuff
|
||||
|
|
|
|||
|
|
@ -15,7 +15,11 @@ func init() {
|
|||
}
|
||||
|
||||
func createThumbnailForRaw(reader io.ReadCloser) (io.ReadCloser, error) {
|
||||
return exeForRaw.Execute(reader)
|
||||
return exeForRaw.Execute(reader, "200")
|
||||
}
|
||||
|
||||
func createRenderingForRaw(reader io.ReadCloser, size string) (io.ReadCloser, error) {
|
||||
return exeForRaw.Execute(reader, size)
|
||||
}
|
||||
|
||||
func isRaw(mType string) bool {
|
||||
|
|
|
|||
|
|
@ -5,9 +5,7 @@
|
|||
|
||||
#define JPEG_QUALITY 50
|
||||
|
||||
#define min(a, b) (a > b ? b : a)
|
||||
|
||||
int jpeg_to_jpeg(FILE* input, FILE* output) {
|
||||
int jpeg_to_jpeg(FILE* input, FILE* output, int targetSize) {
|
||||
#ifdef HAS_DEBUG
|
||||
clock_t t;
|
||||
t = clock();
|
||||
|
|
@ -46,25 +44,25 @@ int jpeg_to_jpeg(FILE* input, FILE* output) {
|
|||
image_min_size = min(jpeg_config_input.output_width, jpeg_config_input.output_height);
|
||||
jpeg_config_input.scale_num = 1;
|
||||
jpeg_config_input.scale_denom = 1;
|
||||
if (image_min_size / 8 >= TARGET_SIZE) {
|
||||
if (image_min_size / 8 >= targetSize) {
|
||||
jpeg_config_input.scale_num = 1;
|
||||
jpeg_config_input.scale_denom = 8;
|
||||
} else if (image_min_size * 2 / 8 >= TARGET_SIZE) {
|
||||
} else if (image_min_size * 2 / 8 >= targetSize) {
|
||||
jpeg_config_input.scale_num = 1;
|
||||
jpeg_config_input.scale_denom = 4;
|
||||
} else if (image_min_size * 3 / 8 >= TARGET_SIZE) {
|
||||
} else if (image_min_size * 3 / 8 >= targetSize) {
|
||||
jpeg_config_input.scale_num = 3;
|
||||
jpeg_config_input.scale_denom = 8;
|
||||
} else if (image_min_size * 4 / 8 >= TARGET_SIZE) {
|
||||
} else if (image_min_size * 4 / 8 >= targetSize) {
|
||||
jpeg_config_input.scale_num = 4;
|
||||
jpeg_config_input.scale_denom = 8;
|
||||
} else if (image_min_size * 5 / 8 >= TARGET_SIZE) {
|
||||
} else if (image_min_size * 5 / 8 >= targetSize) {
|
||||
jpeg_config_input.scale_num = 5;
|
||||
jpeg_config_input.scale_denom = 8;
|
||||
} else if (image_min_size * 6 / 8 >= TARGET_SIZE) {
|
||||
} else if (image_min_size * 6 / 8 >= targetSize) {
|
||||
jpeg_config_input.scale_num = 6;
|
||||
jpeg_config_input.scale_denom = 8;
|
||||
} else if (image_min_size * 7 / 8 >= TARGET_SIZE) {
|
||||
} else if (image_min_size * 7 / 8 >= targetSize) {
|
||||
jpeg_config_input.scale_num = 7;
|
||||
jpeg_config_input.scale_denom = 8;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
void jpeg_size(FILE* infile, int* height, int* width);
|
||||
|
||||
int jpeg_to_jpeg(FILE* input, FILE* output);
|
||||
int jpeg_to_jpeg(FILE* input, FILE* output, int targetSize);
|
||||
|
||||
int jpeg_to_webp(FILE* input, FILE* output);
|
||||
int jpeg_to_webp(FILE* input, FILE* output, int targetSize);
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ static int MyWriter(const uint8_t* data, size_t data_size, const WebPPicture* co
|
|||
return data_size ? (fwrite(data, data_size, 1, out) == 1) : 1;
|
||||
}
|
||||
|
||||
int png_to_webp(FILE* input, FILE* output) {
|
||||
int png_to_webp(FILE* input, FILE* output, int targetSize) {
|
||||
WebPPicture picture;
|
||||
|
||||
#ifdef HAS_DEBUG
|
||||
|
|
@ -79,9 +79,9 @@ int png_to_webp(FILE* input, FILE* output) {
|
|||
return 1;
|
||||
}
|
||||
DEBUG("rescale start");
|
||||
if (image.width > TARGET_SIZE && image.height > TARGET_SIZE) {
|
||||
float ratioHeight = (float) image.height / TARGET_SIZE;
|
||||
float ratioWidth = (float) image.width / TARGET_SIZE;
|
||||
if (image.width > targetSize && image.height > targetSize) {
|
||||
float ratioHeight = (float) image.height / targetSize;
|
||||
float ratioWidth = (float) image.width / targetSize;
|
||||
float ratio = ratioWidth > ratioHeight ? ratioHeight : ratioWidth;
|
||||
if (!WebPPictureRescale(&picture, image.width / ratio, image.height / ratio)) {
|
||||
DEBUG("ERR Rescale");
|
||||
|
|
@ -97,7 +97,7 @@ int png_to_webp(FILE* input, FILE* output) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int png_to_png(FILE* input, FILE* output) {
|
||||
int png_to_png(FILE* input, FILE* output, int targetSize) {
|
||||
#ifdef HAS_DEBUG
|
||||
clock_t t;
|
||||
t = clock();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#include <stdio.h>
|
||||
|
||||
int png_to_webp(FILE* input, FILE* output);
|
||||
int png_to_webp(FILE* input, FILE* output, int targetSize);
|
||||
|
||||
int png_to_png(FILE* input, FILE* output);
|
||||
int png_to_png(FILE* input, FILE* output, int targetSize);
|
||||
|
|
|
|||
|
|
@ -6,12 +6,12 @@
|
|||
|
||||
#define BUF_SIZE 1024 * 1024
|
||||
|
||||
int raw_to_jpeg(FILE* input, FILE* output) {
|
||||
int raw_to_jpeg(FILE* input, FILE* output, int targetSize) {
|
||||
#ifdef HAS_DEBUG
|
||||
clock_t t;
|
||||
t = clock();
|
||||
#endif
|
||||
|
||||
|
||||
char fname_in[32] = "/tmp/filestash.XXXXXX";
|
||||
int _mkstemp_in = mkstemp(fname_in);
|
||||
if (_mkstemp_in == -1) {
|
||||
|
|
@ -35,12 +35,12 @@ int raw_to_jpeg(FILE* input, FILE* output) {
|
|||
DEBUG("libraw open file");
|
||||
if (libraw_open_file(raw, fname_in) != 0) {
|
||||
ERROR("libraw_open_file");
|
||||
libraw_close(raw);
|
||||
libraw_close(raw);
|
||||
fclose(f_in);
|
||||
remove(fname_in);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
raw->params.output_tiff = 1;
|
||||
DEBUG("libraw unpack thumb");
|
||||
char fname_out[32] = "/tmp/filestash.XXXXXX";
|
||||
|
|
@ -51,14 +51,14 @@ int raw_to_jpeg(FILE* input, FILE* output) {
|
|||
fclose(f_in);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
if (libraw_unpack_thumb(raw) == 0 && raw->thumbnail.tformat == LIBRAW_THUMBNAIL_JPEG) {
|
||||
DEBUG("has an embed thumbnail");
|
||||
if (libraw_dcraw_thumb_writer(raw, fname_out) == 0) {
|
||||
DEBUG("process thumbnail");
|
||||
libraw_close(raw);
|
||||
FILE* f_out = fdopen(_mkstemp_out, "r");
|
||||
int err = jpeg_to_jpeg(f_out, output);
|
||||
int err = jpeg_to_jpeg(f_out, output, targetSize);
|
||||
fclose(f_out);
|
||||
fclose(f_in);
|
||||
remove(fname_in);
|
||||
|
|
@ -78,5 +78,5 @@ int raw_to_jpeg(FILE* input, FILE* output) {
|
|||
remove(fname_in);
|
||||
remove(fname_out);
|
||||
libraw_close(raw);
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,4 +4,4 @@
|
|||
#include "utils.h"
|
||||
#include "image_jpeg.h"
|
||||
|
||||
int raw_to_jpeg(FILE* input, FILE* output);
|
||||
int raw_to_jpeg(FILE* input, FILE* output, int targetSize);
|
||||
|
|
|
|||
|
|
@ -3,5 +3,3 @@
|
|||
#include "utils.h"
|
||||
|
||||
#define JPEG_QUALITY 50
|
||||
|
||||
#define min(a, b) (a > b ? b : a)
|
||||
|
|
|
|||
|
|
@ -2,5 +2,5 @@
|
|||
#include "image_jpeg.h"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
return jpeg_to_jpeg(stdin, stdout);
|
||||
return jpeg_to_jpeg(stdin, stdout, 200);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,5 +2,5 @@
|
|||
#include "image_png.h"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
return png_to_webp(stdin, stdout);
|
||||
return png_to_webp(stdin, stdout, 200);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
#include "image_raw.h"
|
||||
|
||||
int main(int args, const char **argv) {
|
||||
return raw_to_jpeg(stdin, stdout);
|
||||
int targetSize = 200;
|
||||
if(args >= 2) {
|
||||
targetSize = atoi(argv[1]);
|
||||
}
|
||||
return raw_to_jpeg(stdin, stdout, targetSize);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
#define TARGET_SIZE 200
|
||||
|
||||
#define HAS_DEBUG 1
|
||||
#if HAS_DEBUG == 1
|
||||
#include <time.h>
|
||||
|
|
@ -10,3 +8,5 @@
|
|||
#endif
|
||||
|
||||
#define ERROR(r) (fprintf(stderr, "[ERROR:('" r "')]"))
|
||||
|
||||
#define min(a, b) (a > b ? b : a)
|
||||
|
|
|
|||
Loading…
Reference in a new issue