Commit 405c43df authored by Tim Coates (CPVV)'s avatar Tim Coates (CPVV)

Resize default image

parent 88c2ff1f
......@@ -6,7 +6,8 @@ plugins {
group = 'au.com.tpic'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '14'
sourceCompatibility = '11'
targetCompatibility = '11'
configurations {
compileOnly {
......@@ -26,6 +27,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-aop'
implementation group: 'com.google.guava', name: 'guava', version: '29.0-jre'
implementation group: 'com.mortennobel', name: 'java-image-scaling', version: '0.8.6'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
......
package au.com.tpic.avatar.services;
import au.com.tpic.avatar.configuration.AvatarServiceProperites;
import com.mortennobel.imagescaling.ResampleFilters;
import com.mortennobel.imagescaling.ResampleOp;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
......@@ -24,6 +26,8 @@ import java.util.stream.Stream;
public class AvatarService {
private final HashMap<String, Path> fileList;
private static final String DEFAULT_FORMAT = "jpg";
private static final Path DEFAULT_IMAGE_PATH = new File(AvatarService.class.getResource("/default.jpg").getFile()).toPath();
public AvatarService(AvatarServiceProperites properites) throws IOException {
Stream<Path> avatars = Files.walk(properites.getDirectory());
......@@ -35,13 +39,11 @@ public class AvatarService {
try {
String hash = getRequestHash(request);
MediaType format = getRequestFormat(request);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
BufferedImage image = (fileList.containsKey(hash)) ? readImageToSize(fileList.get(hash), Integer.parseInt(size)) : generateIdenticons(hash, Integer.parseInt(size));
ImageIO.write(image, format.getSubtype(), baos);
return ResponseEntity.ok().contentType(format).body(baos.toByteArray());
return ResponseEntity.ok().contentType(format).body(writeToFormat(image, format.getSubtype()));
} catch (Exception ignored) {
byte[] body = getClass().getClassLoader().getResourceAsStream("default.jpg").readAllBytes();
return ResponseEntity.ok().contentType(MediaType.IMAGE_JPEG).body(body);
BufferedImage defaultImage = readImageToSize(DEFAULT_IMAGE_PATH, Integer.parseInt(size));
return ResponseEntity.ok().contentType(MediaType.IMAGE_JPEG).body(writeToFormat(defaultImage, DEFAULT_FORMAT));
}
}
......@@ -70,24 +72,25 @@ public class AvatarService {
}
}
BufferedImage finalImage = new BufferedImage(size, size, BufferedImage.TYPE_INT_RGB);
//Scale image to the size you want
AffineTransform at = new AffineTransform();
at.scale(size / width, size / height);
AffineTransformOp op = new AffineTransformOp(at, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
finalImage = op.filter(identicon, finalImage);
return finalImage;
return op.filter(identicon, null);
}
private BufferedImage readImageToSize(Path image, int size) throws IOException {
BufferedImage inputImage = ImageIO.read(image.toFile());
private BufferedImage readImageToSize(Path imagePath, int size) throws IOException {
BufferedImage inputImage = ImageIO.read(imagePath.toFile());
int newHeight = inputImage.getHeight() / inputImage.getWidth() * size;
BufferedImage outputImage = new BufferedImage(size, newHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics2D = outputImage.createGraphics();
graphics2D.drawImage(inputImage, 0, 0, size, newHeight, null);
return outputImage;
ResampleOp resizeOp = new ResampleOp(size, newHeight);
resizeOp.setFilter(ResampleFilters.getLanczos3Filter());
return resizeOp.filter(inputImage, null);
}
private byte[] writeToFormat(BufferedImage image, String format) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(image, format, baos);
return baos.toByteArray();
}
private String getFileHash(Path path) {
......
......@@ -23,21 +23,22 @@ class AvatarServiceTest {
@Test
void getDefaultAvatar() throws IOException {
byte[] expectedBody = getClass().getResourceAsStream("/default.jpg").readAllBytes();
byte[] expectedBody = getClass().getResourceAsStream("/default-200.jpg").readAllBytes();
ResponseEntity<byte[]> expectedResponse = ResponseEntity.ok().contentType(MediaType.IMAGE_JPEG).body(expectedBody);
// Files.write(avatarService.getAvatar(null, "200").getBody(),new File("default-200.jpg"));
assertThat(avatarService.getAvatar(null, "200")).isEqualTo(expectedResponse);
}
@Test
void getIdenticonAvatar() throws IOException {
byte[] expectedBody = getClass().getResourceAsStream("/B725DDDD5F2F979522DCC55A05E.jpg").readAllBytes();
byte[] expectedBody = getClass().getResourceAsStream("/identicon-200.jpg").readAllBytes();
ResponseEntity<byte[]> expectedResponse = ResponseEntity.ok().contentType(MediaType.IMAGE_JPEG).body(expectedBody);
assertThat(avatarService.getAvatar("B725DDDD5F2F979522DCC55A05E", "200")).isEqualTo(expectedResponse);
}
@Test
void getAvatarFromDirectory() throws IOException {
byte[] expectedBody = getClass().getResourceAsStream("/test.png").readAllBytes();
byte[] expectedBody = getClass().getResourceAsStream("/test-200.png").readAllBytes();
ResponseEntity<byte[]> expectedResponse = ResponseEntity.ok().contentType(MediaType.IMAGE_PNG).body(expectedBody);
assertThat(avatarService.getAvatar("098f6bcd4621d373cade4e832627b4f6.png", "200")).isEqualTo(expectedResponse);
}
......
......@@ -22,7 +22,7 @@ class AvatarControllerTest {
@Test
void getDefaultAvatar() throws Exception {
byte[] expectedImage = getClass().getResourceAsStream("/default.jpg").readAllBytes();
byte[] expectedImage = getClass().getResourceAsStream("/default-200.jpg").readAllBytes();
mockMvc.perform(get("/avatar"))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.IMAGE_JPEG))
......@@ -31,7 +31,7 @@ class AvatarControllerTest {
@Test
void getAvatarFromDirectory() throws Exception {
byte[] expectedImage = getClass().getResourceAsStream("/test.png").readAllBytes();
byte[] expectedImage = getClass().getResourceAsStream("/test-200.png").readAllBytes();
mockMvc.perform(get("/avatar/098f6bcd4621d373cade4e832627b4f6.png"))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.IMAGE_PNG))
......
src/test/resources/test-100.jpg

1.83 KB | W: | H:

src/test/resources/test-100.jpg

1.76 KB | W: | H:

src/test/resources/test-100.jpg
src/test/resources/test-100.jpg
src/test/resources/test-100.jpg
src/test/resources/test-100.jpg
  • 2-up
  • Swipe
  • Onion skin
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