1 /*
2 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
127 * @param hints the specified {@code RenderingHints}, or
128 * {@code null}
129 */
130 public RescaleOp (float scaleFactor, float offset, RenderingHints hints) {
131 length = 1;
132 this.scaleFactors = new float[1];
133 this.offsets = new float[1];
134 this.scaleFactors[0] = scaleFactor;
135 this.offsets[0] = offset;
136 this.hints = hints;
137 }
138
139 /**
140 * Returns the scale factors in the given array. The array is also
141 * returned for convenience. If scaleFactors is null, a new array
142 * will be allocated.
143 * @param scaleFactors the array to contain the scale factors of
144 * this {@code RescaleOp}
145 * @return the scale factors of this {@code RescaleOp}.
146 */
147 public final float[] getScaleFactors (float scaleFactors[]) {
148 if (scaleFactors == null) {
149 return this.scaleFactors.clone();
150 }
151 System.arraycopy (this.scaleFactors, 0, scaleFactors, 0,
152 Math.min(this.scaleFactors.length,
153 scaleFactors.length));
154 return scaleFactors;
155 }
156
157 /**
158 * Returns the offsets in the given array. The array is also returned
159 * for convenience. If offsets is null, a new array
160 * will be allocated.
161 * @param offsets the array to contain the offsets of
162 * this {@code RescaleOp}
163 * @return the offsets of this {@code RescaleOp}.
164 */
165 public final float[] getOffsets(float offsets[]) {
166 if (offsets == null) {
167 return this.offsets.clone();
168 }
169
170 System.arraycopy (this.offsets, 0, offsets, 0,
171 Math.min(this.offsets.length, offsets.length));
172 return offsets;
173 }
174
175 /**
176 * Returns the number of scaling factors and offsets used in this
177 * RescaleOp.
178 * @return the number of scaling factors and offsets of this
179 * {@code RescaleOp}.
180 */
181 public final int getNumFactors() {
182 return length;
183 }
184
185
186 /**
187 * Creates a ByteLookupTable to implement the rescale.
188 * The table may have either a SHORT or BYTE input.
189 * @param nElems Number of elements the table is to have.
190 * This will generally be 256 for byte and
191 * 65536 for short.
192 */
193 private ByteLookupTable createByteLut(float scale[],
194 float off[],
195 int nBands,
196 int nElems) {
197
198 byte[][] lutData = new byte[nBands][nElems];
199 int band;
200
201 for (band=0; band<scale.length; band++) {
202 float bandScale = scale[band];
203 float bandOff = off[band];
204 byte[] bandLutData = lutData[band];
205 for (int i=0; i<nElems; i++) {
206 int val = (int)(i*bandScale + bandOff);
207 if ((val & 0xffffff00) != 0) {
208 if (val < 0) {
209 val = 0;
210 } else {
211 val = 255;
212 }
213 }
214 bandLutData[i] = (byte)val;
220 System.arraycopy(lutData[band-1], 0, lutData[band], 0, nElems);
221 band++;
222 }
223 if (nBands == 4 && band < nBands) {
224 byte[] bandLutData = lutData[band];
225 for (int i=0; i<nElems; i++) {
226 bandLutData[i] = (byte)i;
227 }
228 }
229
230 return new ByteLookupTable(0, lutData);
231 }
232
233 /**
234 * Creates a ShortLookupTable to implement the rescale.
235 * The table may have either a SHORT or BYTE input.
236 * @param nElems Number of elements the table is to have.
237 * This will generally be 256 for byte and
238 * 65536 for short.
239 */
240 private ShortLookupTable createShortLut(float scale[],
241 float off[],
242 int nBands,
243 int nElems) {
244
245 short[][] lutData = new short[nBands][nElems];
246 int band = 0;
247
248 for (band=0; band<scale.length; band++) {
249 float bandScale = scale[band];
250 float bandOff = off[band];
251 short[] bandLutData = lutData[band];
252 for (int i=0; i<nElems; i++) {
253 int val = (int)(i*bandScale + bandOff);
254 if ((val & 0xffff0000) != 0) {
255 if (val < 0) {
256 val = 0;
257 } else {
258 val = 65535;
259 }
260 }
261 bandLutData[i] = (short)val;
545 //
546 // Fall back to the slow code
547 //
548 if (scaleConst > 1) {
549 step = 1;
550 }
551
552 int sminX = src.getMinX();
553 int sY = src.getMinY();
554 int dminX = dst.getMinX();
555 int dY = dst.getMinY();
556 int sX;
557 int dX;
558
559 //
560 // Determine bits per band to determine maxval for clamps.
561 // The min is assumed to be zero.
562 // REMIND: This must change if we ever support signed data types.
563 //
564 int nbits;
565 int dstMax[] = new int[numBands];
566 int dstMask[] = new int[numBands];
567 SampleModel dstSM = dst.getSampleModel();
568 for (int z=0; z<numBands; z++) {
569 nbits = dstSM.getSampleSize(z);
570 dstMax[z] = (1 << nbits) - 1;
571 dstMask[z] = ~(dstMax[z]);
572 }
573
574 int val;
575 for (int y=0; y < height; y++, sY++, dY++) {
576 dX = dminX;
577 sX = sminX;
578 for (int x = 0; x < width; x++, sX++, dX++) {
579 // Get data for all bands at this x,y position
580 srcPix = src.getPixel(sX, sY, srcPix);
581 tidx = 0;
582 for (int z=0; z<numBands; z++, tidx += step) {
583 if ((scaleConst == 1 || scaleConst == 3) &&
584 (z == 3) && (numBands == 4)) {
585 val = srcPix[z];
586 } else {
|
1 /*
2 * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
127 * @param hints the specified {@code RenderingHints}, or
128 * {@code null}
129 */
130 public RescaleOp (float scaleFactor, float offset, RenderingHints hints) {
131 length = 1;
132 this.scaleFactors = new float[1];
133 this.offsets = new float[1];
134 this.scaleFactors[0] = scaleFactor;
135 this.offsets[0] = offset;
136 this.hints = hints;
137 }
138
139 /**
140 * Returns the scale factors in the given array. The array is also
141 * returned for convenience. If scaleFactors is null, a new array
142 * will be allocated.
143 * @param scaleFactors the array to contain the scale factors of
144 * this {@code RescaleOp}
145 * @return the scale factors of this {@code RescaleOp}.
146 */
147 public final float[] getScaleFactors (float[] scaleFactors) {
148 if (scaleFactors == null) {
149 return this.scaleFactors.clone();
150 }
151 System.arraycopy (this.scaleFactors, 0, scaleFactors, 0,
152 Math.min(this.scaleFactors.length,
153 scaleFactors.length));
154 return scaleFactors;
155 }
156
157 /**
158 * Returns the offsets in the given array. The array is also returned
159 * for convenience. If offsets is null, a new array
160 * will be allocated.
161 * @param offsets the array to contain the offsets of
162 * this {@code RescaleOp}
163 * @return the offsets of this {@code RescaleOp}.
164 */
165 public final float[] getOffsets(float[] offsets) {
166 if (offsets == null) {
167 return this.offsets.clone();
168 }
169
170 System.arraycopy (this.offsets, 0, offsets, 0,
171 Math.min(this.offsets.length, offsets.length));
172 return offsets;
173 }
174
175 /**
176 * Returns the number of scaling factors and offsets used in this
177 * RescaleOp.
178 * @return the number of scaling factors and offsets of this
179 * {@code RescaleOp}.
180 */
181 public final int getNumFactors() {
182 return length;
183 }
184
185
186 /**
187 * Creates a ByteLookupTable to implement the rescale.
188 * The table may have either a SHORT or BYTE input.
189 * @param nElems Number of elements the table is to have.
190 * This will generally be 256 for byte and
191 * 65536 for short.
192 */
193 private ByteLookupTable createByteLut(float[] scale,
194 float[] off,
195 int nBands,
196 int nElems) {
197
198 byte[][] lutData = new byte[nBands][nElems];
199 int band;
200
201 for (band=0; band<scale.length; band++) {
202 float bandScale = scale[band];
203 float bandOff = off[band];
204 byte[] bandLutData = lutData[band];
205 for (int i=0; i<nElems; i++) {
206 int val = (int)(i*bandScale + bandOff);
207 if ((val & 0xffffff00) != 0) {
208 if (val < 0) {
209 val = 0;
210 } else {
211 val = 255;
212 }
213 }
214 bandLutData[i] = (byte)val;
220 System.arraycopy(lutData[band-1], 0, lutData[band], 0, nElems);
221 band++;
222 }
223 if (nBands == 4 && band < nBands) {
224 byte[] bandLutData = lutData[band];
225 for (int i=0; i<nElems; i++) {
226 bandLutData[i] = (byte)i;
227 }
228 }
229
230 return new ByteLookupTable(0, lutData);
231 }
232
233 /**
234 * Creates a ShortLookupTable to implement the rescale.
235 * The table may have either a SHORT or BYTE input.
236 * @param nElems Number of elements the table is to have.
237 * This will generally be 256 for byte and
238 * 65536 for short.
239 */
240 private ShortLookupTable createShortLut(float[] scale,
241 float[] off,
242 int nBands,
243 int nElems) {
244
245 short[][] lutData = new short[nBands][nElems];
246 int band = 0;
247
248 for (band=0; band<scale.length; band++) {
249 float bandScale = scale[band];
250 float bandOff = off[band];
251 short[] bandLutData = lutData[band];
252 for (int i=0; i<nElems; i++) {
253 int val = (int)(i*bandScale + bandOff);
254 if ((val & 0xffff0000) != 0) {
255 if (val < 0) {
256 val = 0;
257 } else {
258 val = 65535;
259 }
260 }
261 bandLutData[i] = (short)val;
545 //
546 // Fall back to the slow code
547 //
548 if (scaleConst > 1) {
549 step = 1;
550 }
551
552 int sminX = src.getMinX();
553 int sY = src.getMinY();
554 int dminX = dst.getMinX();
555 int dY = dst.getMinY();
556 int sX;
557 int dX;
558
559 //
560 // Determine bits per band to determine maxval for clamps.
561 // The min is assumed to be zero.
562 // REMIND: This must change if we ever support signed data types.
563 //
564 int nbits;
565 int[] dstMax = new int[numBands];
566 int[] dstMask = new int[numBands];
567 SampleModel dstSM = dst.getSampleModel();
568 for (int z=0; z<numBands; z++) {
569 nbits = dstSM.getSampleSize(z);
570 dstMax[z] = (1 << nbits) - 1;
571 dstMask[z] = ~(dstMax[z]);
572 }
573
574 int val;
575 for (int y=0; y < height; y++, sY++, dY++) {
576 dX = dminX;
577 sX = sminX;
578 for (int x = 0; x < width; x++, sX++, dX++) {
579 // Get data for all bands at this x,y position
580 srcPix = src.getPixel(sX, sY, srcPix);
581 tidx = 0;
582 for (int z=0; z<numBands; z++, tidx += step) {
583 if ((scaleConst == 1 || scaleConst == 3) &&
584 (z == 3) && (numBands == 4)) {
585 val = srcPix[z];
586 } else {
|