From 947b9dc27f1a7d3435064a80593531ebe6b82827 Mon Sep 17 00:00:00 2001 From: ken479 Date: Thu, 8 Jul 2021 11:34:12 +0800 Subject: [PATCH 1/8] :recycle: Refactor code on Image Handling and Integrate OpenCV Java --- .../main/java/ai/classifai/ClassifaiApp.java | 3 + classifai-core/pom.xml | 4 + .../data/type/image/BmpImageData.java | 60 +++++++- .../classifai/data/type/image/ImageData.java | 97 ++++++++++++- .../data/type/image/ImageDataFactory.java | 51 ------- .../data/type/image/ImageFileType.java | 3 +- .../data/type/image/JpegImageData.java | 86 ++++++++++- .../data/type/image/PngImageData.java | 52 +++++-- .../data/type/image/WebpImageData.java | 83 +++++++++++ .../annotation/AnnotationVerticle.java | 14 +- .../ai/classifai/util/data/ImageHandler.java | 133 +++++++----------- pom.xml | 6 + 12 files changed, 423 insertions(+), 169 deletions(-) delete mode 100644 classifai-core/src/main/java/ai/classifai/data/type/image/ImageDataFactory.java create mode 100644 classifai-core/src/main/java/ai/classifai/data/type/image/WebpImageData.java diff --git a/classifai-api/src/main/java/ai/classifai/ClassifaiApp.java b/classifai-api/src/main/java/ai/classifai/ClassifaiApp.java index 68df8a86b..71644e3e5 100644 --- a/classifai-api/src/main/java/ai/classifai/ClassifaiApp.java +++ b/classifai-api/src/main/java/ai/classifai/ClassifaiApp.java @@ -36,6 +36,9 @@ public static void main(String[] args) //initiate to run cli arguments new CLIArgument(args); + // Load native library to implement OpenCV Java + nu.pattern.OpenCV.loadLocally(); + VertxOptions vertxOptions = new VertxOptions(); vertxOptions.setMaxEventLoopExecuteTimeUnit(TimeUnit.SECONDS); diff --git a/classifai-core/pom.xml b/classifai-core/pom.xml index 2845629f6..3a97f65d9 100644 --- a/classifai-core/pom.xml +++ b/classifai-core/pom.xml @@ -116,6 +116,10 @@ com.drewnoakes metadata-extractor + + org.openpnp + opencv + diff --git a/classifai-core/src/main/java/ai/classifai/data/type/image/BmpImageData.java b/classifai-core/src/main/java/ai/classifai/data/type/image/BmpImageData.java index 31d279201..259338d04 100644 --- a/classifai-core/src/main/java/ai/classifai/data/type/image/BmpImageData.java +++ b/classifai-core/src/main/java/ai/classifai/data/type/image/BmpImageData.java @@ -26,20 +26,66 @@ */ public class BmpImageData extends ImageData { - public BmpImageData(Metadata metadata) - { - super(metadata); + private final int S_RGB_COLOR_SPACE = 1934772034; + + protected BmpImageData(Metadata metadata) { + super(metadata, BmpHeaderDirectory.class); } @Override - public int getWidth() throws MetadataException + public int getOrientation() { + // same as original image + return 1; + } + + @Override + public int getWidth() { - return metadata.getFirstDirectoryOfType(BmpHeaderDirectory.class).getInt(BmpHeaderDirectory.TAG_IMAGE_WIDTH); + try + { + return directory.getInt(BmpHeaderDirectory.TAG_IMAGE_WIDTH); + } + catch (MetadataException e) + { + logMetadataError(); + return 0; + } } @Override - public int getHeight() throws MetadataException + public int getHeight() { - return metadata.getFirstDirectoryOfType(BmpHeaderDirectory.class).getInt(BmpHeaderDirectory.TAG_IMAGE_HEIGHT); + try { + return directory.getInt(BmpHeaderDirectory.TAG_IMAGE_HEIGHT); + } + catch (MetadataException e) + { + logMetadataError(); + return 0; + } } + + /** + * color space type: [1934772034: sRGB, null: BnW] + * @return number of channels 1 or 3 + */ + @Override + public int getDepth() { + try { + int colorSpaceType = directory.getInt(BmpHeaderDirectory.TAG_COLOR_SPACE_TYPE); + if (colorSpaceType == S_RGB_COLOR_SPACE) + { + return 3; + } + } + catch (MetadataException ignored){} + + return 1; + } + + @Override + public String getMimeType() { + return "image/bmp"; + } + } \ No newline at end of file diff --git a/classifai-core/src/main/java/ai/classifai/data/type/image/ImageData.java b/classifai-core/src/main/java/ai/classifai/data/type/image/ImageData.java index e1766fb22..fc1fbf318 100644 --- a/classifai-core/src/main/java/ai/classifai/data/type/image/ImageData.java +++ b/classifai-core/src/main/java/ai/classifai/data/type/image/ImageData.java @@ -15,23 +15,110 @@ */ package ai.classifai.data.type.image; +import ai.classifai.util.exception.NotSupportedImageTypeException; +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.bmp.BmpHeaderDirectory; +import com.drew.metadata.jpeg.JpegDirectory; +import com.drew.metadata.png.PngDirectory; +import com.drew.metadata.webp.WebpDirectory; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; /** * ImageData provides metadata of images * * @author YCCertifai */ +@Slf4j public abstract class ImageData { + @Getter protected Metadata metadata; + protected Directory directory; - protected ImageData(Metadata metadata) - { + protected ImageData(Metadata metadata, Class directoryClass) { this.metadata = metadata; + this.directory = metadata.getFirstDirectoryOfType(directoryClass); + } + + public abstract int getOrientation(); + + public abstract int getWidth(); + + public abstract int getHeight(); + + public abstract int getDepth(); + + public abstract String getMimeType(); + + protected void logMetadataError() { + log.error("Unhandled metadata error, this should be protected by ImageFactory"); + } + + public static ImageData getImageData(File filePath) + { + try + { + Metadata metadata = ImageMetadataReader.readMetadata(filePath); + + return ImageDataFactory.getImageData(metadata); + } + catch (ImageProcessingException | IOException e) + { + log.debug(String.format("%s is not an image", filePath)); + return null; + } + catch (NotSupportedImageTypeException e) + { + log.debug(String.format("%s is not supported \n %s", filePath, e.getMessage())); + return null; + } + } + + public static ImageData getImageData(byte [] bytes){ + try + { + Metadata metadata = ImageMetadataReader.readMetadata(new ByteArrayInputStream(bytes)); + + return ImageDataFactory.getImageData(metadata); + } + catch (ImageProcessingException | IOException e) + { + log.debug("byte array received is not an image"); + return null; + } + catch (NotSupportedImageTypeException e) + { + log.debug("byte array received is not supported"); + return null; + } + + } + + public static class ImageDataFactory { + private ImageDataFactory() { + } + + public static ImageData getImageData(Metadata metadata) throws NotSupportedImageTypeException { + if (metadata.containsDirectoryOfType(JpegDirectory.class)) { + return new JpegImageData(metadata); + } else if (metadata.containsDirectoryOfType(PngDirectory.class)) { + return new PngImageData(metadata); + } else if (metadata.containsDirectoryOfType(BmpHeaderDirectory.class)) { + return new BmpImageData(metadata); + } else if (metadata.containsDirectoryOfType(WebpDirectory.class)) { + return new WebpImageData(metadata); + } else { + throw new NotSupportedImageTypeException(String.format("%s type not supported", metadata.getDirectories())); + } + } } - public abstract int getWidth() throws MetadataException; - public abstract int getHeight() throws MetadataException; } \ No newline at end of file diff --git a/classifai-core/src/main/java/ai/classifai/data/type/image/ImageDataFactory.java b/classifai-core/src/main/java/ai/classifai/data/type/image/ImageDataFactory.java deleted file mode 100644 index df3f83b33..000000000 --- a/classifai-core/src/main/java/ai/classifai/data/type/image/ImageDataFactory.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2020-2021 CertifAI Sdn. Bhd. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0. - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package ai.classifai.data.type.image; - -import ai.classifai.util.exception.NotSupportedImageTypeException; -import com.drew.metadata.Metadata; -import com.drew.metadata.bmp.BmpHeaderDirectory; -import com.drew.metadata.jpeg.JpegDirectory; -import com.drew.metadata.png.PngDirectory; - -/** - * ImageDataFactory to return subclass of ImageData based on metadata - * throw NotSupportedImageTypeError if image type is not supported - * - * @author YCCertifai - */ -public class ImageDataFactory -{ - public ImageData getImageData(Metadata metadata) throws NotSupportedImageTypeException - { - if (metadata.containsDirectoryOfType(JpegDirectory.class)) - { - return new JpegImageData(metadata); - } - else if (metadata.containsDirectoryOfType(PngDirectory.class)) - { - return new PngImageData(metadata); - } - else if (metadata.containsDirectoryOfType(BmpHeaderDirectory.class)) - { - return new BmpImageData(metadata); - } - else - { - throw new NotSupportedImageTypeException(String.format("%s type not supported", metadata.getDirectories())); - } - } -} \ No newline at end of file diff --git a/classifai-core/src/main/java/ai/classifai/data/type/image/ImageFileType.java b/classifai-core/src/main/java/ai/classifai/data/type/image/ImageFileType.java index ab6b360ba..2181b7467 100644 --- a/classifai-core/src/main/java/ai/classifai/data/type/image/ImageFileType.java +++ b/classifai-core/src/main/java/ai/classifai/data/type/image/ImageFileType.java @@ -37,7 +37,7 @@ public class ImageFileType { private static final Map BASE_64_HEADER; - private static final String[] ALLOWED_FILE_TYPES = new String[]{"jpg", "png", "jpeg", "bmp", "JPG", "PNG", "JPEG"}; //{"jpg", "png", "jpeg", "pdf", "bmp", "JPG", "PNG", "JPEG"}; + private static final String[] ALLOWED_FILE_TYPES = new String[]{"jpg", "png", "jpeg", "bmp", "JPG", "PNG", "JPEG", "webp"}; //{"jpg", "png", "jpeg", "pdf", "bmp", "JPG", "PNG", "JPEG"}; static { @@ -49,6 +49,7 @@ public class ImageFileType { BASE_64_HEADER.put("png", "data:image/jpeg;base64,"); BASE_64_HEADER.put("PNG", "data:image/png;base64,"); BASE_64_HEADER.put("bmp", "data:image/bmp;base64,"); + BASE_64_HEADER.put("webp", "data:image/bmp;base64,"); } public static String[] getImageFileTypes() diff --git a/classifai-core/src/main/java/ai/classifai/data/type/image/JpegImageData.java b/classifai-core/src/main/java/ai/classifai/data/type/image/JpegImageData.java index c5d6685fc..eff9310a2 100644 --- a/classifai-core/src/main/java/ai/classifai/data/type/image/JpegImageData.java +++ b/classifai-core/src/main/java/ai/classifai/data/type/image/JpegImageData.java @@ -17,6 +17,7 @@ import com.drew.metadata.Metadata; import com.drew.metadata.MetadataException; +import com.drew.metadata.exif.ExifIFD0Directory; import com.drew.metadata.jpeg.JpegDirectory; /** @@ -26,18 +27,89 @@ */ public class JpegImageData extends ImageData { - public JpegImageData(Metadata metadata) - { - super(metadata); + protected JpegImageData(Metadata metadata) { + super(metadata, JpegDirectory.class); } + private int getRawWidth() { + try { + return metadata.getFirstDirectoryOfType(JpegDirectory.class).getInt(JpegDirectory.TAG_IMAGE_WIDTH); + } catch (MetadataException e) { + logMetadataError(); + return 0; + } + } + + private int getRawHeight() { + try { + return metadata.getFirstDirectoryOfType(JpegDirectory.class).getInt(JpegDirectory.TAG_IMAGE_HEIGHT); + } catch (MetadataException e) { + logMetadataError(); + return 0; + } + } + + /** + * get Exif orientation from metatdata + * orientation value: [1: 0 deg, 8: 270 deg, 3: 180 deg, 6: 90 deg] + * ref: https://www.impulseadventure.com/photo/exif-orientation.html + * + * 1 = 0 degree (Horizontal, normal) + * 2 = 0 degree,mirrored (Mirror horizontally) + * 3 = 180 degree (Rotate 180 degree) + * 4 = 180 degree,mirrored (Mirror vertically) + * 5 = 90 degree, mirrored (Mirror horizontal and rotate 270 degree clockwise) + * 6 = 90 degree CW (Rotate 90 degree clockwise) + * 7 = 270 degree, mirrored (Mirror horizontal and rotate 90 degree clockwise) + * 8 = 270 degree CW (Rotate 270 degree clockwise) + * + * @return orientation + */ + @Override - public int getWidth() throws MetadataException { - return metadata.getFirstDirectoryOfType(JpegDirectory.class).getInt(JpegDirectory.TAG_IMAGE_WIDTH); + public int getOrientation() { + try { + return metadata.getFirstDirectoryOfType(ExifIFD0Directory.class).getInt(ExifIFD0Directory.TAG_ORIENTATION); + } catch (Exception ignored) { + // if can't find orientation set as 0 deg + return 1; + } } @Override - public int getHeight() throws MetadataException { - return metadata.getFirstDirectoryOfType(JpegDirectory.class).getInt(JpegDirectory.TAG_IMAGE_HEIGHT); + public int getWidth() { + int orientation = getOrientation(); + + if (orientation == 8 || orientation == 6) { + return getRawHeight(); + } + + return getRawWidth(); } + + @Override + public int getHeight() { + int orientation = getOrientation(); + + if (orientation == 8 || orientation == 6) { + return getRawWidth(); + } + + return getRawHeight(); + } + + @Override + public int getDepth() { + try { + return directory.getInt(JpegDirectory.TAG_NUMBER_OF_COMPONENTS); + } catch (Exception ignored) { + return 3; + } + } + + @Override + public String getMimeType() { + return "image/jpg"; + } + } \ No newline at end of file diff --git a/classifai-core/src/main/java/ai/classifai/data/type/image/PngImageData.java b/classifai-core/src/main/java/ai/classifai/data/type/image/PngImageData.java index 15b63cad4..0b51ca7ff 100644 --- a/classifai-core/src/main/java/ai/classifai/data/type/image/PngImageData.java +++ b/classifai-core/src/main/java/ai/classifai/data/type/image/PngImageData.java @@ -26,20 +26,54 @@ */ public class PngImageData extends ImageData { - public PngImageData(Metadata metadata) - { - super(metadata); + protected PngImageData(Metadata metadata) { + super(metadata, PngDirectory.class); } @Override - public int getWidth() throws MetadataException - { - return metadata.getFirstDirectoryOfType(PngDirectory.class).getInt(PngDirectory.TAG_IMAGE_WIDTH); + public int getOrientation() { + // same as original image + return 1; } @Override - public int getHeight() throws MetadataException - { - return metadata.getFirstDirectoryOfType(PngDirectory.class).getInt(PngDirectory.TAG_IMAGE_HEIGHT); + public int getWidth() { + try { + return directory.getInt(PngDirectory.TAG_IMAGE_WIDTH); + } catch (MetadataException e) { + logMetadataError(); + return 0; + } + } + + @Override + public int getHeight() { + try { + return directory.getInt(PngDirectory.TAG_IMAGE_HEIGHT); + } catch (MetadataException e) { + logMetadataError(); + return 0; + } + } + + /** + * get color type: [0: grayscale, 2: trueColor(RGB)] + * + * @return number of channel 1 or 3 + */ + @Override + public int getDepth() { + try { + int colorType = directory.getInt(PngDirectory.TAG_COLOR_TYPE); + + if (colorType == 0) return 1; + } catch (Exception ignored) { + } + return 3; + } + + @Override + public String getMimeType() { + return "image/png"; } } \ No newline at end of file diff --git a/classifai-core/src/main/java/ai/classifai/data/type/image/WebpImageData.java b/classifai-core/src/main/java/ai/classifai/data/type/image/WebpImageData.java new file mode 100644 index 000000000..20d0a9edf --- /dev/null +++ b/classifai-core/src/main/java/ai/classifai/data/type/image/WebpImageData.java @@ -0,0 +1,83 @@ +package ai.classifai.data.type.image; + +import com.drew.metadata.Metadata; +import com.drew.metadata.MetadataException; +import com.drew.metadata.exif.ExifDirectoryBase; +import com.drew.metadata.exif.ExifIFD0Directory; +import com.drew.metadata.webp.WebpDirectory; + +public class WebpImageData extends ImageData{ + + protected WebpImageData(Metadata metadata) + { + super(metadata, WebpDirectory.class); + } + + private int getRawWidth() + { + try { + return directory.getInt(WebpDirectory.TAG_IMAGE_WIDTH); + } catch (MetadataException e) { + logMetadataError(); + return 0; + } + } + + private int getRawHeight() + { + try { + return directory.getInt(WebpDirectory.TAG_IMAGE_HEIGHT); + } catch (MetadataException e) { + logMetadataError(); + return 0; + } + } + + @Override + public int getDepth() + { + String colorSpaceType = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class).getTagName(ExifDirectoryBase.TAG_COLOR_SPACE); + if (!colorSpaceType.isEmpty()) { + return 3; + } else { + return 1; + } + } + + @Override + public int getOrientation() { + try { + return metadata.getFirstDirectoryOfType(ExifIFD0Directory.class).getInt(ExifIFD0Directory.TAG_ORIENTATION); + } catch (Exception ignored) { + // if can't find orientation set as 0 deg + return 1; + } + } + + @Override + public int getWidth() { + int orientation = getOrientation(); + + if (orientation == 8 || orientation == 6) { + return getRawHeight(); + } + + return getRawWidth(); + } + + @Override + public int getHeight() { + int orientation = getOrientation(); + + if (orientation == 8 || orientation == 6) { + return getRawWidth(); + } + + return getRawHeight(); + } + + @Override + public String getMimeType() { + return "image/webp"; + } +} diff --git a/classifai-core/src/main/java/ai/classifai/database/annotation/AnnotationVerticle.java b/classifai-core/src/main/java/ai/classifai/database/annotation/AnnotationVerticle.java index c244cc590..a07fd0954 100644 --- a/classifai-core/src/main/java/ai/classifai/database/annotation/AnnotationVerticle.java +++ b/classifai-core/src/main/java/ai/classifai/database/annotation/AnnotationVerticle.java @@ -44,11 +44,11 @@ import lombok.Getter; import lombok.NonNull; import lombok.extern.slf4j.Slf4j; +import org.opencv.core.Mat; +import org.opencv.imgcodecs.Imgcodecs; -import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.File; -import java.io.IOException; import java.nio.file.Paths; import java.util.HashMap; import java.util.List; @@ -481,7 +481,7 @@ public void queryData(Message message, @NonNull String annotationKey BufferedImage img = WasabiImageHandler.getThumbNail(loader.getWasabiProject(), annotation.getImgPath()); //not checking orientation for on cloud version - imgData = ImageHandler.getThumbNail(img, false, null); +// imgData = ImageHandler.getThumbNail(img); } else { @@ -489,13 +489,13 @@ public void queryData(Message message, @NonNull String annotationKey try { - File fileDataPath = new File(dataPath); + Mat imageMat = Imgcodecs.imread(dataPath); - BufferedImage img = ImageIO.read(fileDataPath); + BufferedImage img = ImageHandler.toBufferedImage(imageMat); - imgData = ImageHandler.getThumbNail(img, true, fileDataPath); + imgData = ImageHandler.getThumbNail(img); } - catch(IOException e) + catch(Exception e) { log.debug("Failure in reading image of path " + dataPath, e); } diff --git a/classifai-core/src/main/java/ai/classifai/util/data/ImageHandler.java b/classifai-core/src/main/java/ai/classifai/util/data/ImageHandler.java index 5396b6346..91b811437 100644 --- a/classifai-core/src/main/java/ai/classifai/util/data/ImageHandler.java +++ b/classifai-core/src/main/java/ai/classifai/util/data/ImageHandler.java @@ -16,27 +16,23 @@ package ai.classifai.util.data; import ai.classifai.data.type.image.ImageData; -import ai.classifai.data.type.image.ImageDataFactory; import ai.classifai.data.type.image.ImageFileType; import ai.classifai.database.annotation.AnnotationVerticle; import ai.classifai.loader.ProjectLoader; import ai.classifai.selector.status.FileSystemStatus; import ai.classifai.util.ParamConfig; -import com.drew.imaging.ImageMetadataReader; -import com.drew.imaging.jpeg.JpegMetadataReader; -import com.drew.metadata.Directory; -import com.drew.metadata.Metadata; -import com.drew.metadata.exif.ExifIFD0Directory; import lombok.NonNull; import lombok.extern.slf4j.Slf4j; +import org.opencv.core.Mat; import javax.imageio.ImageIO; import java.awt.*; -import java.awt.color.ColorSpace; import java.awt.image.BufferedImage; +import java.awt.image.DataBufferByte; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; +import java.io.IOException; import java.util.List; import java.util.*; @@ -48,6 +44,21 @@ @Slf4j public class ImageHandler { + public static BufferedImage toBufferedImage(Mat matrix) + { + int type = BufferedImage.TYPE_BYTE_GRAY; + if (matrix.channels() > 1) { + type = BufferedImage.TYPE_3BYTE_BGR; + } + int bufferSize = matrix.channels() * matrix.cols() * matrix.rows(); + byte[] buffer = new byte[bufferSize]; + matrix.get(0, 0, buffer); // get all the pixels + BufferedImage image = new BufferedImage(matrix.cols(), matrix.rows(), type); + final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData(); + System.arraycopy(buffer, 0, targetPixels, 0, buffer.length); + return image; + } + private static String getImageHeader(String input) { Integer lastIndex = input.length(); @@ -102,106 +113,66 @@ public static boolean isImageReadable(File dataFullPath) return true; } - private static int getExifOrientation(File file) + private static BufferedImage rotateWithOrientation(BufferedImage image) throws IOException { - try - { - Metadata metadata = JpegMetadataReader.readMetadata(file); - Directory dir= metadata.getFirstDirectoryOfType(ExifIFD0Directory.class); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ImageIO.write(image, "png", out); + ImageData imgData = ImageData.getImageData(out.toByteArray()); - return dir.getInt(274); + double angle = 0; + + // the image turn 270 degree + if (imgData.getOrientation() == 8) { + angle = -Math.PI/2; } - catch (Exception e) - { - return 0; + // the image turn 180 degree + else if (imgData.getOrientation() == 3) { + angle = Math.PI; + } + // the image turn 90 degree + else if (imgData.getOrientation() == 6) { + angle = Math.PI/2; } - } - private static BufferedImage rotate(BufferedImage image, double angle) - { double sin = Math.abs(Math.sin(angle)); double cos = Math.abs(Math.cos(angle)); - int w = image.getWidth(); - int h = image.getHeight(); + int w = imgData.getWidth(); + int h = imgData.getHeight(); int newW = (int) Math.floor(w * cos + h * sin); int newH = (int) Math.floor(h * cos + w * sin); - int type = image.getType(); + BufferedImage result = new BufferedImage(newW, newH, type); Graphics2D g = result.createGraphics(); g.translate((newW - w) / 2, (newH - h) / 2); - g.rotate(angle,((double)w) / 2, ((double)h) / 2); + g.rotate(angle,(double) w / 2, (double) h / 2); g.drawRenderedImage(image, null); return result; } - private static BufferedImage rotateWithOrientation(BufferedImage img, int orientation) - { - double angle = 0; - - if (orientation == 8) angle = -Math.PI/2; - else if (orientation == 3) angle = Math.PI; - else if (orientation == 6) angle = Math.PI/2; - - return rotate(img,angle); - } - - private static int getHeight(BufferedImage img, int orientation) - { - if (orientation == 8 || orientation == 6) - { - return img.getWidth(); - } - - return img.getHeight(); - } - - private static int getWidth(BufferedImage img, int orientation) - { - if (orientation == 8 || orientation == 6) - { - return img.getHeight(); - } - return img.getWidth(); - } - - - public static Map getThumbNail(BufferedImage img, boolean toCheckOrientation, File file) - { + public static Map getThumbNail(BufferedImage image) throws IOException { Map imageData = new HashMap<>(); - Integer oriHeight; - Integer oriWidth; + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ImageIO.write(image, "png", out); + ImageData imgData = ImageData.getImageData(out.toByteArray()); - if(toCheckOrientation) - { - int orientation = getExifOrientation(file); + int oriWidth = imgData.getWidth(); - oriHeight = getHeight(img, orientation); - oriWidth = getWidth(img, orientation); - - //rotate for thumbnail generation - img = rotateWithOrientation(img, orientation); - } - else - { - oriHeight = img.getHeight(); - oriWidth = img.getWidth(); - } + int oriHeight = imgData.getHeight(); - int type = img.getColorModel().getColorSpace().getType(); - boolean grayscale = (type == ColorSpace.TYPE_GRAY || type == ColorSpace.CS_GRAY); + int depth = imgData.getDepth(); - Integer depth = grayscale ? 1 : 3; + image = rotateWithOrientation(image); Integer thumbnailWidth = ImageFileType.getFixedThumbnailWidth(); Integer thumbnailHeight = ImageFileType.getFixedThumbnailHeight(); - + if (oriHeight > oriWidth) { thumbnailWidth = thumbnailHeight * oriWidth / oriHeight; @@ -211,15 +182,15 @@ public static Map getThumbNail(BufferedImage img, boolean toChec thumbnailHeight = thumbnailWidth * oriHeight / oriWidth; } - Image tmp = img.getScaledInstance(thumbnailWidth, thumbnailHeight, Image.SCALE_SMOOTH); + Image tmp = image.getScaledInstance(thumbnailWidth, thumbnailHeight, Image.SCALE_SMOOTH); BufferedImage resized = new BufferedImage(thumbnailWidth, thumbnailHeight, BufferedImage.TYPE_INT_ARGB); Graphics2D g2d = resized.createGraphics(); g2d.drawImage(tmp, 0, 0, null); g2d.dispose(); imageData.put(ParamConfig.getImgDepth(), Integer.toString(depth)); - imageData.put(ParamConfig.getImgOriHParam(), Integer.toString(oriHeight)); - imageData.put(ParamConfig.getImgOriWParam(), Integer.toString(oriWidth)); + imageData.put(ParamConfig.getImgOriHParam(), Integer.toString(imgData.getHeight())); + imageData.put(ParamConfig.getImgOriWParam(), Integer.toString(imgData.getWidth())); imageData.put(ParamConfig.getBase64Param(), base64FromBufferedImage(resized)); return imageData; @@ -253,9 +224,7 @@ public static boolean isImageFileValid(File file) { try { - Metadata metadata = ImageMetadataReader.readMetadata(file); - - ImageData imgData = new ImageDataFactory().getImageData(metadata); + ImageData imgData = ImageData.getImageData(file); if (imgData.getWidth() > ImageFileType.getMaxWidth() || imgData.getHeight() > ImageFileType.getMaxHeight()) { diff --git a/pom.xml b/pom.xml index cdb48cb3b..03930a8fd 100644 --- a/pom.xml +++ b/pom.xml @@ -98,6 +98,7 @@ 14 2.0.0-alpha1 dev + 4.5.1-2 @@ -257,6 +258,11 @@ metadata-extractor ${metadata.extractor.version} + + org.openpnp + opencv + ${opencv.version} + From 32067b49424795e25c19c9eb01ba6bbf053bcfbb Mon Sep 17 00:00:00 2001 From: ken479 Date: Thu, 8 Jul 2021 17:42:07 +0800 Subject: [PATCH 2/8] :recycle: Correct sonar cloud issue and commented suggestions --- .../data/type/image/BmpImageData.java | 21 +++++----- .../classifai/data/type/image/ImageData.java | 39 +++++++++++++++++-- .../data/type/image/ImageFileType.java | 2 +- .../data/type/image/JpegImageData.java | 17 +++----- .../data/type/image/PngImageData.java | 15 +++---- .../data/type/image/WebpImageData.java | 21 +++++----- .../annotation/AnnotationVerticle.java | 14 +++++-- .../ai/classifai/util/data/ImageHandler.java | 19 +++------ 8 files changed, 89 insertions(+), 59 deletions(-) diff --git a/classifai-core/src/main/java/ai/classifai/data/type/image/BmpImageData.java b/classifai-core/src/main/java/ai/classifai/data/type/image/BmpImageData.java index 259338d04..cdb6b8015 100644 --- a/classifai-core/src/main/java/ai/classifai/data/type/image/BmpImageData.java +++ b/classifai-core/src/main/java/ai/classifai/data/type/image/BmpImageData.java @@ -26,18 +26,12 @@ */ public class BmpImageData extends ImageData { - private final int S_RGB_COLOR_SPACE = 1934772034; + private final static int SRGB_COLOR_SPACE = 1934772034; protected BmpImageData(Metadata metadata) { super(metadata, BmpHeaderDirectory.class); } - @Override - public int getOrientation() { - // same as original image - return 1; - } - @Override public int getWidth() { @@ -73,13 +67,14 @@ public int getHeight() public int getDepth() { try { int colorSpaceType = directory.getInt(BmpHeaderDirectory.TAG_COLOR_SPACE_TYPE); - if (colorSpaceType == S_RGB_COLOR_SPACE) + if (colorSpaceType == SRGB_COLOR_SPACE) { return 3; } } - catch (MetadataException ignored){} - + catch (Exception e){ + logMetadataError(); + } return 1; } @@ -88,4 +83,10 @@ public String getMimeType() { return "image/bmp"; } + @Override + public boolean isAnimation() { + // Bmp image is always static + return false; + } + } \ No newline at end of file diff --git a/classifai-core/src/main/java/ai/classifai/data/type/image/ImageData.java b/classifai-core/src/main/java/ai/classifai/data/type/image/ImageData.java index fc1fbf318..bb5d21b7f 100644 --- a/classifai-core/src/main/java/ai/classifai/data/type/image/ImageData.java +++ b/classifai-core/src/main/java/ai/classifai/data/type/image/ImageData.java @@ -21,6 +21,7 @@ import com.drew.metadata.Directory; import com.drew.metadata.Metadata; import com.drew.metadata.bmp.BmpHeaderDirectory; +import com.drew.metadata.exif.ExifIFD0Directory; import com.drew.metadata.jpeg.JpegDirectory; import com.drew.metadata.png.PngDirectory; import com.drew.metadata.webp.WebpDirectory; @@ -31,6 +32,7 @@ import java.io.File; import java.io.IOException; +import static com.drew.metadata.exif.ExifIFD0Directory.TAG_ORIENTATION; /** * ImageData provides metadata of images * @@ -48,8 +50,6 @@ protected ImageData(Metadata metadata, Class directoryC this.directory = metadata.getFirstDirectoryOfType(directoryClass); } - public abstract int getOrientation(); - public abstract int getWidth(); public abstract int getHeight(); @@ -58,10 +58,21 @@ protected ImageData(Metadata metadata, Class directoryC public abstract String getMimeType(); + public abstract boolean isAnimation(); + protected void logMetadataError() { log.error("Unhandled metadata error, this should be protected by ImageFactory"); } + public int getOrientation() { + try { + return metadata.getFirstDirectoryOfType(ExifIFD0Directory.class).getInt(TAG_ORIENTATION); + } catch (Exception ignored) { + // if can't find orientation set as 0 deg + return 1; + } + } + public static ImageData getImageData(File filePath) { try @@ -77,7 +88,7 @@ public static ImageData getImageData(File filePath) } catch (NotSupportedImageTypeException e) { - log.debug(String.format("%s is not supported \n %s", filePath, e.getMessage())); + log.debug(String.format("%s is not supported %n %s", filePath, e.getMessage())); return null; } } @@ -121,4 +132,26 @@ public static ImageData getImageData(Metadata metadata) throws NotSupportedImage } } + public double getAngle() { + double angle; + + if (getOrientation() == 8) + { + angle = -0.5*Math.PI; // the image turn 270 degree + } + else if (getOrientation() == 3) + { + angle = Math.PI; // the image turn 180 degree + } + else if (getOrientation() == 6) + { + angle = 0.5*Math.PI; // the image turn 90 degree + } + else + { + angle = 0; + } + + return angle; + } } \ No newline at end of file diff --git a/classifai-core/src/main/java/ai/classifai/data/type/image/ImageFileType.java b/classifai-core/src/main/java/ai/classifai/data/type/image/ImageFileType.java index 2181b7467..8aa02e612 100644 --- a/classifai-core/src/main/java/ai/classifai/data/type/image/ImageFileType.java +++ b/classifai-core/src/main/java/ai/classifai/data/type/image/ImageFileType.java @@ -49,7 +49,7 @@ public class ImageFileType { BASE_64_HEADER.put("png", "data:image/jpeg;base64,"); BASE_64_HEADER.put("PNG", "data:image/png;base64,"); BASE_64_HEADER.put("bmp", "data:image/bmp;base64,"); - BASE_64_HEADER.put("webp", "data:image/bmp;base64,"); + BASE_64_HEADER.put("webp", "data:image/webp;base64,"); } public static String[] getImageFileTypes() diff --git a/classifai-core/src/main/java/ai/classifai/data/type/image/JpegImageData.java b/classifai-core/src/main/java/ai/classifai/data/type/image/JpegImageData.java index eff9310a2..d521baf30 100644 --- a/classifai-core/src/main/java/ai/classifai/data/type/image/JpegImageData.java +++ b/classifai-core/src/main/java/ai/classifai/data/type/image/JpegImageData.java @@ -17,7 +17,6 @@ import com.drew.metadata.Metadata; import com.drew.metadata.MetadataException; -import com.drew.metadata.exif.ExifIFD0Directory; import com.drew.metadata.jpeg.JpegDirectory; /** @@ -66,16 +65,6 @@ private int getRawHeight() { * @return orientation */ - @Override - public int getOrientation() { - try { - return metadata.getFirstDirectoryOfType(ExifIFD0Directory.class).getInt(ExifIFD0Directory.TAG_ORIENTATION); - } catch (Exception ignored) { - // if can't find orientation set as 0 deg - return 1; - } - } - @Override public int getWidth() { int orientation = getOrientation(); @@ -112,4 +101,10 @@ public String getMimeType() { return "image/jpg"; } + @Override + public boolean isAnimation() { + // Jpeg is always static image + return false; + } + } \ No newline at end of file diff --git a/classifai-core/src/main/java/ai/classifai/data/type/image/PngImageData.java b/classifai-core/src/main/java/ai/classifai/data/type/image/PngImageData.java index 0b51ca7ff..0ceb7be63 100644 --- a/classifai-core/src/main/java/ai/classifai/data/type/image/PngImageData.java +++ b/classifai-core/src/main/java/ai/classifai/data/type/image/PngImageData.java @@ -30,12 +30,6 @@ protected PngImageData(Metadata metadata) { super(metadata, PngDirectory.class); } - @Override - public int getOrientation() { - // same as original image - return 1; - } - @Override public int getWidth() { try { @@ -67,7 +61,8 @@ public int getDepth() { int colorType = directory.getInt(PngDirectory.TAG_COLOR_TYPE); if (colorType == 0) return 1; - } catch (Exception ignored) { + } catch (MetadataException e) { + logMetadataError(); } return 3; } @@ -76,4 +71,10 @@ public int getDepth() { public String getMimeType() { return "image/png"; } + + @Override + public boolean isAnimation() { + // Png image is always static + return false; + } } \ No newline at end of file diff --git a/classifai-core/src/main/java/ai/classifai/data/type/image/WebpImageData.java b/classifai-core/src/main/java/ai/classifai/data/type/image/WebpImageData.java index 20d0a9edf..86317d755 100644 --- a/classifai-core/src/main/java/ai/classifai/data/type/image/WebpImageData.java +++ b/classifai-core/src/main/java/ai/classifai/data/type/image/WebpImageData.java @@ -6,6 +6,8 @@ import com.drew.metadata.exif.ExifIFD0Directory; import com.drew.metadata.webp.WebpDirectory; +import static com.drew.metadata.webp.WebpDirectory.TAG_IS_ANIMATION; + public class WebpImageData extends ImageData{ protected WebpImageData(Metadata metadata) @@ -44,16 +46,6 @@ public int getDepth() } } - @Override - public int getOrientation() { - try { - return metadata.getFirstDirectoryOfType(ExifIFD0Directory.class).getInt(ExifIFD0Directory.TAG_ORIENTATION); - } catch (Exception ignored) { - // if can't find orientation set as 0 deg - return 1; - } - } - @Override public int getWidth() { int orientation = getOrientation(); @@ -80,4 +72,13 @@ public int getHeight() { public String getMimeType() { return "image/webp"; } + + @Override + public boolean isAnimation() { + try { + return metadata.getFirstDirectoryOfType(WebpDirectory.class).getBoolean(TAG_IS_ANIMATION); + } catch (Exception e) { + return false; + } + } } diff --git a/classifai-core/src/main/java/ai/classifai/database/annotation/AnnotationVerticle.java b/classifai-core/src/main/java/ai/classifai/database/annotation/AnnotationVerticle.java index a07fd0954..59ca68815 100644 --- a/classifai-core/src/main/java/ai/classifai/database/annotation/AnnotationVerticle.java +++ b/classifai-core/src/main/java/ai/classifai/database/annotation/AnnotationVerticle.java @@ -478,10 +478,18 @@ public void queryData(Message message, @NonNull String annotationKey if(loader.isCloud()) { - BufferedImage img = WasabiImageHandler.getThumbNail(loader.getWasabiProject(), annotation.getImgPath()); + try + { + BufferedImage img = WasabiImageHandler.getThumbNail(loader.getWasabiProject(), annotation.getImgPath()); + + //not checking orientation for on cloud version + imgData = ImageHandler.getThumbNail(img); + } + catch(Exception e) + { + log.debug("Unable to write Buffered Image."); + } - //not checking orientation for on cloud version -// imgData = ImageHandler.getThumbNail(img); } else { diff --git a/classifai-core/src/main/java/ai/classifai/util/data/ImageHandler.java b/classifai-core/src/main/java/ai/classifai/util/data/ImageHandler.java index 91b811437..dcbb2cc89 100644 --- a/classifai-core/src/main/java/ai/classifai/util/data/ImageHandler.java +++ b/classifai-core/src/main/java/ai/classifai/util/data/ImageHandler.java @@ -119,20 +119,7 @@ private static BufferedImage rotateWithOrientation(BufferedImage image) throws I ImageIO.write(image, "png", out); ImageData imgData = ImageData.getImageData(out.toByteArray()); - double angle = 0; - - // the image turn 270 degree - if (imgData.getOrientation() == 8) { - angle = -Math.PI/2; - } - // the image turn 180 degree - else if (imgData.getOrientation() == 3) { - angle = Math.PI; - } - // the image turn 90 degree - else if (imgData.getOrientation() == 6) { - angle = Math.PI/2; - } + double angle = imgData.getAngle(); double sin = Math.abs(Math.sin(angle)); double cos = Math.abs(Math.cos(angle)); @@ -231,6 +218,10 @@ public static boolean isImageFileValid(File file) log.info("Image size bigger than maximum allowed input size. Skipped " + file); return false; } + else if (imgData.isAnimation()) { + log.info("The image is animated and not supported "); + return false; + } } catch (Exception e) { From 529a02a8314931c9805821716c338dafc9a3682f Mon Sep 17 00:00:00 2001 From: ken479 Date: Thu, 8 Jul 2021 18:04:37 +0800 Subject: [PATCH 3/8] :recycle: Refactor code --- .../data/type/image/BmpImageData.java | 11 ++---- .../classifai/data/type/image/ImageData.java | 32 +++++++++++++---- .../data/type/image/JpegImageData.java | 35 +++---------------- .../data/type/image/PngImageData.java | 10 ++---- .../data/type/image/WebpImageData.java | 13 +++---- 5 files changed, 42 insertions(+), 59 deletions(-) diff --git a/classifai-core/src/main/java/ai/classifai/data/type/image/BmpImageData.java b/classifai-core/src/main/java/ai/classifai/data/type/image/BmpImageData.java index cdb6b8015..8aa0abf67 100644 --- a/classifai-core/src/main/java/ai/classifai/data/type/image/BmpImageData.java +++ b/classifai-core/src/main/java/ai/classifai/data/type/image/BmpImageData.java @@ -29,11 +29,11 @@ public class BmpImageData extends ImageData private final static int SRGB_COLOR_SPACE = 1934772034; protected BmpImageData(Metadata metadata) { - super(metadata, BmpHeaderDirectory.class); + super(metadata, BmpHeaderDirectory.class, "image/bmp"); } @Override - public int getWidth() + protected int getRawWidth() { try { @@ -47,7 +47,7 @@ public int getWidth() } @Override - public int getHeight() + protected int getRawHeight() { try { return directory.getInt(BmpHeaderDirectory.TAG_IMAGE_HEIGHT); @@ -78,11 +78,6 @@ public int getDepth() { return 1; } - @Override - public String getMimeType() { - return "image/bmp"; - } - @Override public boolean isAnimation() { // Bmp image is always static diff --git a/classifai-core/src/main/java/ai/classifai/data/type/image/ImageData.java b/classifai-core/src/main/java/ai/classifai/data/type/image/ImageData.java index bb5d21b7f..195414dae 100644 --- a/classifai-core/src/main/java/ai/classifai/data/type/image/ImageData.java +++ b/classifai-core/src/main/java/ai/classifai/data/type/image/ImageData.java @@ -41,29 +41,49 @@ @Slf4j public abstract class ImageData { - @Getter + protected Metadata metadata; protected Directory directory; + @Getter protected String mimeType; - protected ImageData(Metadata metadata, Class directoryClass) { + protected ImageData(Metadata metadata, Class directoryClass, String mimeType) { this.metadata = metadata; this.directory = metadata.getFirstDirectoryOfType(directoryClass); + this.mimeType = mimeType; } - public abstract int getWidth(); + protected abstract int getRawWidth(); - public abstract int getHeight(); + protected abstract int getRawHeight(); public abstract int getDepth(); - public abstract String getMimeType(); - public abstract boolean isAnimation(); protected void logMetadataError() { log.error("Unhandled metadata error, this should be protected by ImageFactory"); } + public int getWidth() { + int orientation = getOrientation(); + + if (orientation == 8 || orientation == 6) { + return getRawHeight(); + } + + return getRawWidth(); + } + + public int getHeight() { + int orientation = getOrientation(); + + if (orientation == 8 || orientation == 6) { + return getRawWidth(); + } + + return getRawHeight(); + } + public int getOrientation() { try { return metadata.getFirstDirectoryOfType(ExifIFD0Directory.class).getInt(TAG_ORIENTATION); diff --git a/classifai-core/src/main/java/ai/classifai/data/type/image/JpegImageData.java b/classifai-core/src/main/java/ai/classifai/data/type/image/JpegImageData.java index d521baf30..830c65d7a 100644 --- a/classifai-core/src/main/java/ai/classifai/data/type/image/JpegImageData.java +++ b/classifai-core/src/main/java/ai/classifai/data/type/image/JpegImageData.java @@ -27,10 +27,11 @@ public class JpegImageData extends ImageData { protected JpegImageData(Metadata metadata) { - super(metadata, JpegDirectory.class); + super(metadata, JpegDirectory.class, "image/jpg"); } - private int getRawWidth() { + @Override + protected int getRawWidth() { try { return metadata.getFirstDirectoryOfType(JpegDirectory.class).getInt(JpegDirectory.TAG_IMAGE_WIDTH); } catch (MetadataException e) { @@ -39,7 +40,8 @@ private int getRawWidth() { } } - private int getRawHeight() { + @Override + protected int getRawHeight() { try { return metadata.getFirstDirectoryOfType(JpegDirectory.class).getInt(JpegDirectory.TAG_IMAGE_HEIGHT); } catch (MetadataException e) { @@ -65,28 +67,6 @@ private int getRawHeight() { * @return orientation */ - @Override - public int getWidth() { - int orientation = getOrientation(); - - if (orientation == 8 || orientation == 6) { - return getRawHeight(); - } - - return getRawWidth(); - } - - @Override - public int getHeight() { - int orientation = getOrientation(); - - if (orientation == 8 || orientation == 6) { - return getRawWidth(); - } - - return getRawHeight(); - } - @Override public int getDepth() { try { @@ -96,11 +76,6 @@ public int getDepth() { } } - @Override - public String getMimeType() { - return "image/jpg"; - } - @Override public boolean isAnimation() { // Jpeg is always static image diff --git a/classifai-core/src/main/java/ai/classifai/data/type/image/PngImageData.java b/classifai-core/src/main/java/ai/classifai/data/type/image/PngImageData.java index 0ceb7be63..31a9bc358 100644 --- a/classifai-core/src/main/java/ai/classifai/data/type/image/PngImageData.java +++ b/classifai-core/src/main/java/ai/classifai/data/type/image/PngImageData.java @@ -27,11 +27,11 @@ public class PngImageData extends ImageData { protected PngImageData(Metadata metadata) { - super(metadata, PngDirectory.class); + super(metadata, PngDirectory.class,"image/png" ); } @Override - public int getWidth() { + protected int getRawWidth() { try { return directory.getInt(PngDirectory.TAG_IMAGE_WIDTH); } catch (MetadataException e) { @@ -41,7 +41,7 @@ public int getWidth() { } @Override - public int getHeight() { + protected int getRawHeight() { try { return directory.getInt(PngDirectory.TAG_IMAGE_HEIGHT); } catch (MetadataException e) { @@ -67,10 +67,6 @@ public int getDepth() { return 3; } - @Override - public String getMimeType() { - return "image/png"; - } @Override public boolean isAnimation() { diff --git a/classifai-core/src/main/java/ai/classifai/data/type/image/WebpImageData.java b/classifai-core/src/main/java/ai/classifai/data/type/image/WebpImageData.java index 86317d755..bfc232e45 100644 --- a/classifai-core/src/main/java/ai/classifai/data/type/image/WebpImageData.java +++ b/classifai-core/src/main/java/ai/classifai/data/type/image/WebpImageData.java @@ -12,10 +12,11 @@ public class WebpImageData extends ImageData{ protected WebpImageData(Metadata metadata) { - super(metadata, WebpDirectory.class); + super(metadata, WebpDirectory.class, "image/webp"); } - private int getRawWidth() + @Override + protected int getRawWidth() { try { return directory.getInt(WebpDirectory.TAG_IMAGE_WIDTH); @@ -25,7 +26,8 @@ private int getRawWidth() } } - private int getRawHeight() + @Override + protected int getRawHeight() { try { return directory.getInt(WebpDirectory.TAG_IMAGE_HEIGHT); @@ -68,11 +70,6 @@ public int getHeight() { return getRawHeight(); } - @Override - public String getMimeType() { - return "image/webp"; - } - @Override public boolean isAnimation() { try { From daa6216b2ab91b1f8529e3004d16114bbe0ae2a4 Mon Sep 17 00:00:00 2001 From: ken479 Date: Thu, 8 Jul 2021 18:09:01 +0800 Subject: [PATCH 4/8] :pencil2: Resolve typo --- .../main/java/ai/classifai/data/type/image/BmpImageData.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classifai-core/src/main/java/ai/classifai/data/type/image/BmpImageData.java b/classifai-core/src/main/java/ai/classifai/data/type/image/BmpImageData.java index 8aa0abf67..375b401a3 100644 --- a/classifai-core/src/main/java/ai/classifai/data/type/image/BmpImageData.java +++ b/classifai-core/src/main/java/ai/classifai/data/type/image/BmpImageData.java @@ -26,7 +26,7 @@ */ public class BmpImageData extends ImageData { - private final static int SRGB_COLOR_SPACE = 1934772034; + private static final int SRGB_COLOR_SPACE = 1934772034; protected BmpImageData(Metadata metadata) { super(metadata, BmpHeaderDirectory.class, "image/bmp"); From 851dfe1acfbd9ccd73567e659b4f55ce2149267f Mon Sep 17 00:00:00 2001 From: ken479 Date: Fri, 9 Jul 2021 04:07:19 +0800 Subject: [PATCH 5/8] :recycle: Refactor code --- .../data/type/image/BmpImageData.java | 2 +- .../data/type/image/JpegImageData.java | 5 ++- .../data/type/image/WebpImageData.java | 38 ++++--------------- 3 files changed, 12 insertions(+), 33 deletions(-) diff --git a/classifai-core/src/main/java/ai/classifai/data/type/image/BmpImageData.java b/classifai-core/src/main/java/ai/classifai/data/type/image/BmpImageData.java index 375b401a3..320a0b346 100644 --- a/classifai-core/src/main/java/ai/classifai/data/type/image/BmpImageData.java +++ b/classifai-core/src/main/java/ai/classifai/data/type/image/BmpImageData.java @@ -72,7 +72,7 @@ public int getDepth() { return 3; } } - catch (Exception e){ + catch (MetadataException e){ logMetadataError(); } return 1; diff --git a/classifai-core/src/main/java/ai/classifai/data/type/image/JpegImageData.java b/classifai-core/src/main/java/ai/classifai/data/type/image/JpegImageData.java index 830c65d7a..620cde64e 100644 --- a/classifai-core/src/main/java/ai/classifai/data/type/image/JpegImageData.java +++ b/classifai-core/src/main/java/ai/classifai/data/type/image/JpegImageData.java @@ -71,9 +71,10 @@ protected int getRawHeight() { public int getDepth() { try { return directory.getInt(JpegDirectory.TAG_NUMBER_OF_COMPONENTS); - } catch (Exception ignored) { - return 3; + } catch (MetadataException e) { + logMetadataError(); } + return 3; } @Override diff --git a/classifai-core/src/main/java/ai/classifai/data/type/image/WebpImageData.java b/classifai-core/src/main/java/ai/classifai/data/type/image/WebpImageData.java index bfc232e45..af61d17ce 100644 --- a/classifai-core/src/main/java/ai/classifai/data/type/image/WebpImageData.java +++ b/classifai-core/src/main/java/ai/classifai/data/type/image/WebpImageData.java @@ -2,8 +2,7 @@ import com.drew.metadata.Metadata; import com.drew.metadata.MetadataException; -import com.drew.metadata.exif.ExifDirectoryBase; -import com.drew.metadata.exif.ExifIFD0Directory; +import com.drew.metadata.exif.ExifSubIFDDirectory; import com.drew.metadata.webp.WebpDirectory; import static com.drew.metadata.webp.WebpDirectory.TAG_IS_ANIMATION; @@ -40,41 +39,20 @@ protected int getRawHeight() @Override public int getDepth() { - String colorSpaceType = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class).getTagName(ExifDirectoryBase.TAG_COLOR_SPACE); - if (!colorSpaceType.isEmpty()) { - return 3; - } else { - return 1; - } - } - - @Override - public int getWidth() { - int orientation = getOrientation(); - - if (orientation == 8 || orientation == 6) { - return getRawHeight(); - } - - return getRawWidth(); - } - - @Override - public int getHeight() { - int orientation = getOrientation(); - - if (orientation == 8 || orientation == 6) { - return getRawWidth(); + try { + int colorSpace = metadata.getFirstDirectoryOfType(ExifSubIFDDirectory.class).getInt(ExifSubIFDDirectory.TAG_COLOR_SPACE); + if (colorSpace == 0) return 1; + } catch (MetadataException e) { + logMetadataError(); } - - return getRawHeight(); + return 3; } @Override public boolean isAnimation() { try { return metadata.getFirstDirectoryOfType(WebpDirectory.class).getBoolean(TAG_IS_ANIMATION); - } catch (Exception e) { + } catch (MetadataException e) { return false; } } From bae001d2e4981bbca9069f52da5f820b0783f2e6 Mon Sep 17 00:00:00 2001 From: ken479 Date: Fri, 9 Jul 2021 04:15:52 +0800 Subject: [PATCH 6/8] :recycle: Fix static access --- .../main/java/ai/classifai/data/type/image/WebpImageData.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/classifai-core/src/main/java/ai/classifai/data/type/image/WebpImageData.java b/classifai-core/src/main/java/ai/classifai/data/type/image/WebpImageData.java index af61d17ce..3975dd39a 100644 --- a/classifai-core/src/main/java/ai/classifai/data/type/image/WebpImageData.java +++ b/classifai-core/src/main/java/ai/classifai/data/type/image/WebpImageData.java @@ -6,6 +6,7 @@ import com.drew.metadata.webp.WebpDirectory; import static com.drew.metadata.webp.WebpDirectory.TAG_IS_ANIMATION; +import static com.drew.metadata.exif.ExifDirectoryBase.TAG_COLOR_SPACE; public class WebpImageData extends ImageData{ @@ -40,7 +41,7 @@ protected int getRawHeight() public int getDepth() { try { - int colorSpace = metadata.getFirstDirectoryOfType(ExifSubIFDDirectory.class).getInt(ExifSubIFDDirectory.TAG_COLOR_SPACE); + int colorSpace = metadata.getFirstDirectoryOfType(ExifSubIFDDirectory.class).getInt(TAG_COLOR_SPACE); if (colorSpace == 0) return 1; } catch (MetadataException e) { logMetadataError(); From 7ee0eb3ec97dc4dbaf2d27b37fe33ccb2690524c Mon Sep 17 00:00:00 2001 From: ken479 Date: Fri, 9 Jul 2021 08:54:46 +0800 Subject: [PATCH 7/8] :page_facing_up: Add license and description --- .../data/type/image/WebpImageData.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/classifai-core/src/main/java/ai/classifai/data/type/image/WebpImageData.java b/classifai-core/src/main/java/ai/classifai/data/type/image/WebpImageData.java index 3975dd39a..1936a3dfe 100644 --- a/classifai-core/src/main/java/ai/classifai/data/type/image/WebpImageData.java +++ b/classifai-core/src/main/java/ai/classifai/data/type/image/WebpImageData.java @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2021 CertifAI Sdn. Bhd. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + package ai.classifai.data.type.image; import com.drew.metadata.Metadata; @@ -8,6 +24,12 @@ import static com.drew.metadata.webp.WebpDirectory.TAG_IS_ANIMATION; import static com.drew.metadata.exif.ExifDirectoryBase.TAG_COLOR_SPACE; +/** + * Provides metadata of webp images + * + * @author YCCertifai + */ + public class WebpImageData extends ImageData{ protected WebpImageData(Metadata metadata) From 7fb174324a6bb65e9c31f01b0a02d89e5c1b602b Mon Sep 17 00:00:00 2001 From: ken479 Date: Fri, 9 Jul 2021 09:18:36 +0800 Subject: [PATCH 8/8] :pencil2: Update author name --- .../main/java/ai/classifai/data/type/image/WebpImageData.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classifai-core/src/main/java/ai/classifai/data/type/image/WebpImageData.java b/classifai-core/src/main/java/ai/classifai/data/type/image/WebpImageData.java index 1936a3dfe..797d1d8f2 100644 --- a/classifai-core/src/main/java/ai/classifai/data/type/image/WebpImageData.java +++ b/classifai-core/src/main/java/ai/classifai/data/type/image/WebpImageData.java @@ -27,7 +27,7 @@ /** * Provides metadata of webp images * - * @author YCCertifai + * @author ken479 */ public class WebpImageData extends ImageData{