Project

General

Profile

Download (6.76 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2021 EDIT
3
* European Distributed Institute of Taxonomy
4
* http://www.e-taxonomy.eu
5
*
6
* The contents of this file are subject to the Mozilla Public License Version 1.1
7
* See LICENSE.TXT at the top of this package for the full license terms.
8
*/
9
package eu.etaxonomy.cdm.api.service.media;
10

    
11
import java.io.IOException;
12
import java.io.InputStream;
13

    
14
import org.apache.commons.imaging.ImageInfo;
15
import org.apache.commons.imaging.ImageReadException;
16
import org.apache.commons.imaging.Imaging;
17
import org.apache.commons.imaging.common.GenericImageMetadata.GenericImageMetadataItem;
18
import org.apache.commons.imaging.common.ImageMetadata;
19
import org.apache.commons.imaging.common.ImageMetadata.ImageMetadataItem;
20
import org.apache.commons.lang3.StringUtils;
21
import org.apache.http.HttpException;
22
import org.apache.http.client.ClientProtocolException;
23
import org.apache.log4j.Logger;
24

    
25
import eu.etaxonomy.cdm.common.CdmUtils;
26
import eu.etaxonomy.cdm.common.UriUtils;
27

    
28
/**
29
 * TODO make use of timeOut ?
30
 *
31
 * Most code  was extracted from CdmImageInfo.
32
 *
33
 */
34
public class MediaInfoFileReader extends AbstactMediaMetadataReader {
35

    
36
    private static Logger logger = Logger.getLogger(MediaInfoFileReader.class);
37

    
38
    public static final Integer IMAGE_READ_TIMEOUT = 3000; // ms
39

    
40
    private Integer timeOut = IMAGE_READ_TIMEOUT; // setting default
41

    
42
    /**
43
     * The <code>MediaMetadataFileReader</code> should not be used directly this method
44
     * only exists for not to break legacy code.
45
     * <p>
46
     * Instead the {@link IMediaInfoFactory} should always be used for to allow
47
     * all application parts to benefit from the potential speed up through the
48
     * MediaMetadataService or other fast source of metadata.
49
     */
50
    @Deprecated
51
    public static MediaInfoFileReader legacyFactoryMethod(eu.etaxonomy.cdm.common.URI uri) {
52
        return new MediaInfoFileReader(uri);
53
    }
54

    
55
    protected MediaInfoFileReader(eu.etaxonomy.cdm.common.URI uri) {
56
        super(uri, uri);
57
    }
58

    
59
    @Override
60
    public MediaInfoFileReader read() throws IOException, HttpException {
61
        return readBaseInfo().readMetaData();
62
    }
63

    
64
    /**
65
     * Combines the calls to:
66
     *
67
     * <ul>
68
     * <li>{@link #readImageInfo()}</li>
69
     * <li>{@link #readImageLength()}</li>
70
     * <li>{@link #readSuffix()}</li>
71
     * </ul>
72
     * to read the commonly needed base information.
73
     *
74
     * @return
75
     * @throws IOException
76
     * @throws HttpException
77
     */
78
    public MediaInfoFileReader readBaseInfo() throws IOException, HttpException{
79
        readImageInfo();
80
        readImageLength();
81
        readSuffix();
82
        return this;
83
    }
84

    
85
    /**
86
     * Reads the image info (width, height, bitPerPixel, metadata, format, mime type)
87
     */
88
    public MediaInfoFileReader readImageInfo() throws IOException, HttpException{
89

    
90
        InputStream inputStream;
91
        try {
92
            inputStream = UriUtils.getInputStream(cdmImageInfo.getUri());
93
            ImageInfo imageInfo = Imaging.getImageInfo(inputStream, null);
94

    
95
            cdmImageInfo.setFormatName(imageInfo.getFormatName());
96
            cdmImageInfo.setMimeType(imageInfo.getMimeType());
97
            cdmImageInfo.setWidth(imageInfo.getWidth());
98
            cdmImageInfo.setHeight(imageInfo.getHeight());
99
            cdmImageInfo.setBitPerPixel(imageInfo.getBitsPerPixel());
100
            inputStream.close();
101

    
102
        } catch (ImageReadException e) {
103
            logger.error("Could not read: " + cdmImageInfo.getUri() + ". " + e.getMessage());
104
            throw new IOException(e);
105
        }
106

    
107
        return this;
108
    }
109

    
110
    public MediaInfoFileReader readMetaData() throws IOException, HttpException {
111

    
112
        ImageMetadata mediaData = null;
113
        try {
114
            InputStream inputStream = UriUtils.getInputStream(cdmImageInfo.getUri());
115
            mediaData = Imaging.getMetadata(inputStream, null);
116
        }catch (ImageReadException e) {
117
            logger.error("Could not read: " + cdmImageInfo.getUri() + ". " + e.getMessage());
118
            //throw new IOException(e);
119
        }
120

    
121
        if(mediaData != null) {
122
            for (ImageMetadataItem imItem : mediaData.getItems()){
123
                if (imItem instanceof GenericImageMetadataItem){
124
                    GenericImageMetadataItem item = (GenericImageMetadataItem)imItem;
125
                    if ("Keywords".equals(item.getKeyword())){
126
                        String value = text(item);
127
                        String[] splits = value.split(":");
128
                        if (splits.length == 2){
129
                            //convention used e.g. for Flora of cyprus (#9137)
130
                            cdmImageInfo.getMetaData().put(splits[0].trim(), splits[1].trim());
131
                        }else{
132
                            cdmImageInfo.getMetaData().put(
133
                                    item.getKeyword(),
134
                                    CdmUtils.concat("; ", cdmImageInfo.getMetaData().get(item.getKeyword()), value)
135
                                    );
136
                        }
137
                    }else if (item.getKeyword().contains("/")){
138
                        //TODO: not sure where this syntax is used originally
139
                        String key = item.getKeyword();
140
                        //key.replace("/", "");
141
                        int index = key.indexOf("/");
142
                        key = key.substring(0, index);
143
                        cdmImageInfo.getMetaData().put(key, text(item));
144
                    }else{
145
                        cdmImageInfo.getMetaData().put(item.getKeyword(), text(item));
146
                    }
147
                }
148
            }
149
        }
150

    
151
        return this;
152
    }
153

    
154
    /**
155
     * Reads the size of the image defined by the {@link #imageUri} in bytes
156
     */
157
    public MediaInfoFileReader readImageLength() throws ClientProtocolException, IOException, HttpException{
158
        try {
159
            long length = UriUtils.getResourceLength(cdmImageInfo.getUri(), null);
160
            cdmImageInfo.setLength(length);
161
        } catch (HttpException e) {
162
            if (e.getMessage().equals("Could not retrieve Content-Length")){
163
                InputStream inputStream = UriUtils.getInputStream(cdmImageInfo.getUri());
164
                int n = 0;
165
                while(inputStream.read() != -1){
166
                    n++;
167
                }
168
                inputStream.close();
169
                logger.info("Content-Length not available in http header. Image size computed via input stream size: " + cdmImageInfo.getUri());
170
                cdmImageInfo.setLength(n);
171
            }else{
172
                throw e;
173
            }
174
        }
175
        return this;
176
    }
177

    
178
    public MediaInfoFileReader readSuffix(){
179
        String path = cdmImageInfo.getUri().getPath();
180
        String suffix = path.substring(StringUtils.lastIndexOf(path, '.') + 1);
181
        cdmImageInfo.setSuffix(suffix);
182
        return this;
183
    }
184
}
(5-5/9)