mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-07 01:54:22 +00:00
Added added service for image formats not supported by ImageIO (jp2)
This commit is contained in:
@@ -8,18 +8,30 @@
|
||||
package org.dspace.app.canvasdimension;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.commons.cli.*;
|
||||
import org.dspace.app.canvasdimension.factory.IIIFCanvasDimensionServiceFactory;
|
||||
import org.dspace.app.canvasdimension.service.IIIFCanvasDimensionService;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.eperson.factory.EPersonServiceFactory;
|
||||
import org.dspace.eperson.service.EPersonService;
|
||||
import org.dspace.handle.factory.HandleServiceFactory;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||
|
||||
public class CanvasDimensionCLI {
|
||||
|
||||
private static final EPersonService epersonService = EPersonServiceFactory.getInstance().getEPersonService();
|
||||
private static final ConfigurationService configurationService = DSpaceServicesFactory.getInstance()
|
||||
.getConfigurationService();
|
||||
|
||||
private CanvasDimensionCLI() {}
|
||||
|
||||
public static void main(String[] argv) throws Exception {
|
||||
@@ -27,16 +39,26 @@ public class CanvasDimensionCLI {
|
||||
boolean force = false;
|
||||
boolean isQuiet = false;
|
||||
String identifier = null;
|
||||
String eperson = null;
|
||||
int max2Process = Integer.MAX_VALUE;
|
||||
boolean iiifEnabled = configurationService.getBooleanProperty("iiif.enabled");
|
||||
|
||||
if (!iiifEnabled) {
|
||||
System.out.println("IIIF is not enabled on this DSpace server.");
|
||||
return;
|
||||
}
|
||||
|
||||
Context context = new Context();
|
||||
IIIFCanvasDimensionProcessor canvasProcessor = new IIIFCanvasDimensionProcessor();
|
||||
IIIFCanvasDimensionService canvasProcessor = IIIFCanvasDimensionServiceFactory.getInstance()
|
||||
.getIiifCanvasDimensionService();
|
||||
|
||||
CommandLineParser parser = new DefaultParser();
|
||||
|
||||
Options options = new Options();
|
||||
options.addOption("i", "identifier", true,
|
||||
"process IIIF canvas dimensions for images belonging to identifier");
|
||||
options.addOption("e", "eperson", true,
|
||||
"email of eperson setting canvas dimensions");
|
||||
options.addOption("f", "force", false,
|
||||
"force update of all IIIF canvas height and width dimensions");
|
||||
options.addOption("q", "quiet", false,
|
||||
@@ -74,6 +96,9 @@ public class CanvasDimensionCLI {
|
||||
if (line.hasOption('q')) {
|
||||
isQuiet = true;
|
||||
}
|
||||
if (line.hasOption('e')) {
|
||||
eperson = line.getOptionValue('e');
|
||||
}
|
||||
if (line.hasOption('i')) {
|
||||
identifier = line.getOptionValue('i');
|
||||
} else {
|
||||
@@ -111,6 +136,21 @@ public class CanvasDimensionCLI {
|
||||
+ identifier + " to a DSpace object");
|
||||
}
|
||||
|
||||
EPerson user;
|
||||
|
||||
if (eperson.indexOf('@') != -1) {
|
||||
// @ sign, must be an email
|
||||
user = epersonService.findByEmail(context, eperson);
|
||||
} else {
|
||||
user = epersonService.find(context, UUID.fromString(eperson));
|
||||
}
|
||||
|
||||
if (user == null) {
|
||||
System.out.println("Error, eperson cannot be found: " + eperson);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
context.setCurrentUser(user);
|
||||
|
||||
canvasProcessor.setForceProcessing(force);
|
||||
canvasProcessor.setMax2Process(max2Process);
|
||||
|
@@ -0,0 +1,65 @@
|
||||
package org.dspace.app.canvasdimension;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.dspace.app.canvasdimension.service.IIIFApiQueryService;
|
||||
import org.dspace.content.Bitstream;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
public class IIIFApiQueryServiceImpl implements IIIFApiQueryService, InitializingBean {
|
||||
|
||||
@Autowired(required = true)
|
||||
protected ConfigurationService configurationService;
|
||||
|
||||
String iiifImageServer;
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
iiifImageServer = configurationService.getProperty("iiif.image.server");
|
||||
}
|
||||
|
||||
public int[] getImageDimensions(Bitstream bitstream) {
|
||||
return getIiifImageDimensions(bitstream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves image dimensions from the image server (IIIF Image API v.2.1.1).
|
||||
* @param bitstream the bitstream DSO
|
||||
* @return image dimensions
|
||||
*/
|
||||
private int[] getIiifImageDimensions(Bitstream bitstream) {
|
||||
int[] arr = new int[2];
|
||||
String path = iiifImageServer + bitstream.getID() + "/info.json";
|
||||
URL url;
|
||||
try {
|
||||
url = new URL(path);
|
||||
HttpURLConnection con = (HttpURLConnection) url.openConnection();
|
||||
con.setRequestMethod("GET");
|
||||
BufferedReader in = new BufferedReader(
|
||||
new InputStreamReader(con.getInputStream()));
|
||||
String inputLine;
|
||||
StringBuilder response = new StringBuilder();
|
||||
while ((inputLine = in.readLine()) != null) {
|
||||
response.append(inputLine);
|
||||
}
|
||||
in.close();
|
||||
JsonNode parent = new ObjectMapper().readTree(response.toString());
|
||||
arr[0] = parent.get("width").asInt();
|
||||
arr[1] = parent.get("height").asInt();
|
||||
return arr;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -16,11 +16,14 @@ import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.dspace.app.canvasdimension.service.IIIFApiQueryService;
|
||||
import org.dspace.app.canvasdimension.service.IIIFCanvasDimensionService;
|
||||
import org.dspace.content.Bitstream;
|
||||
import org.dspace.content.Bundle;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.content.MetadataValue;
|
||||
import org.dspace.content.service.BitstreamService;
|
||||
import org.dspace.content.service.CommunityService;
|
||||
import org.dspace.content.service.DSpaceObjectService;
|
||||
@@ -28,19 +31,20 @@ import org.dspace.content.service.ItemService;
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.license.CreativeCommonsServiceImpl;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
public class IIIFCanvasDimensionProcessor implements InitializingBean {
|
||||
public class IIIFCanvasDimensionServiceImpl implements IIIFCanvasDimensionService {
|
||||
|
||||
@Autowired
|
||||
@Autowired(required = true)
|
||||
ItemService itemService;
|
||||
@Autowired
|
||||
@Autowired(required = true)
|
||||
CommunityService communityService;
|
||||
@Autowired
|
||||
@Autowired(required = true)
|
||||
BitstreamService bitstreamService;
|
||||
@Autowired
|
||||
@Autowired(required = true)
|
||||
DSpaceObjectService<Bitstream> dSpaceObjectService;
|
||||
@Autowired(required = true)
|
||||
IIIFApiQueryService iiifApiQuery;
|
||||
|
||||
// metadata used to enable the iiif features on the item
|
||||
public static final String METADATA_IIIF_ENABLED = "dspace.iiif.enabled";
|
||||
@@ -55,20 +59,17 @@ public class IIIFCanvasDimensionProcessor implements InitializingBean {
|
||||
private int processed = 0;
|
||||
protected Item currentItem = null; // TODO needed?
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the force processing property. If true, existing canvas
|
||||
* metadata will be replaced.
|
||||
* @param force
|
||||
*/
|
||||
@Override
|
||||
public void setForceProcessing(boolean force) {
|
||||
forceProcessing = force;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIsQuiet(boolean quiet) {
|
||||
isQuiet = quiet;
|
||||
}
|
||||
@@ -77,6 +78,7 @@ public class IIIFCanvasDimensionProcessor implements InitializingBean {
|
||||
* Set the maximum number of items to process.
|
||||
* @param max2Process
|
||||
*/
|
||||
@Override
|
||||
public void setMax2Process(int max2Process) {
|
||||
this.max2Process = max2Process;
|
||||
}
|
||||
@@ -85,6 +87,7 @@ public class IIIFCanvasDimensionProcessor implements InitializingBean {
|
||||
* Set dso identifiers to skip.
|
||||
* @param skipList
|
||||
*/
|
||||
@Override
|
||||
public void setSkipList(List<String> skipList) {
|
||||
this.skipList = skipList;
|
||||
}
|
||||
@@ -94,6 +97,7 @@ public class IIIFCanvasDimensionProcessor implements InitializingBean {
|
||||
* @param context
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
public void processSite(Context context) throws Exception {
|
||||
if (skipList != null) {
|
||||
//if a skip-list exists, we need to filter community-by-community
|
||||
@@ -119,6 +123,7 @@ public class IIIFCanvasDimensionProcessor implements InitializingBean {
|
||||
* @param community
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
public void processCommunity(Context context, Community community) throws Exception {
|
||||
if (!inSkipList(community.getHandle())) {
|
||||
List<Community> subcommunities = community.getSubcommunities();
|
||||
@@ -138,6 +143,7 @@ public class IIIFCanvasDimensionProcessor implements InitializingBean {
|
||||
* @param collection
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
public void processCollection(Context context, Collection collection) throws Exception {
|
||||
if (!inSkipList(collection.getHandle())) {
|
||||
Iterator<Item> itemIterator = itemService.findAllByCollection(context, collection);
|
||||
@@ -153,6 +159,7 @@ public class IIIFCanvasDimensionProcessor implements InitializingBean {
|
||||
* @param item
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
public void processItem(Context context, Item item) throws Exception {
|
||||
if (!inSkipList(item.getHandle())) {
|
||||
boolean isIIIFItem = item.getMetadata().stream().filter(m -> m.getMetadataField().toString('.')
|
||||
@@ -160,8 +167,10 @@ public class IIIFCanvasDimensionProcessor implements InitializingBean {
|
||||
.anyMatch(m -> m.getValue().equalsIgnoreCase("true") ||
|
||||
m.getValue().equalsIgnoreCase("yes"));
|
||||
if (isIIIFItem) {
|
||||
if (processBundles(context, item)) {
|
||||
if (processItemBundles(context, item)) {
|
||||
++processed;
|
||||
// commit changes
|
||||
context.commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -174,15 +183,16 @@ public class IIIFCanvasDimensionProcessor implements InitializingBean {
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
private boolean processBundles(Context context, Item item) throws Exception {
|
||||
private boolean processItemBundles(Context context, Item item) throws Exception {
|
||||
List<Bundle> bundles = getIIIFBundles(item);
|
||||
boolean done = false;
|
||||
for (Bundle bundle : bundles) {
|
||||
List<Bitstream> myBitstreams = bundle.getBitstreams();
|
||||
for (Bitstream myBitstream : myBitstreams) {
|
||||
done |= processBitstream(context, myBitstream);
|
||||
List<Bitstream> bitstreams = bundle.getBitstreams();
|
||||
for (Bitstream bit : bitstreams) {
|
||||
done |= processBitstream(context, bit);
|
||||
}
|
||||
}
|
||||
itemService.update(context, item);
|
||||
return done;
|
||||
|
||||
}
|
||||
@@ -197,15 +207,23 @@ public class IIIFCanvasDimensionProcessor implements InitializingBean {
|
||||
*/
|
||||
private boolean processBitstream(Context context, Bitstream bitstream) throws Exception {
|
||||
boolean processed = false;
|
||||
boolean isUnsupported = bitstream.getFormat(context).getMIMEType().contains("image/jp2");
|
||||
boolean isImage = bitstream.getFormat(context).getMIMEType().contains("image/");
|
||||
if (isImage) {
|
||||
Optional op = bitstream.getMetadata().stream().filter(m -> m.getMetadataField().toString('.')
|
||||
.contentEquals(IIIF_WIDTH_METADATA)).findFirst();
|
||||
Optional<MetadataValue> op = bitstream.getMetadata().stream()
|
||||
.filter(m -> m.getMetadataField().toString('.')
|
||||
.contentEquals(IIIF_WIDTH_METADATA)).findFirst();
|
||||
if (op.isEmpty() || forceProcessing) {
|
||||
InputStream srcStream = bitstreamService.retrieve(context, bitstream);
|
||||
int[] dims = ImageDimensionReader.getImageDimensions(srcStream);
|
||||
int[] dims;
|
||||
if (isUnsupported) {
|
||||
dims = iiifApiQuery.getImageDimensions(bitstream);
|
||||
} else {
|
||||
InputStream stream = bitstreamService.retrieve(context, bitstream);
|
||||
dims = ImageDimensionReader.getImageDimensions(stream);
|
||||
}
|
||||
if (dims != null) {
|
||||
processed = setBitstreamMetadata(context, bitstream, dims);
|
||||
bitstreamService.update(context, bitstream);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -216,14 +234,12 @@ public class IIIFCanvasDimensionProcessor implements InitializingBean {
|
||||
try {
|
||||
dSpaceObjectService.clearMetadata(context, bitstream, "iiif",
|
||||
"image", "width", Item.ANY);
|
||||
dSpaceObjectService.addAndShiftRightMetadata(context, bitstream, "iiif",
|
||||
"image", "width", null,
|
||||
String.valueOf(dims[0]), null, -1, -1);
|
||||
dSpaceObjectService.setMetadataSingleValue(context, bitstream, "iiif",
|
||||
"image", "width", Item.ANY, String.valueOf(dims[0]));
|
||||
dSpaceObjectService.clearMetadata(context, bitstream, "iiif",
|
||||
"image", "height", Item.ANY);
|
||||
dSpaceObjectService.addAndShiftRightMetadata(context, bitstream, "iiif",
|
||||
"image", "height", null,
|
||||
String.valueOf(dims[1]), null, -1, -1);
|
||||
dSpaceObjectService.setMetadataSingleValue(context, bitstream, "iiif",
|
||||
"image", "height", Item.ANY, String.valueOf(dims[1]));
|
||||
return true;
|
||||
} catch (SQLException e) {
|
||||
System.out.println("Unable to update metadata: " + e.getMessage());
|
@@ -18,8 +18,8 @@ public class ImageDimensionReader {
|
||||
public static int[] getImageDimensions(InputStream image) throws Exception {
|
||||
int[] dims = new int[2];
|
||||
BufferedImage buf = ImageIO.read(image);
|
||||
int width = buf.getWidth();
|
||||
int height = buf.getHeight();
|
||||
int width = buf.getWidth(null);
|
||||
int height = buf.getHeight(null);
|
||||
if (width > 0 && height > 0) {
|
||||
dims[0] = width;
|
||||
dims[1] = height;
|
||||
|
@@ -0,0 +1,15 @@
|
||||
package org.dspace.app.canvasdimension.factory;
|
||||
|
||||
import org.dspace.app.canvasdimension.service.IIIFCanvasDimensionService;
|
||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||
|
||||
public abstract class IIIFCanvasDimensionServiceFactory {
|
||||
|
||||
public static IIIFCanvasDimensionServiceFactory getInstance() {
|
||||
return DSpaceServicesFactory.getInstance().getServiceManager()
|
||||
.getServiceByName("iiifCanvasDimensionServiceFactory",
|
||||
IIIFCanvasDimensionServiceFactory.class);
|
||||
}
|
||||
|
||||
public abstract IIIFCanvasDimensionService getIiifCanvasDimensionService();
|
||||
}
|
@@ -0,0 +1,15 @@
|
||||
package org.dspace.app.canvasdimension.factory;
|
||||
|
||||
import org.dspace.app.canvasdimension.service.IIIFCanvasDimensionService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
public class IIIFCanvasDimensionServiceFactoryImpl extends IIIFCanvasDimensionServiceFactory {
|
||||
|
||||
@Autowired(required = true)
|
||||
private IIIFCanvasDimensionService iiifCanvasDimensionService;
|
||||
|
||||
@Override
|
||||
public IIIFCanvasDimensionService getIiifCanvasDimensionService() {
|
||||
return iiifCanvasDimensionService;
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
package org.dspace.app.canvasdimension.service;
|
||||
|
||||
import org.dspace.content.Bitstream;
|
||||
|
||||
public interface IIIFApiQueryService {
|
||||
|
||||
public int[] getImageDimensions(Bitstream bitstream);
|
||||
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
package org.dspace.app.canvasdimension.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.core.Context;
|
||||
|
||||
public interface IIIFCanvasDimensionService {
|
||||
|
||||
public void processSite(Context context) throws Exception;
|
||||
|
||||
public void processCommunity(Context context, Community community) throws Exception;
|
||||
|
||||
public void processCollection(Context context, Collection collection) throws Exception;
|
||||
|
||||
public void processItem(Context context, Item item) throws Exception;
|
||||
|
||||
public void setForceProcessing(boolean force);
|
||||
|
||||
public void setIsQuiet(boolean quiet);
|
||||
|
||||
public void setMax2Process(int max2Process);
|
||||
|
||||
public void setSkipList(List<String> skipList);
|
||||
|
||||
|
||||
|
||||
}
|
@@ -366,4 +366,11 @@
|
||||
<class>org.dspace.statistics.AnonymizeStatistics</class>
|
||||
</step>
|
||||
</command>
|
||||
<command>
|
||||
<name>canvas-dimensions</name>
|
||||
<description>Add canvas width and height metadata for IIIF enabled items.</description>
|
||||
<step>
|
||||
<class>org.dspace.app.canvasdimension.CanvasDimensionCLI</class>
|
||||
</step>
|
||||
</command>
|
||||
</commands>
|
||||
|
@@ -10,6 +10,7 @@
|
||||
<bean id="requestItemServiceFactory" class="org.dspace.app.requestitem.factory.RequestItemServiceFactoryImpl"/>
|
||||
<bean id="itemExportServiceFactory" class="org.dspace.app.itemexport.factory.ItemExportServiceFactoryImpl"/>
|
||||
<bean id="itemImportServiceFactory" class="org.dspace.app.itemimport.factory.ItemImportServiceFactoryImpl"/>
|
||||
<bean id="iiifCanvasDimensionServiceFactory" class="org.dspace.app.canvasdimension.factory.IIIFCanvasDimensionServiceFactoryImpl"/>
|
||||
<bean id="mediaFilterServiceFactory" class="org.dspace.app.mediafilter.factory.MediaFilterServiceFactoryImpl"/>
|
||||
<bean id="sfxServiceFactory" class="org.dspace.app.sfx.factory.SfxServiceFactoryImpl"/>
|
||||
<bean id="appUtilServiceFactory" class="org.dspace.app.util.factory.UtilServiceFactoryImpl"/>
|
||||
|
@@ -17,6 +17,9 @@
|
||||
<!--Ensure that bean remains prototype ! -->
|
||||
<bean class="org.dspace.app.mediafilter.MediaFilterServiceImpl" scope="prototype"/>
|
||||
|
||||
<bean class="org.dspace.app.canvasdimension.IIIFCanvasDimensionServiceImpl" scope="prototype"/>
|
||||
<bean class="org.dspace.app.canvasdimension.IIIFApiQueryServiceImpl" scope="prototype"/>
|
||||
|
||||
<bean class="org.dspace.app.sfx.SFXFileReaderServiceImpl" scope="prototype"/>
|
||||
|
||||
<bean class="org.dspace.app.util.MetadataExposureServiceImpl"/>
|
||||
|
Reference in New Issue
Block a user