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 java.util.Arrays;
22 import java.util.List;
23 import java.util.Locale;
24 import java.util.stream.Collectors;
25
26 import org.mycore.iiif.image.model.MCRIIIFImageSourceRegion;
27
28 public class MCRIIIFRegionParser {
29
30 public static final String PERCENT_PREFIX = "pct:";
31
32 private final int w;
33
34 private final int h;
35
36 private final String sourceRegion;
37
38 private boolean completeValid = true;
39
40 public MCRIIIFRegionParser(String sourceRegion, int w, int h) {
41 this.sourceRegion = sourceRegion.toLowerCase(Locale.ENGLISH);
42
43 this.w = w;
44 this.h = h;
45
46 if (w < 0 || h < 0) {
47 throw new IllegalArgumentException("w or h are zero!");
48 }
49
50 if (isFull()) {
51 return;
52 }
53
54 if (isSquare()) {
55 return;
56 }
57
58 if (parseNumbers().size() != 4) {
59 completeValid = false;
60 throw new IllegalArgumentException("sourceRegion must have 4 numbers!");
61 }
62 }
63
64 public MCRIIIFImageSourceRegion parseImageRegion() throws NumberFormatException {
65 if (isPercent()) {
66 return parsePercentImageRegion();
67 } else if (isFull()) {
68 return new MCRIIIFImageSourceRegion(0, 0, w - 1, h - 1);
69 } else if (isSquare()) {
70 final int shorterDimension = Math.min(w, h);
71 final int x1 = (int) Math.floor(w / 2.0 - shorterDimension / 2.0);
72 final int y1 = (int) Math.floor(h / 2.0 - shorterDimension / 2.0);
73 return new MCRIIIFImageSourceRegion(x1, y1, x1 + shorterDimension, y1 + shorterDimension);
74 }
75
76 return parseAbsoluteImageRegion();
77 }
78
79 private MCRIIIFImageSourceRegion parsePercentImageRegion() {
80 List<Double> doubles = parseNumbers();
81
82 double x = Math.floor(doubles.get(0) * (w / 100.0));
83 double y = Math.floor(doubles.get(1) * (h / 100.0));
84 double x2 = Math.ceil(x + (doubles.get(2) * (w / 100.0)));
85 double y2 = Math.ceil(y + (doubles.get(3) * (w / 100.0)));
86
87 return parseImageRegion((int) x, (int) y, (int) x2, (int) y2);
88 }
89
90 private MCRIIIFImageSourceRegion parseAbsoluteImageRegion() {
91 List<Double> doubles = parseNumbers();
92 Double x1 = doubles.get(0);
93 Double y1 = doubles.get(1);
94 Double x2 = doubles.get(2) + x1;
95 Double y2 = doubles.get(3) + y1;
96 return parseImageRegion((int) Math.round(x1), (int) Math.round(y1), (int) Math.round(x2), (int) Math.round(y2));
97 }
98
99 private MCRIIIFImageSourceRegion parseImageRegion(int x1, int y1, int x2, int y2) {
100 if (x1 >= w || y1 >= h) {
101 completeValid = false;
102 throw new IllegalArgumentException(
103 "x[" + x1 + "] or y[" + y1 + "] cant be bigger then or equal image size[" + w + "x" + h + "]!");
104 }
105
106 if (!(y1 < y2 && x1 < x2 && x1 >= 0 && y1 >= 0 && x2 <= w && y2 <= h)) {
107 completeValid = false;
108 }
109
110
111 int nx1 = Math.max(0, x1);
112 int ny1 = Math.max(0, y1);
113
114
115 int nx2 = Math.min(w - 1, x2);
116 int ny2 = Math.min(h - 1, y2);
117
118 return new MCRIIIFImageSourceRegion(nx1, ny1, nx2, ny2);
119 }
120
121 private boolean isPercent() {
122 return this.sourceRegion.startsWith(PERCENT_PREFIX);
123 }
124
125 private boolean isFull() {
126 return "full".equals(sourceRegion);
127 }
128
129 private boolean isSquare() {
130 return "square".equals(sourceRegion);
131 }
132
133 private List<Double> parseNumbers() {
134 return Arrays
135 .stream((isPercent() ? this.sourceRegion.substring(PERCENT_PREFIX.length()) : this.sourceRegion).split(","))
136 .map(Double::parseDouble)
137 .collect(Collectors.toList());
138 }
139
140 public boolean isCompleteValid() {
141 return completeValid;
142 }
143 }