Revision d907eaa7
Added by Andreas Kohlbecker almost 13 years ago
cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/media/MediaUtils.java | ||
---|---|---|
1 | 1 |
package eu.etaxonomy.cdm.model.media; |
2 | 2 |
|
3 | 3 |
import java.util.ArrayList; |
4 |
import java.util.Collection; |
|
5 |
import java.util.Collections; |
|
6 |
import java.util.HashSet; |
|
7 |
import java.util.Iterator; |
|
4 | 8 |
import java.util.List; |
5 | 9 |
import java.util.NoSuchElementException; |
10 |
import java.util.Set; |
|
6 | 11 |
import java.util.SortedMap; |
7 | 12 |
import java.util.TreeMap; |
8 | 13 |
import java.util.regex.Matcher; |
... | ... | |
12 | 17 |
|
13 | 18 |
public class MediaUtils { |
14 | 19 |
|
15 |
private static final Logger logger = Logger.getLogger(MediaUtils.class); |
|
16 |
|
|
17 |
/** |
|
18 |
* @param mimeTypeRegexes |
|
19 |
* @param size |
|
20 |
* @param widthOrDuration |
|
21 |
* @param height |
|
22 |
* @return |
|
23 |
* |
|
24 |
* |
|
25 |
*/ |
|
26 |
public static MediaRepresentation findBestMatchingRepresentation(Media media, Integer size, Integer height, Integer widthOrDuration, String[] mimeTypes){ |
|
27 |
// find best matching representations of each media |
|
28 |
SortedMap<Integer, MediaRepresentation> prefRepresentations |
|
29 |
= orderMediaRepresentations(media, mimeTypes, size, widthOrDuration, height); |
|
30 |
try { |
|
31 |
// take first one and remove all other representations |
|
32 |
MediaRepresentation prefOne = prefRepresentations.get(prefRepresentations.firstKey()); |
|
33 |
|
|
34 |
return prefOne; |
|
35 |
|
|
36 |
} catch (NoSuchElementException nse) { |
|
37 |
/* IGNORE */ |
|
38 |
} |
|
39 |
return null; |
|
40 |
} |
|
41 |
|
|
42 |
/** |
|
43 |
* @param mediaList |
|
44 |
* @param mimeTypes |
|
45 |
* @param sizeTokens |
|
46 |
* @param widthOrDuration |
|
47 |
* @param height |
|
48 |
* @param size |
|
49 |
* @return |
|
50 |
*/ |
|
51 |
public static List<Media> findPreferredMedia(List<Media> mediaList, |
|
52 |
String[] mimeTypes, String[] sizeTokens, Integer widthOrDuration, |
|
53 |
Integer height, Integer size) { |
|
54 |
for(int i=0; i<mimeTypes.length; i++){ |
|
55 |
mimeTypes[i] = mimeTypes[i].replace(':', '/'); |
|
56 |
} |
|
57 |
|
|
58 |
if(sizeTokens.length > 0){ |
|
59 |
try { |
|
60 |
size = Integer.valueOf(sizeTokens[0]); |
|
61 |
} catch (NumberFormatException nfe) { |
|
62 |
/* IGNORE */ |
|
63 |
} |
|
64 |
} |
|
65 |
if(sizeTokens.length > 1){ |
|
66 |
try { |
|
67 |
widthOrDuration = Integer.valueOf(sizeTokens[1]); |
|
68 |
} catch (NumberFormatException nfe) { |
|
69 |
/* IGNORE */ |
|
70 |
} |
|
71 |
} |
|
72 |
if(sizeTokens.length > 2){ |
|
73 |
try { |
|
74 |
height = Integer.valueOf(sizeTokens[2]); |
|
75 |
} catch (NumberFormatException nfe) { |
|
76 |
/* IGNORE */ |
|
77 |
} |
|
78 |
} |
|
79 |
|
|
80 |
List<Media> returnMedia = new ArrayList<Media>(mediaList.size()); |
|
81 |
if(mediaList != null){ |
|
82 |
for(Media media : mediaList){ |
|
83 |
SortedMap<Integer, MediaRepresentation> prefRepresentations |
|
84 |
= orderMediaRepresentations(media, mimeTypes, size, widthOrDuration, height); |
|
85 |
try { |
|
86 |
// take first one and remove all other representations |
|
87 |
MediaRepresentation prefOne = prefRepresentations.get(prefRepresentations.firstKey()); |
|
88 |
for (MediaRepresentation representation : media.getRepresentations()) { |
|
89 |
if (representation != prefOne) { |
|
90 |
media.removeRepresentation(representation); |
|
91 |
} |
|
92 |
} |
|
93 |
returnMedia.add(media); |
|
94 |
} catch (NoSuchElementException nse) { |
|
95 |
logger.debug(nse); |
|
96 |
/* IGNORE */ |
|
97 |
} |
|
98 |
} |
|
99 |
} |
|
100 |
return returnMedia; |
|
101 |
} |
|
102 |
|
|
103 |
/** |
|
104 |
* @param media |
|
105 |
* @param mimeTypeRegexes |
|
106 |
* @param size |
|
107 |
* @param widthOrDuration |
|
108 |
* @param height |
|
109 |
* @return |
|
110 |
* |
|
111 |
* TODO move into a media utils class |
|
112 |
* TODO implement the quality filter |
|
113 |
|
|
114 |
public static SortedMap<String, MediaRepresentation> orderMediaRepresentations(Media media, String[] mimeTypeRegexes, |
|
115 |
Integer size, Integer widthOrDuration, Integer height) { |
|
116 |
SortedMap<String, MediaRepresentation> prefRepr = new TreeMap<String, MediaRepresentation>(); |
|
117 |
for (String mimeTypeRegex : mimeTypeRegexes) { |
|
118 |
// getRepresentationByMimeType |
|
119 |
Pattern mimeTypePattern = Pattern.compile(mimeTypeRegex); |
|
120 |
int representationCnt = 0; |
|
121 |
for (MediaRepresentation representation : media.getRepresentations()) { |
|
122 |
int dwa = 0; |
|
123 |
if(representation.getMimeType() == null){ |
|
124 |
prefRepr.put((dwa + representationCnt++) + "_NA", representation); |
|
125 |
} else { |
|
126 |
Matcher mather = mimeTypePattern.matcher(representation.getMimeType()); |
|
127 |
if (mather.matches()) { |
|
128 |
|
|
129 |
/* TODO the quality filter part is being skipped |
|
130 |
* // look for representation with the best matching parts |
|
131 |
for (MediaRepresentationPart part : representation.getParts()) { |
|
132 |
if (part instanceof ImageFile) { |
|
133 |
ImageFile image = (ImageFile) part; |
|
134 |
int dw = image.getWidth() * image.getHeight() - height * widthOrDuration; |
|
135 |
if (dw < 0) { |
|
136 |
dw *= -1; |
|
137 |
} |
|
138 |
dwa += dw; |
|
139 |
} |
|
140 |
dwa = (representation.getParts().size() > 0 ? dwa / representation.getParts().size() : 0); |
|
141 |
} |
|
142 |
prefRepr.put((dwa + representationCnt++) + '_' + representation.getMimeType(), representation); |
|
143 |
|
|
144 |
// preferred mime type found => end loop |
|
145 |
break; |
|
146 |
} |
|
147 |
} |
|
148 |
} |
|
149 |
} |
|
150 |
return prefRepr; |
|
151 |
} |
|
152 |
|
|
153 |
*/ |
|
154 |
/** |
|
155 |
* @param mimeTypeRegexes |
|
156 |
* @param size |
|
157 |
* @param widthOrDuration |
|
158 |
* @param height |
|
159 |
* @return |
|
160 |
* |
|
161 |
* |
|
162 |
*/ |
|
163 |
private static SortedMap<Integer, MediaRepresentation> orderMediaRepresentations(Media media, String[] mimeTypeRegexes, |
|
164 |
Integer size, Integer widthOrDuration, Integer height) { |
|
165 |
|
|
166 |
SortedMap<Integer, MediaRepresentation> prefRepr = new TreeMap<Integer, MediaRepresentation>(); |
|
167 |
// SortedMap<String, MediaRepresentation> sortedForSizeDistance = new TreeMap<String, MediaRepresentation>(); |
|
168 |
// String keyString = ""; |
|
169 |
|
|
170 |
size = (size == null ? new Integer(0) : size ); |
|
171 |
widthOrDuration = (widthOrDuration == null ? new Integer(0) : widthOrDuration); |
|
172 |
height = (height == null ? new Integer(0) : height); |
|
173 |
mimeTypeRegexes = (mimeTypeRegexes == null ? new String[]{} : mimeTypeRegexes); |
|
174 |
|
|
175 |
if(media != null){ |
|
176 |
|
|
177 |
for (String mimeTypeRegex : mimeTypeRegexes) { |
|
178 |
// getRepresentationByMimeType |
|
179 |
Pattern mimeTypePattern = Pattern.compile(mimeTypeRegex); |
|
180 |
int representationCnt = 0; |
|
181 |
for (MediaRepresentation representation : media.getRepresentations()) { |
|
182 |
if(representation.getMimeType() != null){ |
|
183 |
Matcher mather = mimeTypePattern.matcher(representation.getMimeType()); |
|
184 |
if (mather.matches()) { |
|
185 |
int dwa = 0; |
|
186 |
|
|
187 |
//first the size is used for comparison |
|
188 |
for (MediaRepresentationPart part : representation.getParts()) { |
|
189 |
if (part.getSize()!= null){ |
|
190 |
int sizeOfPart = part.getSize(); |
|
191 |
int distance = sizeOfPart - size; |
|
192 |
if (distance < 0) { |
|
193 |
distance*= -1; |
|
194 |
} |
|
195 |
dwa += distance; |
|
196 |
} |
|
197 |
//if height and width/duration is defined, add this information, too |
|
198 |
if (height != 0 && widthOrDuration != 0){ |
|
199 |
int dw = 0; |
|
200 |
|
|
201 |
if (part instanceof ImageFile) { |
|
202 |
ImageFile image = (ImageFile) part; |
|
203 |
dw = image.getWidth() * image.getHeight() - height * widthOrDuration; |
|
204 |
} |
|
205 |
else if (part instanceof MovieFile){ |
|
206 |
MovieFile movie = (MovieFile) part; |
|
207 |
dw = movie.getDuration() - widthOrDuration; |
|
208 |
|
|
209 |
}else if (part instanceof AudioFile){ |
|
210 |
AudioFile audio = (AudioFile) part; |
|
211 |
dw = audio.getDuration() - widthOrDuration; |
|
212 |
|
|
213 |
} |
|
214 |
if (dw < 0) { |
|
215 |
dw *= -1; |
|
216 |
} |
|
217 |
dwa += dw; |
|
218 |
|
|
219 |
} |
|
220 |
} |
|
221 |
dwa = (representation.getParts().size() > 0 ? dwa / representation.getParts().size() : 0); |
|
222 |
|
|
223 |
//keyString =(dwa + representationCnt++) + '_' + representation.getMimeType(); |
|
224 |
|
|
225 |
prefRepr.put((dwa + representationCnt++), representation); |
|
226 |
} |
|
227 |
} |
|
228 |
} |
|
229 |
} |
|
230 |
} |
|
231 |
return prefRepr; |
|
232 |
} |
|
20 |
private static final Logger logger = Logger.getLogger(MediaUtils.class); |
|
21 |
|
|
22 |
/** |
|
23 |
* @param representationPartType TODO |
|
24 |
* @param size |
|
25 |
* @param height |
|
26 |
* @param widthOrDuration |
|
27 |
* @param mimeTypeRegexes |
|
28 |
* @return |
|
29 |
* |
|
30 |
* |
|
31 |
*/ |
|
32 |
public static MediaRepresentation findBestMatchingRepresentation(Media media, Class<? extends MediaRepresentationPart> representationPartType, Integer size, Integer height, Integer widthOrDuration, String[] mimeTypes){ |
|
33 |
// find best matching representations of each media |
|
34 |
SortedMap<Integer, MediaRepresentation> prefRepresentations |
|
35 |
= filterAndOrderMediaRepresentations(media.getRepresentations(), null, mimeTypes, size, widthOrDuration, height); |
|
36 |
try { |
|
37 |
// take first one and remove all other representations |
|
38 |
MediaRepresentation prefOne = prefRepresentations.get(prefRepresentations.firstKey()); |
|
39 |
|
|
40 |
return prefOne; |
|
41 |
|
|
42 |
} catch (NoSuchElementException nse) { |
|
43 |
/* IGNORE */ |
|
44 |
} |
|
45 |
return null; |
|
46 |
} |
|
47 |
|
|
48 |
/** |
|
49 |
* |
|
50 |
* @param mediaList |
|
51 |
* @param representationPartType TODO |
|
52 |
* @param mimeTypes |
|
53 |
* @param sizeTokens |
|
54 |
* @param widthOrDuration |
|
55 |
* @param height |
|
56 |
* @param size |
|
57 |
* @return |
|
58 |
*/ |
|
59 |
public static List<Media> findPreferredMedia(List<Media> mediaList, |
|
60 |
Class<? extends MediaRepresentationPart> representationPartType, String[] mimeTypes, String[] sizeTokens, |
|
61 |
Integer widthOrDuration, Integer height, Integer size) { |
|
62 |
|
|
63 |
if(mimeTypes != null) { |
|
64 |
for(int i=0; i<mimeTypes.length; i++){ |
|
65 |
mimeTypes[i] = mimeTypes[i].replace(':', '/'); |
|
66 |
} |
|
67 |
} |
|
68 |
|
|
69 |
if(sizeTokens != null) { |
|
70 |
if(sizeTokens.length > 0){ |
|
71 |
try { |
|
72 |
size = Integer.valueOf(sizeTokens[0]); |
|
73 |
} catch (NumberFormatException nfe) { |
|
74 |
/* IGNORE */ |
|
75 |
} |
|
76 |
} |
|
77 |
if(sizeTokens.length > 1){ |
|
78 |
try { |
|
79 |
widthOrDuration = Integer.valueOf(sizeTokens[1]); |
|
80 |
} catch (NumberFormatException nfe) { |
|
81 |
/* IGNORE */ |
|
82 |
} |
|
83 |
} |
|
84 |
if(sizeTokens.length > 2){ |
|
85 |
try { |
|
86 |
height = Integer.valueOf(sizeTokens[2]); |
|
87 |
} catch (NumberFormatException nfe) { |
|
88 |
/* IGNORE */ |
|
89 |
} |
|
90 |
} |
|
91 |
} |
|
92 |
|
|
93 |
List<Media> returnMediaList = new ArrayList<Media>(mediaList.size()); |
|
94 |
if(mediaList != null){ |
|
95 |
for(Media media : mediaList){ |
|
96 |
|
|
97 |
Set<MediaRepresentation> candidateRepresentations = new HashSet<MediaRepresentation>(); |
|
98 |
candidateRepresentations.addAll(media.getRepresentations()); |
|
99 |
|
|
100 |
SortedMap<Integer, MediaRepresentation> prefRepresentations |
|
101 |
= filterAndOrderMediaRepresentations(candidateRepresentations, representationPartType, mimeTypes, size, widthOrDuration, height); |
|
102 |
try { |
|
103 |
if(prefRepresentations.size() > 0){ |
|
104 |
// Media.representations is a set |
|
105 |
// so it cannot retain the sorting which has been found by filterAndOrderMediaRepresentations() |
|
106 |
// thus we take first one and remove all other representations |
|
107 |
|
|
108 |
media.getRepresentations().clear(); |
|
109 |
media.addRepresentation(prefRepresentations.get(prefRepresentations.firstKey())); |
|
110 |
returnMediaList.add(media); |
|
111 |
} |
|
112 |
} catch (NoSuchElementException nse) { |
|
113 |
logger.debug(nse); |
|
114 |
/* IGNORE */ |
|
115 |
} |
|
116 |
|
|
117 |
} |
|
118 |
} |
|
119 |
return returnMediaList; |
|
120 |
} |
|
121 |
|
|
122 |
/** |
|
123 |
* @param media |
|
124 |
* @param mimeTypeRegexes |
|
125 |
* @param size |
|
126 |
* @param widthOrDuration |
|
127 |
* @param height |
|
128 |
* @return |
|
129 |
* |
|
130 |
* TODO move into a media utils class |
|
131 |
* TODO implement the quality filter |
|
132 |
|
|
133 |
public static SortedMap<String, MediaRepresentation> orderMediaRepresentations(Media media, String[] mimeTypeRegexes, |
|
134 |
Integer size, Integer widthOrDuration, Integer height) { |
|
135 |
SortedMap<String, MediaRepresentation> prefRepr = new TreeMap<String, MediaRepresentation>(); |
|
136 |
for (String mimeTypeRegex : mimeTypeRegexes) { |
|
137 |
// getRepresentationByMimeType |
|
138 |
Pattern mimeTypePattern = Pattern.compile(mimeTypeRegex); |
|
139 |
int representationCnt = 0; |
|
140 |
for (MediaRepresentation representation : media.getRepresentations()) { |
|
141 |
int dwa = 0; |
|
142 |
if(representation.getMimeType() == null){ |
|
143 |
prefRepr.put((dwa + representationCnt++) + "_NA", representation); |
|
144 |
} else { |
|
145 |
Matcher mather = mimeTypePattern.matcher(representation.getMimeType()); |
|
146 |
if (mather.matches()) { |
|
147 |
|
|
148 |
/* TODO the quality filter part is being skipped |
|
149 |
* // look for representation with the best matching parts |
|
150 |
for (MediaRepresentationPart part : representation.getParts()) { |
|
151 |
if (part instanceof ImageFile) { |
|
152 |
ImageFile image = (ImageFile) part; |
|
153 |
int dw = image.getWidth() * image.getHeight() - height * widthOrDuration; |
|
154 |
if (dw < 0) { |
|
155 |
dw *= -1; |
|
156 |
} |
|
157 |
dwa += dw; |
|
158 |
} |
|
159 |
dwa = (representation.getParts().size() > 0 ? dwa / representation.getParts().size() : 0); |
|
160 |
} |
|
161 |
prefRepr.put((dwa + representationCnt++) + '_' + representation.getMimeType(), representation); |
|
162 |
|
|
163 |
// preferred mime type found => end loop |
|
164 |
break; |
|
165 |
} |
|
166 |
} |
|
167 |
} |
|
168 |
} |
|
169 |
return prefRepr; |
|
170 |
} |
|
171 |
|
|
172 |
*/ |
|
173 |
/** |
|
174 |
* @param mimeTypeRegexes |
|
175 |
* @param size |
|
176 |
* @param widthOrDuration |
|
177 |
* @param height |
|
178 |
* @return |
|
179 |
* |
|
180 |
* |
|
181 |
*/ |
|
182 |
private static SortedMap<Integer, MediaRepresentation> filterAndOrderMediaRepresentations(Set<MediaRepresentation> mediaRepresentations, |
|
183 |
Class<? extends MediaRepresentationPart> representationPartType, String[] mimeTypeRegexes, |
|
184 |
Integer size, Integer widthOrDuration, Integer height) { |
|
185 |
|
|
186 |
SortedMap<Integer, MediaRepresentation> prefRepr = new TreeMap<Integer, MediaRepresentation>(); |
|
187 |
|
|
188 |
|
|
189 |
size = (size == null ? new Integer(0) : size ); |
|
190 |
widthOrDuration = (widthOrDuration == null ? new Integer(0) : widthOrDuration); |
|
191 |
height = (height == null ? new Integer(0) : height); |
|
192 |
mimeTypeRegexes = (mimeTypeRegexes == null ? new String[]{".*"} : mimeTypeRegexes); |
|
193 |
|
|
194 |
for (String mimeTypeRegex : mimeTypeRegexes) { |
|
195 |
// getRepresentationByMimeType |
|
196 |
Pattern mimeTypePattern = Pattern.compile(mimeTypeRegex); |
|
197 |
int representationCnt = 0; |
|
198 |
for (MediaRepresentation representation : mediaRepresentations) { |
|
199 |
|
|
200 |
List<MediaRepresentationPart> matchingParts = new ArrayList<MediaRepresentationPart>(); |
|
201 |
|
|
202 |
|
|
203 |
// check MIME type |
|
204 |
boolean mimeTypeOK = representation.getMimeType() == null || mimeTypePattern.matcher(representation.getMimeType()).matches(); |
|
205 |
logger.debug("mimeTypeOK: " + Boolean.valueOf(mimeTypeOK).toString()); |
|
206 |
|
|
207 |
int dwa = 0; |
|
208 |
|
|
209 |
|
|
210 |
//first the size is used for comparison |
|
211 |
for (MediaRepresentationPart part : representation.getParts()) { |
|
212 |
|
|
213 |
// check representationPartType |
|
214 |
boolean representationPartTypeOK = representationPartType == null || part.getClass().isAssignableFrom(representationPartType); |
|
215 |
logger.debug("representationPartTypeOK: " + Boolean.valueOf(representationPartTypeOK).toString()); |
|
216 |
|
|
217 |
if ( !(representationPartTypeOK && mimeTypeOK) ) { |
|
218 |
continue; |
|
219 |
} |
|
220 |
|
|
221 |
logger.debug(part + " matches"); |
|
222 |
matchingParts.add(part); |
|
223 |
|
|
224 |
if (part.getSize()!= null){ |
|
225 |
int sizeOfPart = part.getSize(); |
|
226 |
int distance = sizeOfPart - size; |
|
227 |
if (distance < 0) { |
|
228 |
distance*= -1; |
|
229 |
} |
|
230 |
dwa += distance; |
|
231 |
} |
|
232 |
|
|
233 |
//if height and width/duration is defined, add this information, too |
|
234 |
if (height != 0 && widthOrDuration != 0){ |
|
235 |
int durationWidthWeight = 0; |
|
236 |
|
|
237 |
if (part instanceof ImageFile) { |
|
238 |
ImageFile image = (ImageFile) part; |
|
239 |
durationWidthWeight = image.getWidth() * image.getHeight() - height * widthOrDuration; |
|
240 |
} |
|
241 |
else if (part instanceof MovieFile){ |
|
242 |
MovieFile movie = (MovieFile) part; |
|
243 |
durationWidthWeight = movie.getDuration() - widthOrDuration; |
|
244 |
|
|
245 |
}else if (part instanceof AudioFile){ |
|
246 |
AudioFile audio = (AudioFile) part; |
|
247 |
durationWidthWeight = audio.getDuration() - widthOrDuration; |
|
248 |
|
|
249 |
} |
|
250 |
if (durationWidthWeight < 0) { |
|
251 |
durationWidthWeight *= -1; |
|
252 |
} |
|
253 |
dwa += durationWidthWeight; |
|
254 |
|
|
255 |
} |
|
256 |
} // loop parts |
|
257 |
logger.debug("matchingParts.size():" + matchingParts.size()); |
|
258 |
if(matchingParts.size() > 0 ){ |
|
259 |
dwa = dwa / matchingParts.size(); |
|
260 |
|
|
261 |
representation.getParts().clear(); |
|
262 |
representation.getParts().addAll(matchingParts); |
|
263 |
|
|
264 |
//keyString =(dwa + representationCnt++) + '_' + representation.getMimeType(); |
|
265 |
|
|
266 |
prefRepr.put((dwa + representationCnt++), representation); |
|
267 |
} |
|
268 |
} // loop representations |
|
269 |
} // loop mime types |
|
270 |
logger.debug(prefRepr.size() + " preferred representations found"); |
|
271 |
return prefRepr; |
|
272 |
} |
|
233 | 273 |
} |
Also available in: Unified diff
modifications in cdmlib for #2206 (modify the means to find images for the data portal)