1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.mycore.iiif.image.parser;
20
21 import org.mycore.iiif.image.model.MCRIIIFImageTargetSize;
22
23 public class MCRIIIFScaleParser {
24
25 private String targetScale;
26
27 private int sourceRegionWidth;
28
29 private int sourceRegionHeight;
30
31 public MCRIIIFScaleParser(String targetScale, int w, int h) {
32 this.targetScale = targetScale;
33 this.sourceRegionWidth = w;
34 this.sourceRegionHeight = h;
35 }
36
37 private boolean isFull() {
38 return "full".equals(targetScale) || "max".equals(targetScale);
39 }
40
41 private boolean isPercent() {
42 return targetScale.startsWith("pct:");
43 }
44
45 private boolean isBestFit() {
46 return targetScale.startsWith("!");
47 }
48
49 public MCRIIIFImageTargetSize parseTargetScale() {
50 if (isFull()) {
51 return new MCRIIIFImageTargetSize(sourceRegionWidth, sourceRegionHeight);
52 }
53
54 if (isPercent()) {
55 return parsePercentValue();
56 }
57
58 StringBuilder wBuilder = new StringBuilder();
59 StringBuilder hBuilder = new StringBuilder();
60 getWidthAndHeightStrings(wBuilder, hBuilder);
61 String w = wBuilder.toString();
62 String h = hBuilder.toString();
63
64 try {
65 if (w.length() == 0) {
66 return scaleToHeight(Integer.parseInt(h));
67 } else if (h.length() == 0) {
68 return scaleToWidth(Integer.parseInt(w));
69 } else if (isBestFit()) {
70 return bestFit(Integer.parseInt(w), Integer.parseInt(h));
71 } else {
72 return scale(Integer.parseInt(w), Integer.parseInt(h));
73 }
74 } catch (NumberFormatException e) {
75 throw new IllegalArgumentException(h + " or " + w + " ist not a valid scale value!", e);
76 }
77
78 }
79
80 private MCRIIIFImageTargetSize scale(int w, int h) {
81 if (w <= 0) {
82 throw new IllegalArgumentException("width to scale must be positive! [" + w + "]");
83 }
84 if (h <= 0) {
85 throw new IllegalArgumentException("height to scale must be positive! [" + h + "]");
86 }
87 return new MCRIIIFImageTargetSize(w, h);
88 }
89
90 private MCRIIIFImageTargetSize bestFit(int w, int h) {
91 if (w <= 0) {
92 throw new IllegalArgumentException("width to scale must be positive! [" + w + "]");
93 }
94 if (h <= 0) {
95 throw new IllegalArgumentException("height to scale must be positive! [" + h + "]");
96 }
97 double ratio = Math.min(((double) w) / this.sourceRegionWidth, ((double) h) / this.sourceRegionHeight);
98 return new MCRIIIFImageTargetSize((int) Math.round(this.sourceRegionWidth * ratio),
99 (int) Math.round(this.sourceRegionHeight * ratio));
100 }
101
102 private MCRIIIFImageTargetSize scaleToWidth(Integer w) {
103 if (w <= 0) {
104 throw new IllegalArgumentException("width to scale must be positive! [" + w + "]");
105 }
106 double ratio = ((double) this.sourceRegionHeight) / this.sourceRegionWidth;
107 return new MCRIIIFImageTargetSize(w, (int) Math.ceil(ratio * w));
108 }
109
110 private MCRIIIFImageTargetSize scaleToHeight(Integer h) {
111 if (h <= 0) {
112 throw new IllegalArgumentException("height to scale must be positive! [" + h + "]");
113 }
114 double ratio = ((double) this.sourceRegionWidth) / this.sourceRegionHeight;
115 return new MCRIIIFImageTargetSize((int) Math.ceil(ratio * h), h);
116 }
117
118 private MCRIIIFImageTargetSize parsePercentValue() {
119 String rightValue = this.targetScale.substring("pct:".length());
120 double percentValue;
121
122 try {
123 percentValue = Double.parseDouble(rightValue);
124 } catch (NumberFormatException e) {
125 throw new IllegalArgumentException(rightValue + " is not a valid scale!", e);
126 }
127
128 if (percentValue <= 0) {
129 throw new IllegalArgumentException("Scale has to be positive! [" + percentValue + "]");
130 }
131
132 return new MCRIIIFImageTargetSize((int) Math.ceil(percentValue / 100 * sourceRegionWidth),
133 (int) Math.ceil(percentValue / 100 * sourceRegionHeight));
134 }
135
136 private void getWidthAndHeightStrings(StringBuilder wBuilder, StringBuilder hBuilder) {
137 char[] chars = this.targetScale.toCharArray();
138 boolean writeW = true;
139 boolean first = true;
140 for (char currentChar : chars) {
141 switch (currentChar) {
142 case ',':
143 first = false;
144 if (!writeW) {
145 throw new IllegalArgumentException("second , found in scale!");
146 }
147 writeW = false;
148 break;
149 case '!':
150 if (!first) {
151 throw new IllegalArgumentException("! should be located only in the first position of scale!");
152 }
153 first = false;
154 break;
155 default:
156 first = false;
157 if (writeW) {
158 wBuilder.append(currentChar);
159 } else {
160 hBuilder.append(currentChar);
161 }
162 break;
163 }
164 }
165
166 }
167
168 }