1 package com.github.celldynamics.quimp.plugin.utils;
2
3 import org.slf4j.Logger;
4 import org.slf4j.LoggerFactory;
5
6 import ij.process.ImageProcessor;
7
8
9
10
11
12
13
14
15 public class ImageProcessorPlus {
16
17
18
19
20 static final Logger LOGGER = LoggerFactory.getLogger(ImageProcessorPlus.class.getName());
21
22
23
24
25 public ImageProcessorPlus() {
26 }
27
28
29
30
31
32
33
34
35
36
37
38
39 public ImageProcessor extendImageBeforeRotation(ImageProcessor ip, double angle) {
40 ImageProcessor ret;
41 int width = ip.getWidth();
42 int height = ip.getHeight();
43
44 RectangleBoxquimp/plugin/utils/RectangleBox.html#RectangleBox">RectangleBox rb = new RectangleBox(width, height);
45 rb.rotateBoundingBox(angle);
46 int newWidth = (int) Math.round(rb.getWidth());
47 int newHeight = (int) Math.round(rb.getHeight());
48 if (newWidth < width) {
49 newWidth = width;
50 }
51 if (newHeight < height) {
52 newHeight = height;
53 }
54
55 ret = ip.createProcessor(newWidth, newHeight);
56
57 ret.setValue(ip.getBackgroundValue());
58 ret.setBackgroundValue(ip.getBackgroundValue());
59 ret.fill();
60 ret.setInterpolationMethod(ip.getInterpolationMethod());
61
62 ret.insert(ip, (newWidth - ip.getWidth()) / 2, (newHeight - ip.getHeight()) / 2);
63 ret.resetRoi();
64 return ret;
65 }
66
67
68
69
70
71
72
73
74
75
76 public ImageProcessor rotate(ImageProcessor ip, double angle, boolean addBorders) {
77 ImageProcessor ret;
78 if (addBorders) {
79 ret = extendImageBeforeRotation(ip, angle);
80 } else {
81 ret = ip;
82 }
83 ret.rotate(angle);
84 return ret;
85 }
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101 public ImageProcessor crop(ImageProcessor ip, int luX, int luY, int width, int height) {
102 ip.setRoi(luX, luY, width, height);
103 ip = ip.crop();
104 ip.resetRoi();
105 return ip;
106 }
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123 public ImageProcessor cropImageAfterRotation(ImageProcessor ip, int width, int height) {
124 int sw = (ip.getWidth() - width) / 2;
125 int sh = (ip.getHeight() - height) / 2;
126 if (sw < 0) {
127 sw = 0;
128 }
129 if (sh < 0) {
130 sh = 0;
131 }
132 ip.setRoi(sw, sh, width, height);
133 ip = ip.crop();
134 ip.resetRoi();
135 return ip;
136 }
137
138
139
140
141
142
143
144
145
146 public void runningMean(ImageProcessor ip, String prefilterangle, int masksize) {
147 LOGGER.debug("Convolving: " + prefilterangle + " " + masksize);
148 if (masksize == 0) {
149 return;
150 }
151 float[] kernel = new GenerateKernel(masksize).generateKernel(prefilterangle);
152 ip.convolve(kernel, masksize, masksize);
153 }
154
155
156
157
158
159
160
161 class GenerateKernel {
162 private int size;
163
164
165
166
167
168 public GenerateKernel(int size) {
169 this.size = size;
170 }
171
172
173
174
175
176
177
178
179
180
181 public float[] generateKernel(String option) {
182 float[] ret = new float[size * size];
183 int mid = size / 2;
184 switch (option) {
185 case "0":
186 for (int i = 0; i < size; i++) {
187 ret[sub2lin(mid, i)] = 1.0f;
188 }
189 break;
190 case "135":
191 for (int i = 0; i < size; i++) {
192 ret[sub2lin(i, i)] = 1.0f;
193 }
194 break;
195 case "90":
196 for (int i = 0; i < size; i++) {
197 ret[sub2lin(i, mid)] = 1.0f;
198 }
199 break;
200 case "45":
201 for (int i = 0; i < size; i++) {
202 ret[sub2lin(i, size - 1 - i)] = 1.0f;
203 }
204 break;
205 default:
206 throw new UnsupportedOperationException("Unsupported mask angle.");
207 }
208
209 return normalise(ret);
210 }
211
212
213
214
215
216
217
218
219 private int sub2lin(int row, int col) {
220 return row * size + col;
221 }
222
223
224
225
226
227
228
229
230
231 private float[] normalise(float[] kernel) {
232 float s = 0;
233 for (int i = 0; i < kernel.length; i++) {
234 s += kernel[i];
235 }
236 float[] ret = new float[kernel.length];
237 for (int i = 0; i < ret.length; i++) {
238 ret[i] = kernel[i] / s;
239 }
240 return ret;
241 }
242 }
243 }