1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 package org.openimaj.image.processing.resize;
31
32 import org.openimaj.citation.annotation.Reference;
33 import org.openimaj.citation.annotation.ReferenceType;
34 import org.openimaj.image.FImage;
35 import org.openimaj.image.Image;
36 import org.openimaj.image.processing.resize.filters.TriangleFilter;
37 import org.openimaj.image.processor.SinglebandImageProcessor;
38 import org.openimaj.math.geometry.shape.Rectangle;
39
40
41
42
43
44
45
46
47
48
49
50
51 @Reference(
52 type = ReferenceType.Incollection,
53 author = { "Schumacher, Dale" },
54 title = "Graphics Gems III",
55 year = "1992",
56 pages = { "8", "", "16" },
57 chapter = "General Filtered Image Rescaling",
58 url = "http://dl.acm.org/citation.cfm?id=130745.130747",
59 editor = { "Kirk, David" },
60 publisher = "Academic Press Professional, Inc.",
61 customData = {
62 "isbn", "0-12-409671-9",
63 "numpages", "9",
64 "acmid", "130747",
65 "address", "San Diego, CA, USA"
66 })
67 public class ResizeProcessor implements SinglebandImageProcessor<Float, FImage> {
68
69
70
71
72
73
74
75
76
77 public static enum Mode {
78
79 DOUBLE,
80
81 HALF,
82
83 SCALE,
84
85 ASPECT_RATIO,
86
87 FIT,
88
89
90
91
92 MAX,
93
94
95
96
97 MAX_AREA,
98
99 NONE,
100 }
101
102
103 private Mode mode = null;
104
105
106 private float amount = 0;
107
108
109 private float newX;
110
111
112 private float newY;
113
114
115 private ResizeFilterFunction filterFunction;
116
117
118
119
120
121 public static final ResizeFilterFunction DEFAULT_FILTER = TriangleFilter.INSTANCE;
122
123
124
125
126
127
128
129
130
131 public ResizeProcessor(Mode mode) {
132 this.mode = mode;
133 this.filterFunction = DEFAULT_FILTER;
134 }
135
136
137
138
139
140
141
142
143
144
145 public ResizeProcessor(float amount, ResizeFilterFunction ff) {
146 this.mode = Mode.SCALE;
147 this.amount = amount;
148 this.filterFunction = ff;
149 }
150
151
152
153
154
155
156
157
158
159
160
161
162
163 public ResizeProcessor(float newX, float newY, ResizeFilterFunction ff) {
164 this.mode = Mode.ASPECT_RATIO;
165 this.newX = newX;
166 this.newY = newY;
167 this.filterFunction = ff;
168 }
169
170
171
172
173
174
175
176
177 public ResizeProcessor(float amount) {
178 this(amount, DEFAULT_FILTER);
179 }
180
181
182
183
184
185
186
187
188
189
190
191
192 public ResizeProcessor(float newX, float newY) {
193 this(newX, newY, DEFAULT_FILTER);
194 }
195
196
197
198
199
200
201
202
203
204
205 public ResizeProcessor(int maxSize) {
206 this.mode = Mode.MAX;
207 this.newX = maxSize;
208 this.newY = maxSize;
209 this.filterFunction = DEFAULT_FILTER;
210 }
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225 public ResizeProcessor(int maxSizeArea, boolean area) {
226 this.mode = area ? Mode.MAX_AREA : Mode.MAX;
227 this.newX = maxSizeArea;
228 this.newY = maxSizeArea;
229 }
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246 public ResizeProcessor(int newX, int newY, boolean aspectRatio) {
247 this(newX, newY, DEFAULT_FILTER);
248
249 if (aspectRatio)
250 this.mode = Mode.ASPECT_RATIO;
251 else
252 this.mode = Mode.FIT;
253 }
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272 public ResizeProcessor(int newX, int newY, boolean aspectRatio, ResizeFilterFunction filterf) {
273 this(newX, newY, filterf);
274
275 if (aspectRatio)
276 this.mode = Mode.ASPECT_RATIO;
277 else
278 this.mode = Mode.FIT;
279 }
280
281
282
283
284
285
286 @Override
287 public void processImage(FImage image) {
288 switch (this.mode) {
289 case DOUBLE:
290 internalDoubleSize(image);
291 break;
292 case HALF:
293 internalHalfSize(image);
294 break;
295 case FIT:
296 zoomInplace(image, (int) newX, (int) newY, filterFunction);
297 break;
298 case SCALE:
299 newX = image.width * amount;
300 newY = image.height * amount;
301 case ASPECT_RATIO:
302 resample(image, (int) newX, (int) newY, true, filterFunction);
303 break;
304 case MAX:
305 resizeMax(image, (int) newX, filterFunction);
306 break;
307 case MAX_AREA:
308 resizeMaxArea(image, (int) newX, filterFunction);
309 break;
310 case NONE:
311 return;
312 default:
313 zoomInplace(image, (int) newX, (int) newY, this.filterFunction);
314 }
315 }
316
317
318
319
320
321
322
323 public void setFilterFunction(ResizeFilterFunction filterFunction) {
324 this.filterFunction = filterFunction;
325 }
326
327
328
329
330
331
332
333
334
335
336
337
338
339 public static FImage resizeMax(FImage image, int maxDim, ResizeFilterFunction filterf) {
340 final int width = image.width;
341 final int height = image.height;
342
343 int newWidth, newHeight;
344 if (width < maxDim && height < maxDim) {
345 return image;
346 } else if (width < height) {
347 newHeight = maxDim;
348 final float resizeRatio = ((float) maxDim / (float) height);
349 newWidth = (int) (width * resizeRatio);
350 } else {
351 newWidth = maxDim;
352 final float resizeRatio = ((float) maxDim / (float) width);
353 newHeight = (int) (height * resizeRatio);
354 }
355
356 zoomInplace(image, newWidth, newHeight, filterf);
357
358 return image;
359 }
360
361
362
363
364
365
366
367
368
369
370
371
372
373 public static FImage resizeMaxArea(FImage image, int maxArea, ResizeFilterFunction filterf) {
374 final int width = image.width;
375 final int height = image.height;
376 final int area = width * height;
377
378 if (area < maxArea) {
379 return image;
380 } else {
381 final double whRatio = (double) width / (double) height;
382 final int newWidth = (int) Math.sqrt(maxArea * whRatio);
383 final int newHeight = (int) (newWidth / whRatio);
384
385 zoomInplace(image, newWidth, newHeight, filterf);
386
387 return image;
388 }
389 }
390
391
392
393
394
395
396
397
398
399
400
401 public static FImage resizeMax(FImage image, int maxDim) {
402 final int width = image.width;
403 final int height = image.height;
404
405 int newWidth, newHeight;
406 if (width < maxDim && height < maxDim) {
407 return image;
408 } else if (width < height) {
409 newHeight = maxDim;
410 final float resizeRatio = ((float) maxDim / (float) height);
411 newWidth = (int) (width * resizeRatio);
412 } else {
413 newWidth = maxDim;
414 final float resizeRatio = ((float) maxDim / (float) width);
415 newHeight = (int) (height * resizeRatio);
416 }
417
418 zoomInplace(image, newWidth, newHeight);
419
420 return image;
421 }
422
423
424
425
426
427
428
429
430
431
432
433 public static FImage resizeMaxArea(FImage image, int maxArea) {
434 return resizeMaxArea(image, maxArea, DEFAULT_FILTER);
435 }
436
437
438
439
440
441
442
443
444
445
446
447 public static <I extends Image<?, I> & SinglebandImageProcessor.Processable<Float, FImage, I>> I doubleSize(I image) {
448 return image.process(new ResizeProcessor(Mode.DOUBLE));
449 }
450
451
452
453
454
455
456
457
458 public static FImage doubleSize(FImage image) {
459 int nheight, nwidth;
460 float im[][], tmp[][];
461 FImage newimage;
462
463 nheight = 2 * image.height - 2;
464 nwidth = 2 * image.width - 2;
465 newimage = new FImage(nwidth, nheight);
466 im = image.pixels;
467 tmp = newimage.pixels;
468
469 for (int y = 0; y < image.height - 1; y++) {
470 for (int x = 0; x < image.width - 1; x++) {
471 final int y2 = 2 * y;
472 final int x2 = 2 * x;
473 tmp[y2][x2] = im[y][x];
474 tmp[y2 + 1][x2] = 0.5f * (im[y][x] + im[y + 1][x]);
475 tmp[y2][x2 + 1] = 0.5f * (im[y][x] + im[y][x + 1]);
476 tmp[y2 + 1][x2 + 1] = 0.25f * (im[y][x] + im[y + 1][x] + im[y][x + 1] + im[y + 1][x + 1]);
477 }
478 }
479 return newimage;
480 }
481
482 protected static void internalDoubleSize(FImage image) {
483 image.internalAssign(doubleSize(image));
484 }
485
486
487
488
489
490
491
492
493
494
495 public static <I extends Image<?, I> & SinglebandImageProcessor.Processable<Float, FImage, I>> I halfSize(I image) {
496 return image.process(new ResizeProcessor(Mode.HALF));
497 }
498
499
500
501
502
503
504
505
506
507
508 public static FImage halfSize(FImage image) {
509 int newheight, newwidth;
510 float im[][], tmp[][];
511 FImage newimage;
512
513 newheight = image.height / 2;
514 newwidth = image.width / 2;
515 newimage = new FImage(newwidth, newheight);
516 im = image.pixels;
517 tmp = newimage.pixels;
518
519 for (int y = 0, yi = 0; y < newheight; y++, yi += 2) {
520 for (int x = 0, xi = 0; x < newwidth; x++, xi += 2) {
521 tmp[y][x] = im[yi][xi];
522 }
523 }
524
525 return newimage;
526 }
527
528 protected static void internalHalfSize(FImage image) {
529 image.internalAssign(halfSize(image));
530 }
531
532
533
534
535
536
537
538
539
540
541
542
543 public static FImage resample(FImage in, int newX, int newY) {
544 return resample(in.clone(), newX, newY, false);
545 }
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564 public static FImage resample(FImage in, int newX, int newY, boolean aspect) {
565
566
567 int nx = newX;
568 int ny = newY;
569 if (aspect) {
570 if (ny > nx)
571 nx = (int) Math.round((in.width * ny) / (double) in.height);
572 else
573 ny = (int) Math.round((in.height * nx) / (double) in.width);
574 }
575
576 zoomInplace(in, nx, ny);
577 return in;
578 }
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599 public static FImage resample(FImage in, int newX, int newY, boolean aspect, ResizeFilterFunction filterf)
600 {
601
602
603 int nx = newX;
604 int ny = newY;
605 if (aspect) {
606 if (ny > nx)
607 nx = (int) Math.round((in.width * ny) / (double) in.height);
608 else
609 ny = (int) Math.round((in.height * nx) / (double) in.width);
610 }
611
612 zoomInplace(in, nx, ny, filterf);
613 return in;
614 }
615
616
617
618
619
620
621
622 static class PixelContribution {
623
624 int pixel;
625
626 double weight;
627 }
628
629
630
631
632
633
634
635 static class PixelContributions {
636 int numberOfContributors;
637
638 PixelContribution[] contributions;
639 }
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662 private static void calc_x_contrib(PixelContributions contribX, double xscale, double fwidth, int dstwidth,
663 int srcwidth, ResizeFilterFunction filterf, int i)
664 {
665 double width;
666 double fscale;
667 double center;
668 double weight;
669
670 if (xscale < 1.0) {
671
672 width = fwidth / xscale;
673 fscale = 1.0 / xscale;
674
675 if (width <= .5) {
676
677 width = .5 + 1.0e-6;
678 fscale = 1.0;
679 }
680
681 contribX.numberOfContributors = 0;
682 contribX.contributions = new PixelContribution[(int) (width * 2.0 + 1.0)];
683
684 center = i / xscale;
685 final int left = (int) Math.ceil(center - width);
686
687 final int right = (int) Math.floor(center + width);
688
689 double density = 0.0;
690
691 for (int j = left; j <= right; j++) {
692 weight = center - j;
693 weight = filterf.filter(weight / fscale) / fscale;
694 int n;
695 if (j < 0) {
696 n = -j;
697 }
698 else if (j >= srcwidth) {
699 n = (srcwidth - j) + srcwidth - 1;
700 }
701 else {
702 n = j;
703 }
704
705
706
707
708
709
710
711
712
713
714 final int k = contribX.numberOfContributors++;
715 contribX.contributions[k] = new PixelContribution();
716 contribX.contributions[k].pixel = n;
717 contribX.contributions[k].weight = weight;
718
719 density += weight;
720
721 }
722
723 if ((density != 0.0) && (density != 1.0)) {
724
725 density = 1.0 / density;
726 for (int k = 0; k < contribX.numberOfContributors; k++) {
727 contribX.contributions[k].weight *= density;
728 }
729 }
730 }
731 else {
732
733 contribX.numberOfContributors = 0;
734 contribX.contributions = new PixelContribution[(int) (fwidth * 2.0 + 1.0)];
735
736 center = i / xscale;
737 final int left = (int) Math.ceil(center - fwidth);
738 final int right = (int) Math.floor(center + fwidth);
739
740 for (int j = left; j <= right; j++) {
741 weight = center - j;
742 weight = filterf.filter(weight);
743
744 int n;
745 if (j < 0) {
746 n = -j;
747 }
748 else if (j >= srcwidth) {
749 n = (srcwidth - j) + srcwidth - 1;
750 }
751 else {
752 n = j;
753 }
754
755
756
757
758
759
760
761
762
763
764 final int k = contribX.numberOfContributors++;
765 contribX.contributions[k] = new PixelContribution();
766 contribX.contributions[k].pixel = n;
767 contribX.contributions[k].weight = weight;
768 }
769 }
770 }
771
772
773
774
775
776
777
778
779
780
781
782
783 public static FImage zoomInplace(FImage in, int newX, int newY) {
784 final ResizeFilterFunction filter = DEFAULT_FILTER;
785 return zoomInplace(in, newX, newY, filter);
786 }
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801 public static FImage zoomInplace(FImage in, int newX, int newY, ResizeFilterFunction filterf) {
802 final FImage dst = new FImage(newX, newY);
803 zoom(in, dst, filterf);
804 in.internalAssign(dst);
805 return in;
806 }
807
808
809
810
811
812
813
814
815
816
817
818
819
820 public static FImage zoom(FImage in, FImage dst, ResizeFilterFunction filterf) {
821 final int dstWidth = dst.getWidth();
822 final int dstHeight = dst.getHeight();
823
824 final int srcWidth = in.getWidth();
825 final int srcHeight = in.getHeight();
826
827 final double xscale = (double) dstWidth / (double) srcWidth;
828 final double yscale = (double) dstHeight / (double) srcHeight;
829
830
831 final float[] work = new float[in.height];
832
833 final PixelContributions[] contribY = new PixelContributions[dstHeight];
834 for (int i = 0; i < contribY.length; i++) {
835 contribY[i] = new PixelContributions();
836 }
837
838 final float maxValue = in.max();
839
840
841 final double fwidth = filterf.getSupport();
842 if (yscale < 1.0) {
843 double width = fwidth / yscale;
844 double fscale = 1.0 / yscale;
845
846 if (width <= .5) {
847
848 width = .5 + 1.0e-6;
849 fscale = 1.0;
850 }
851
852 for (int i = 0; i < dstHeight; i++) {
853 contribY[i].contributions = new PixelContribution[(int) (width * 2.0 + 1)];
854 contribY[i].numberOfContributors = 0;
855
856 final double center = i / yscale;
857 final int left = (int) Math.ceil(center - width);
858
859 final int right = left + contribY[i].contributions.length - 1;
860
861 double density = 0.0;
862 for (int j = left; j <= right; j++) {
863 double weight = center - j;
864 weight = filterf.filter(weight / fscale) / fscale;
865 int n;
866 if (j < 0) {
867 n = -j;
868 }
869 else if (j >= srcHeight) {
870 n = (srcHeight - j) + srcHeight - 1;
871 }
872 else {
873 n = j;
874 }
875
876
877
878
879
880
881
882
883
884
885 final int k = contribY[i].numberOfContributors++;
886 contribY[i].contributions[k] = new PixelContribution();
887 contribY[i].contributions[k].pixel = n;
888 contribY[i].contributions[k].weight = weight;
889
890 density += weight;
891 }
892
893 if ((density != 0.0) && (density != 1.0)) {
894
895 density = 1.0 / density;
896 for (int k = 0; k < contribY[i].numberOfContributors; k++) {
897 contribY[i].contributions[k].weight *= density;
898 }
899 }
900 }
901 }
902 else {
903 for (int i = 0; i < dstHeight; ++i) {
904 contribY[i].contributions = new PixelContribution[(int) (fwidth * 2 + 1)];
905 contribY[i].numberOfContributors = 0;
906
907 final double center = i / yscale;
908 final double left = Math.ceil(center - fwidth);
909
910 final double right = left + contribY[i].contributions.length - 1;
911 for (int j = (int) left; j <= right; ++j) {
912 double weight = center - j;
913 weight = filterf.filter(weight);
914 int n;
915 if (j < 0) {
916 n = -j;
917 }
918 else if (j >= srcHeight) {
919 n = (srcHeight - j) + srcHeight - 1;
920 }
921 else {
922 n = j;
923 }
924
925
926
927
928
929
930
931
932
933
934 final int k = contribY[i].numberOfContributors++;
935 contribY[i].contributions[k] = new PixelContribution();
936 contribY[i].contributions[k].pixel = n;
937 contribY[i].contributions[k].weight = weight;
938 }
939 }
940 }
941
942 for (int xx = 0; xx < dstWidth; xx++) {
943 final PixelContributions contribX = new PixelContributions();
944 calc_x_contrib(contribX, xscale, fwidth, dst.width, in.width, filterf, xx);
945
946
947 for (int k = 0; k < srcHeight; k++) {
948 double weight = 0.0;
949 boolean bPelDelta = false;
950
951
952 final double pel = in.pixels[k][contribX.contributions[0].pixel];
953 for (int j = 0; j < contribX.numberOfContributors; j++) {
954 final double pel2 = j == 0 ? pel : in.pixels[k][contribX.contributions[j].pixel];
955 if (pel2 != pel) {
956 bPelDelta = true;
957 }
958 weight += pel2 * contribX.contributions[j].weight;
959 }
960 weight = bPelDelta ? Math.round(weight * 255) / 255f : pel;
961
962 if (weight < 0) {
963 weight = 0;
964 }
965 else if (weight > maxValue) {
966 weight = maxValue;
967 }
968
969 work[k] = (float) weight;
970 }
971
972
973
974
975
976 for (int i = 0; i < dstHeight; i++) {
977 double weight = 0.0;
978 boolean bPelDelta = false;
979 final double pel = work[contribY[i].contributions[0].pixel];
980
981 for (int j = 0; j < contribY[i].numberOfContributors; j++) {
982
983
984 final double pel2 = j == 0 ? pel : work[contribY[i].contributions[j].pixel];
985 if (pel2 != pel) {
986 bPelDelta = true;
987 }
988 weight += pel2 * contribY[i].contributions[j].weight;
989 }
990 weight = bPelDelta ? Math.round(weight * 255) / 255f : pel;
991
992 if (weight < 0) {
993 weight = 0;
994 }
995 else if (weight > maxValue) {
996 weight = maxValue;
997 }
998
999 dst.pixels[i][xx] = (float) weight;
1000 }
1001 }
1002
1003 return dst;
1004 }
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020 public static FImage zoom(FImage in, Rectangle inRect, FImage dst, Rectangle dstRect) {
1021 return zoom(in, inRect, dst, dstRect, DEFAULT_FILTER);
1022 }
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040 public static FImage zoom(FImage in, Rectangle inRect, FImage dst, Rectangle dstRect, ResizeFilterFunction filterf)
1041 {
1042
1043 if (!in.getBounds().isInside(inRect) || !dst.getBounds().isInside(dstRect))
1044 throw new IllegalArgumentException("Bad bounds");
1045
1046 double xscale, yscale;
1047 int n;
1048 double center, left, right;
1049 double width, fscale;
1050 double weight;
1051 boolean bPelDelta;
1052 float pel, pel2;
1053 PixelContributions contribX;
1054
1055
1056 final FImage src = in;
1057 final int srcX = (int) inRect.x;
1058 final int srcY = (int) inRect.y;
1059 final int srcWidth = (int) inRect.width;
1060 final int srcHeight = (int) inRect.height;
1061
1062 final int dstX = (int) dstRect.x;
1063 final int dstY = (int) dstRect.y;
1064 final int dstWidth = (int) dstRect.width;
1065 final int dstHeight = (int) dstRect.height;
1066
1067 final float maxValue = in.max();
1068
1069
1070 final Float[] work = new Float[srcHeight];
1071
1072 xscale = (double) dstWidth / (double) srcWidth;
1073
1074
1075
1076 final PixelContributions[] contribY = new PixelContributions[dstHeight];
1077
1078 yscale = (double) dstHeight / (double) srcHeight;
1079 final double fwidth = filterf.getSupport();
1080
1081 if (yscale < 1.0) {
1082 width = fwidth / yscale;
1083 fscale = 1.0 / yscale;
1084 double density = 0;
1085 for (int i = 0; i < dstHeight; ++i) {
1086 contribY[i] = new PixelContributions();
1087 contribY[i].numberOfContributors = 0;
1088 contribY[i].contributions = new PixelContribution[(int) Math.round(width * 2 + 1)];
1089
1090 center = i / yscale;
1091 left = Math.ceil(center - width);
1092 right = Math.floor(center + width);
1093 for (int j = (int) left; j <= right; ++j) {
1094 weight = center - j;
1095 weight = filterf.filter(weight / fscale) / fscale;
1096
1097 if (j < 0) {
1098 n = -j;
1099 } else if (j >= srcHeight) {
1100 n = (srcHeight - j) + srcHeight - 1;
1101 } else {
1102 n = j;
1103 }
1104
1105 final int k = contribY[i].numberOfContributors++;
1106 contribY[i].contributions[k] = new PixelContribution();
1107 contribY[i].contributions[k].pixel = n;
1108 contribY[i].contributions[k].weight = weight;
1109 density += weight;
1110 }
1111
1112 if ((density != 0.0) && (density != 1.0)) {
1113
1114 density = 1.0 / density;
1115 for (int k = 0; k < contribY[i].numberOfContributors; k++) {
1116 contribY[i].contributions[k].weight *= density;
1117 }
1118 }
1119 }
1120 } else {
1121 for (int i = 0; i < dstHeight; ++i) {
1122 contribY[i] = new PixelContributions();
1123 contribY[i].numberOfContributors = 0;
1124 contribY[i].contributions = new PixelContribution[(int) Math.round(fwidth * 2 + 1)];
1125
1126 center = i / yscale;
1127 left = Math.ceil(center - fwidth);
1128 right = Math.floor(center + fwidth);
1129 for (int j = (int) left; j <= right; ++j) {
1130 weight = center - j;
1131 weight = filterf.filter(weight);
1132
1133 if (j < 0) {
1134 n = -j;
1135 } else if (j >= srcHeight) {
1136 n = (srcHeight - j) + srcHeight - 1;
1137 } else {
1138 n = j;
1139 }
1140
1141 final int k = contribY[i].numberOfContributors++;
1142 contribY[i].contributions[k] = new PixelContribution();
1143 contribY[i].contributions[k].pixel = n;
1144 contribY[i].contributions[k].weight = weight;
1145 }
1146 }
1147 }
1148
1149 for (int xx = 0; xx < dstWidth; xx++) {
1150 contribX = new PixelContributions();
1151 calc_x_contrib(contribX, xscale, fwidth, dstWidth, srcWidth, filterf, xx);
1152
1153
1154 for (int k = 0; k < srcHeight; ++k) {
1155 weight = 0.0;
1156 bPelDelta = false;
1157
1158 pel = src.pixels[k + srcY][contribX.contributions[0].pixel + srcX];
1159
1160 for (int j = 0; j < contribX.numberOfContributors; ++j) {
1161 pel2 = src.pixels[k + srcY][contribX.contributions[j].pixel + srcX];
1162 if (pel2 != pel)
1163 bPelDelta = true;
1164 weight += pel2 * contribX.contributions[j].weight;
1165 }
1166 weight = bPelDelta ? Math.round(weight * 255f) / 255f : pel;
1167
1168 if (weight < 0) {
1169 weight = 0;
1170 }
1171 else if (weight > maxValue) {
1172 weight = maxValue;
1173 }
1174
1175 work[k] = (float) weight;
1176 }
1177
1178
1179
1180
1181
1182 for (int i = 0; i < dstHeight; ++i) {
1183 weight = 0.0;
1184 bPelDelta = false;
1185 pel = work[contribY[i].contributions[0].pixel];
1186
1187 for (int j = 0; j < contribY[i].numberOfContributors; ++j) {
1188 pel2 = work[contribY[i].contributions[j].pixel];
1189 if (pel2 != pel)
1190 bPelDelta = true;
1191 weight += pel2 * contribY[i].contributions[j].weight;
1192 }
1193
1194 weight = bPelDelta ? Math.round(weight * 255f) / 255f : pel;
1195
1196 if (weight < 0) {
1197 weight = 0;
1198 }
1199 else if (weight > maxValue) {
1200 weight = maxValue;
1201 }
1202
1203 dst.pixels[i + dstY][xx + dstX] = (float) weight;
1204
1205 }
1206 }
1207
1208 return dst;
1209 }
1210 }