Commit 82e8b490 authored by Matija Obreza's avatar Matija Obreza

Merge branch 'server-446-better-thumbnail-quality' into 'master'

Thumbnails as JPEGs

See merge request !32
parents 7adf7dd7 71ae1fae
Pipeline #10121 passed with stage
in 1 minute and 25 seconds
/*
* Copyright 2018 Global Crop Diversity Trust
* Copyright 2019 Global Crop Diversity Trust
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -24,7 +24,6 @@ import org.genesys.filerepository.model.RepositoryFolder;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
// TODO: Auto-generated Javadoc
/**
* The ImageGalleryService.
*/
......@@ -34,7 +33,10 @@ public interface ImageGalleryService {
public static final String THUMB_PATH = "/_thumbs";
/** The Constant THUMB_EXT. */
public static final String THUMB_EXT = ".png";
public static final String THUMB_EXT = ".jpg";
/** The Constant THUMB_CONTENT_TYPE. */
public static final String THUMB_CONTENT_TYPE = "image/jpeg";
/**
* Loads gallery with the specified path.
......
......@@ -42,6 +42,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PreAuthorize;
......@@ -77,6 +78,9 @@ public class ImageGalleryServiceImpl implements ImageGalleryService {
/** Thumbnail generator. */
@Autowired
private ThumbnailGenerator thumbnailGenerator;
@Autowired(required = false)
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
/** The jpa query factory. */
@Autowired
......@@ -251,27 +255,40 @@ public class ImageGalleryServiceImpl implements ImageGalleryService {
return;
}
imageGallery2.getImages().forEach(repositoryImage -> {
try {
final byte[][] cache = new byte[1][];
for (int i = thumbnailSizes.length - 1; i >= 0; i--) {
cache[0] = ensureThumbnail(thumbnailSizes[i], thumbnailSizes[i], repositoryImage, () -> {
if (cache[0] != null) {
LOG.debug("Using cached image bytes for {}", repositoryImage.getStoragePath());
return cache[0];
} else {
LOG.info("Must load image bytes for {}", repositoryImage.getStoragePath());
return cache[0] = bytesStorageService.get(repositoryImage.storagePath());
}
});
}
} catch (final NullPointerException e) {
LOG.error("Error generating thumbnail for image={} message={}", repositoryImage, e.getMessage(), e);
} catch (final Exception e) {
LOG.error("Error generating thumbnail for " + repositoryImage, e);
imageGallery2.getImages().forEach(repositoryImage -> makeThumbnails(repositoryImage));
}
/**
* Use {@link #threadPoolTaskExecutor} if available.
*/
private void makeThumbnails(RepositoryImage repositoryImage) {
if (threadPoolTaskExecutor != null) {
threadPoolTaskExecutor.submit(() -> generateThumbnails(repositoryImage));
} else {
generateThumbnails(repositoryImage);
}
}
private void generateThumbnails(final RepositoryImage repositoryImage) {
try {
final byte[][] cache = new byte[1][];
for (int i = thumbnailSizes.length - 1; i >= 0; i--) {
cache[0] = ensureThumbnail(thumbnailSizes[i], thumbnailSizes[i], repositoryImage, () -> {
if (cache[0] != null) {
LOG.debug("Using cached image bytes for {}", repositoryImage.getStoragePath());
return cache[0];
} else {
LOG.info("Must load image bytes for {}", repositoryImage.getStoragePath());
return cache[0] = bytesStorageService.get(repositoryImage.storagePath());
}
});
}
});
} catch (final NullPointerException e) {
LOG.error("Error generating thumbnail for image={} message={}", repositoryImage, e.getMessage(), e);
} catch (final Exception e) {
LOG.error("Error generating thumbnail for " + repositoryImage, e);
}
}
/**
......@@ -327,12 +344,12 @@ public class ImageGalleryServiceImpl implements ImageGalleryService {
LOG.debug("Generating new thumbnail width={} height={} for image={}", width, height, repositoryImage.getUuid());
try {
final byte[] bytesPng = thumbnailGenerator.createThumbnail(width, height, loader.getImageBytes());
final byte[] thumbnailBytes = thumbnailGenerator.createThumbnail(width, height, loader.getImageBytes());
LOG.debug("Persisting new thumbnail width={} height={} for image={}", width, height, repositoryImage.getUuid());
bytesStorageService.upsert(getFullThumbnailsPath(repositoryImage).resolve(filename), bytesPng);
return bytesPng;
bytesStorageService.upsert(getFullThumbnailsPath(repositoryImage).resolve(filename), thumbnailBytes);
return thumbnailBytes;
} catch (NullPointerException e) {
LOG.warn("Error generating thumbnail: {}", e.getMessage());
}
......@@ -358,7 +375,7 @@ public class ImageGalleryServiceImpl implements ImageGalleryService {
if (height != null) {
sb.append(height);
}
sb.append(".png");
sb.append(ImageGalleryService.THUMB_EXT);
return sb.toString();
}
......
......@@ -56,13 +56,13 @@ public class ThumbnailGenerator1 implements ThumbnailGenerator {
final InputStream inputStream = new ByteArrayInputStream(imageBytes);
final Builder<? extends InputStream> th = Thumbnails.of(inputStream);
th.outputFormat("png");
th.outputFormat("jpg");
th.antialiasing(Antialiasing.ON);
th.alphaInterpolation(AlphaInterpolation.QUALITY);
// th.dithering(Dithering.DISABLE);
th.outputQuality(0.9f);
th.rendering(Rendering.QUALITY);
th.scalingMode(ScalingMode.BICUBIC);
th.scalingMode(ScalingMode.PROGRESSIVE_BILINEAR);
th.crop(Positions.CENTER);
if ((width != null) && (height != null)) {
......
......@@ -121,7 +121,7 @@ public class ImageGalleryThumbnailsTest extends RepositoryServiceTest {
final TestImage image1 = new TestImage("maize.jpg", "image/jpg");
final RepositoryImage repoImage1 = fileRepoService.addImage(initialPath, image1.getOriginalFilename(), image1.getContentType(), image1.getImageBytes(), null);
final byte[] thumbBytes1 = bytesStorageService.get(Paths.get(ImageGalleryService.THUMB_PATH, repoImage1.getThumbnailPath(), "200x200" + ".png"));
final byte[] thumbBytes1 = bytesStorageService.get(Paths.get(ImageGalleryService.THUMB_PATH, repoImage1.getThumbnailPath(), "200x200" + ImageGalleryService.THUMB_EXT));
assertThat("Thumbnail must not be null", thumbBytes1, notNullValue());
try (InputStream is = new ByteArrayInputStream(thumbBytes1)) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment