Skip to content

Commit

Permalink
🐛 Merge pull request #464 from CertifaiAI/ken_ImageHandling
Browse files Browse the repository at this point in the history
🐛 Change of library to opencv to support for webp image
  • Loading branch information
codenamewei authored Jul 9, 2021
2 parents 856e96f + 7fb1743 commit 722634e
Show file tree
Hide file tree
Showing 12 changed files with 442 additions and 173 deletions.
3 changes: 3 additions & 0 deletions classifai-api/src/main/java/ai/classifai/ClassifaiApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 4 additions & 0 deletions classifai-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@
<groupId>com.drewnoakes</groupId>
<artifactId>metadata-extractor</artifactId>
</dependency>
<dependency>
<groupId>org.openpnp</groupId>
<artifactId>opencv</artifactId>
</dependency>
</dependencies>


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,62 @@
*/
public class BmpImageData extends ImageData
{
public BmpImageData(Metadata metadata)
{
super(metadata);
private static final int SRGB_COLOR_SPACE = 1934772034;

protected BmpImageData(Metadata metadata) {
super(metadata, BmpHeaderDirectory.class, "image/bmp");
}

@Override
public int getWidth() throws MetadataException
protected int getRawWidth()
{
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
protected int getRawHeight()
{
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 == SRGB_COLOR_SPACE)
{
return 3;
}
}
catch (MetadataException e){
logMetadataError();
}
return 1;
}

@Override
public boolean isAnimation() {
// Bmp image is always static
return false;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,163 @@
*/
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.exif.ExifIFD0Directory;
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;

import static com.drew.metadata.exif.ExifIFD0Directory.TAG_ORIENTATION;
/**
* ImageData provides metadata of images
*
* @author YCCertifai
*/
@Slf4j
public abstract class ImageData
{

protected Metadata metadata;
protected Directory directory;
@Getter protected String mimeType;

protected ImageData(Metadata metadata)
{
protected <T extends Directory> ImageData(Metadata metadata, Class<T> directoryClass, String mimeType) {
this.metadata = metadata;
this.directory = metadata.getFirstDirectoryOfType(directoryClass);
this.mimeType = mimeType;
}

protected abstract int getRawWidth();

protected abstract int getRawHeight();

public abstract int getDepth();

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 abstract int getWidth() throws MetadataException;
public abstract int getHeight() throws MetadataException;
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
{
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 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;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -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/webp;base64,");
}

public static String[] getImageFileTypes()
Expand Down
Loading

0 comments on commit 722634e

Please sign in to comment.