MME-10 Attempt to include heic support; just moving to extracting metadata from images instead.
This commit is contained in:
parent
0d80c92850
commit
38f80aa8cd
@ -102,15 +102,14 @@ dependencies {
|
|||||||
|
|
||||||
compileOnly 'org.jetbrains:annotations:26.0.2-1'
|
compileOnly 'org.jetbrains:annotations:26.0.2-1'
|
||||||
|
|
||||||
// https://mvnrepository.com/artifact/com.twelvemonkeys.imageio/imageio-webp
|
|
||||||
runtimeOnly 'com.twelvemonkeys.imageio:imageio-webp:3.12.0'
|
|
||||||
|
|
||||||
// https://mvnrepository.com/artifact/com.twelvemonkeys.imageio/imageio-batik
|
// https://mvnrepository.com/artifact/com.twelvemonkeys.imageio/imageio-batik
|
||||||
runtimeOnly 'com.twelvemonkeys.imageio:imageio-batik:3.12.0'
|
runtimeOnly 'com.twelvemonkeys.imageio:imageio-batik:3.12.0'
|
||||||
|
|
||||||
// https://mvnrepository.com/artifact/org.apache.xmlgraphics/batik-all
|
// https://mvnrepository.com/artifact/org.apache.xmlgraphics/batik-all
|
||||||
runtimeOnly 'org.apache.xmlgraphics:batik-all:1.19'
|
runtimeOnly 'org.apache.xmlgraphics:batik-all:1.19'
|
||||||
|
|
||||||
|
implementation 'com.drewnoakes:metadata-extractor:2.19.0'
|
||||||
|
|
||||||
// Custom testing
|
// Custom testing
|
||||||
testImplementation 'org.testcontainers:testcontainers:1.21.4'
|
testImplementation 'org.testcontainers:testcontainers:1.21.4'
|
||||||
testImplementation 'org.testcontainers:junit-jupiter:1.21.4'
|
testImplementation 'org.testcontainers:junit-jupiter:1.21.4'
|
||||||
|
|||||||
BIN
src/integrationTest/resources/willow.HEIC
Normal file
BIN
src/integrationTest/resources/willow.HEIC
Normal file
Binary file not shown.
@ -7,6 +7,14 @@ import app.mealsmadeeasy.api.user.User;
|
|||||||
import app.mealsmadeeasy.api.util.MimeTypeService;
|
import app.mealsmadeeasy.api.util.MimeTypeService;
|
||||||
import app.mealsmadeeasy.api.util.NoSuchEntityWithIdException;
|
import app.mealsmadeeasy.api.util.NoSuchEntityWithIdException;
|
||||||
import app.mealsmadeeasy.api.util.NoSuchEntityWithUsernameAndFilenameException;
|
import app.mealsmadeeasy.api.util.NoSuchEntityWithUsernameAndFilenameException;
|
||||||
|
import com.drew.imaging.ImageMetadataReader;
|
||||||
|
import com.drew.imaging.ImageProcessingException;
|
||||||
|
import com.drew.metadata.Directory;
|
||||||
|
import com.drew.metadata.Metadata;
|
||||||
|
import com.drew.metadata.MetadataException;
|
||||||
|
import com.drew.metadata.jpeg.JpegDirectory;
|
||||||
|
import com.drew.metadata.png.PngDirectory;
|
||||||
|
import com.drew.metadata.webp.WebpDirectory;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
@ -103,6 +111,33 @@ public class S3ImageService implements ImageService {
|
|||||||
return didTransfer;
|
return didTransfer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private record HeightWidth(int height, int width) {}
|
||||||
|
|
||||||
|
private <D extends Directory> HeightWidth getHeightAndWidthFromMetadata(
|
||||||
|
InputStream inputStream,
|
||||||
|
Class<D> directoryClass,
|
||||||
|
int heightTag,
|
||||||
|
int widthTag,
|
||||||
|
String debugName
|
||||||
|
) throws IOException {
|
||||||
|
try {
|
||||||
|
final Metadata metadata = ImageMetadataReader.readMetadata(inputStream);
|
||||||
|
final D directory = metadata.getFirstDirectoryOfType(directoryClass);
|
||||||
|
if (directory == null) {
|
||||||
|
throw new RuntimeException("Unable to get " + directoryClass.getSimpleName() + " for " + debugName);
|
||||||
|
}
|
||||||
|
if (!directory.containsTag(heightTag)) {
|
||||||
|
throw new RuntimeException("Unable to find height tag for " + debugName);
|
||||||
|
}
|
||||||
|
if (!directory.containsTag(widthTag)) {
|
||||||
|
throw new RuntimeException("Unable to find width tag for " + debugName);
|
||||||
|
}
|
||||||
|
return new HeightWidth(directory.getInt(heightTag), directory.getInt(widthTag));
|
||||||
|
} catch (ImageProcessingException | MetadataException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @apiNote Consumes and closes the {@link java.io.InputStream}.
|
* @apiNote Consumes and closes the {@link java.io.InputStream}.
|
||||||
*
|
*
|
||||||
@ -137,15 +172,43 @@ public class S3ImageService implements ImageService {
|
|||||||
this.imageBucketName, filename, mimeType, toStore, objectSize
|
this.imageBucketName, filename, mimeType, toStore, objectSize
|
||||||
);
|
);
|
||||||
|
|
||||||
final BufferedImage bufferedImage = ImageIO.read(toRead);
|
final HeightWidth hw;
|
||||||
if (bufferedImage == null) {
|
switch (mimeType) {
|
||||||
throw new ImageException(
|
case "image/jpeg" -> {
|
||||||
ImageException.Type.UNSUPPORTED_IMAGE_TYPE,
|
hw = this.getHeightAndWidthFromMetadata(
|
||||||
"ImageIO could not read image: " + userFilename
|
toRead,
|
||||||
|
JpegDirectory.class,
|
||||||
|
JpegDirectory.TAG_IMAGE_HEIGHT,
|
||||||
|
JpegDirectory.TAG_IMAGE_WIDTH,
|
||||||
|
userFilename
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
final int height = bufferedImage.getHeight();
|
case "image/png" -> {
|
||||||
final int width = bufferedImage.getWidth();
|
hw = this.getHeightAndWidthFromMetadata(
|
||||||
|
toRead,
|
||||||
|
PngDirectory.class,
|
||||||
|
PngDirectory.TAG_IMAGE_HEIGHT,
|
||||||
|
PngDirectory.TAG_IMAGE_WIDTH,
|
||||||
|
userFilename
|
||||||
|
);
|
||||||
|
}
|
||||||
|
case "image/webp" -> {
|
||||||
|
hw = this.getHeightAndWidthFromMetadata(
|
||||||
|
toRead,
|
||||||
|
WebpDirectory.class,
|
||||||
|
WebpDirectory.TAG_IMAGE_HEIGHT,
|
||||||
|
WebpDirectory.TAG_IMAGE_WIDTH,
|
||||||
|
userFilename
|
||||||
|
);
|
||||||
|
}
|
||||||
|
case "image/svg+xml" -> {
|
||||||
|
final BufferedImage bufferedImage = ImageIO.read(toRead);
|
||||||
|
hw = new HeightWidth(bufferedImage.getHeight(), bufferedImage.getWidth());
|
||||||
|
}
|
||||||
|
default -> throw new RuntimeException("Unsupported mime type: " + mimeType);
|
||||||
|
}
|
||||||
|
final int height = hw.height();
|
||||||
|
final int width = hw.width();
|
||||||
|
|
||||||
toRead.close();
|
toRead.close();
|
||||||
toStore.close();
|
toStore.close();
|
||||||
|
|||||||
@ -19,7 +19,7 @@ public class MimeTypeService {
|
|||||||
final Matcher m = extensionPattern.matcher(userFilename);
|
final Matcher m = extensionPattern.matcher(userFilename);
|
||||||
if (m.matches()) {
|
if (m.matches()) {
|
||||||
final String extension = m.group(1);
|
final String extension = m.group(1);
|
||||||
return switch (extension) {
|
return switch (extension.toLowerCase()) {
|
||||||
case "jpg", "jpeg" -> IMAGE_JPEG;
|
case "jpg", "jpeg" -> IMAGE_JPEG;
|
||||||
case "png" -> IMAGE_PNG;
|
case "png" -> IMAGE_PNG;
|
||||||
case "svg" -> IMAGE_SVG;
|
case "svg" -> IMAGE_SVG;
|
||||||
@ -32,7 +32,7 @@ public class MimeTypeService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getExtension(String mimeType) {
|
public String getExtension(String mimeType) {
|
||||||
return switch (mimeType) {
|
return switch (mimeType.toLowerCase()) {
|
||||||
case IMAGE_JPEG -> "jpg";
|
case IMAGE_JPEG -> "jpg";
|
||||||
case IMAGE_PNG -> "png";
|
case IMAGE_PNG -> "png";
|
||||||
case IMAGE_SVG -> "svg";
|
case IMAGE_SVG -> "svg";
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user