Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/share/classes/javax/imageio/IIOParam.java
41152 views
1
/*
2
* Copyright (c) 2000, 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
23
* questions.
24
*/
25
26
package javax.imageio;
27
28
import java.awt.Point;
29
import java.awt.Rectangle;
30
31
/**
32
* A superclass of all classes describing how streams should be
33
* decoded or encoded. This class contains all the variables and
34
* methods that are shared by {@code ImageReadParam} and
35
* {@code ImageWriteParam}.
36
*
37
* <p> This class provides mechanisms to specify a source region and a
38
* destination region. When reading, the source is the stream and
39
* the in-memory image is the destination. When writing, these are
40
* reversed. In the case of writing, destination regions may be used
41
* only with a writer that supports pixel replacement.
42
* <p>
43
* Decimation subsampling may be specified for both readers
44
* and writers, using a movable subsampling grid.
45
* <p>
46
* Subsets of the source and destination bands may be selected.
47
*
48
*/
49
public abstract class IIOParam {
50
51
/**
52
* The source region, on {@code null} if none is set.
53
*/
54
protected Rectangle sourceRegion = null;
55
56
/**
57
* The decimation subsampling to be applied in the horizontal
58
* direction. By default, the value is {@code 1}.
59
* The value must not be negative or 0.
60
*/
61
protected int sourceXSubsampling = 1;
62
63
/**
64
* The decimation subsampling to be applied in the vertical
65
* direction. By default, the value is {@code 1}.
66
* The value must not be negative or 0.
67
*/
68
protected int sourceYSubsampling = 1;
69
70
/**
71
* A horizontal offset to be applied to the subsampling grid before
72
* subsampling. The first pixel to be used will be offset this
73
* amount from the origin of the region, or of the image if no
74
* region is specified.
75
*/
76
protected int subsamplingXOffset = 0;
77
78
/**
79
* A vertical offset to be applied to the subsampling grid before
80
* subsampling. The first pixel to be used will be offset this
81
* amount from the origin of the region, or of the image if no
82
* region is specified.
83
*/
84
protected int subsamplingYOffset = 0;
85
86
/**
87
* An array of {@code int}s indicating which source bands
88
* will be used, or {@code null}. If {@code null}, the
89
* set of source bands to be used is as described in the comment
90
* for the {@code setSourceBands} method. No value should
91
* be allowed to be negative.
92
*/
93
protected int[] sourceBands = null;
94
95
/**
96
* An {@code ImageTypeSpecifier} to be used to generate a
97
* destination image when reading, or to set the output color type
98
* when writing. If non has been set the value will be
99
* {@code null}. By default, the value is {@code null}.
100
*/
101
protected ImageTypeSpecifier destinationType = null;
102
103
/**
104
* The offset in the destination where the upper-left decoded
105
* pixel should be placed. By default, the value is (0, 0).
106
*/
107
protected Point destinationOffset = new Point(0, 0);
108
109
/**
110
* The default {@code IIOParamController} that will be
111
* used to provide settings for this {@code IIOParam}
112
* object when the {@code activateController} method
113
* is called. This default should be set by subclasses
114
* that choose to provide their own default controller,
115
* usually a GUI, for setting parameters.
116
*
117
* @see IIOParamController
118
* @see #getDefaultController
119
* @see #activateController
120
*/
121
protected IIOParamController defaultController = null;
122
123
/**
124
* The {@code IIOParamController} that will be
125
* used to provide settings for this {@code IIOParam}
126
* object when the {@code activateController} method
127
* is called. This value overrides any default controller,
128
* even when null.
129
*
130
* @see IIOParamController
131
* @see #setController(IIOParamController)
132
* @see #hasController()
133
* @see #activateController()
134
*/
135
protected IIOParamController controller = null;
136
137
/**
138
* Protected constructor may be called only by subclasses.
139
*/
140
protected IIOParam() {
141
controller = defaultController;
142
}
143
144
/**
145
* Sets the source region of interest. The region of interest is
146
* described as a rectangle, with the upper-left corner of the
147
* source image as pixel (0, 0) and increasing values down and to
148
* the right. The actual number of pixels used will depend on
149
* the subsampling factors set by {@code setSourceSubsampling}.
150
* If subsampling has been set such that this number is zero,
151
* an {@code IllegalStateException} will be thrown.
152
*
153
* <p> The source region of interest specified by this method will
154
* be clipped as needed to fit within the source bounds, as well
155
* as the destination offsets, width, and height at the time of
156
* actual I/O.
157
*
158
* <p> A value of {@code null} for {@code sourceRegion}
159
* will remove any region specification, causing the entire image
160
* to be used.
161
*
162
* @param sourceRegion a {@code Rectangle} specifying the
163
* source region of interest, or {@code null}.
164
*
165
* @exception IllegalArgumentException if
166
* {@code sourceRegion} is non-{@code null} and either
167
* {@code sourceRegion.x} or {@code sourceRegion.y} is
168
* negative.
169
* @exception IllegalArgumentException if
170
* {@code sourceRegion} is non-{@code null} and either
171
* {@code sourceRegion.width} or
172
* {@code sourceRegion.height} is negative or 0.
173
* @exception IllegalStateException if subsampling is such that
174
* this region will have a subsampled width or height of zero.
175
*
176
* @see #getSourceRegion
177
* @see #setSourceSubsampling
178
* @see ImageReadParam#setDestinationOffset
179
* @see ImageReadParam#getDestinationOffset
180
*/
181
public void setSourceRegion(Rectangle sourceRegion) {
182
if (sourceRegion == null) {
183
this.sourceRegion = null;
184
return;
185
}
186
187
if (sourceRegion.x < 0) {
188
throw new IllegalArgumentException("sourceRegion.x < 0!");
189
}
190
if (sourceRegion.y < 0){
191
throw new IllegalArgumentException("sourceRegion.y < 0!");
192
}
193
if (sourceRegion.width <= 0) {
194
throw new IllegalArgumentException("sourceRegion.width <= 0!");
195
}
196
if (sourceRegion.height <= 0) {
197
throw new IllegalArgumentException("sourceRegion.height <= 0!");
198
}
199
200
// Throw an IllegalStateException if region falls between subsamples
201
if (sourceRegion.width <= subsamplingXOffset) {
202
throw new IllegalStateException
203
("sourceRegion.width <= subsamplingXOffset!");
204
}
205
if (sourceRegion.height <= subsamplingYOffset) {
206
throw new IllegalStateException
207
("sourceRegion.height <= subsamplingYOffset!");
208
}
209
210
this.sourceRegion = (Rectangle)sourceRegion.clone();
211
}
212
213
/**
214
* Returns the source region to be used. The returned value is
215
* that set by the most recent call to
216
* {@code setSourceRegion}, and will be {@code null} if
217
* there is no region set.
218
*
219
* @return the source region of interest as a
220
* {@code Rectangle}, or {@code null}.
221
*
222
* @see #setSourceRegion
223
*/
224
public Rectangle getSourceRegion() {
225
if (sourceRegion == null) {
226
return null;
227
}
228
return (Rectangle)sourceRegion.clone();
229
}
230
231
/**
232
* Specifies a decimation subsampling to apply on I/O. The
233
* {@code sourceXSubsampling} and
234
* {@code sourceYSubsampling} parameters specify the
235
* subsampling period (<i>i.e.</i>, the number of rows and columns
236
* to advance after every source pixel). Specifically, a period of
237
* 1 will use every row or column; a period of 2 will use every
238
* other row or column. The {@code subsamplingXOffset} and
239
* {@code subsamplingYOffset} parameters specify an offset
240
* from the region (or image) origin for the first subsampled pixel.
241
* Adjusting the origin of the subsample grid is useful for avoiding
242
* seams when subsampling a very large source image into destination
243
* regions that will be assembled into a complete subsampled image.
244
* Most users will want to simply leave these parameters at 0.
245
*
246
* <p> The number of pixels and scanlines to be used are calculated
247
* as follows.
248
* <p>
249
* The number of subsampled pixels in a scanline is given by
250
* <p>
251
* {@code truncate[(width - subsamplingXOffset + sourceXSubsampling - 1)
252
* / sourceXSubsampling]}.
253
* <p>
254
* If the region is such that this width is zero, an
255
* {@code IllegalStateException} is thrown.
256
* <p>
257
* The number of scanlines to be used can be computed similarly.
258
*
259
* <p>The ability to set the subsampling grid to start somewhere
260
* other than the source region origin is useful if the
261
* region is being used to create subsampled tiles of a large image,
262
* where the tile width and height are not multiples of the
263
* subsampling periods. If the subsampling grid does not remain
264
* consistent from tile to tile, there will be artifacts at the tile
265
* boundaries. By adjusting the subsampling grid offset for each
266
* tile to compensate, these artifacts can be avoided. The tradeoff
267
* is that in order to avoid these artifacts, the tiles are not all
268
* the same size. The grid offset to use in this case is given by:
269
* <br>
270
* grid offset = [period - (region offset modulo period)] modulo period)
271
*
272
* <p> If either {@code sourceXSubsampling} or
273
* {@code sourceYSubsampling} is 0 or negative, an
274
* {@code IllegalArgumentException} will be thrown.
275
*
276
* <p> If either {@code subsamplingXOffset} or
277
* {@code subsamplingYOffset} is negative or greater than or
278
* equal to the corresponding period, an
279
* {@code IllegalArgumentException} will be thrown.
280
*
281
* <p> There is no {@code unsetSourceSubsampling} method;
282
* simply call {@code setSourceSubsampling(1, 1, 0, 0)} to
283
* restore default values.
284
*
285
* @param sourceXSubsampling the number of columns to advance
286
* between pixels.
287
* @param sourceYSubsampling the number of rows to advance between
288
* pixels.
289
* @param subsamplingXOffset the horizontal offset of the first subsample
290
* within the region, or within the image if no region is set.
291
* @param subsamplingYOffset the horizontal offset of the first subsample
292
* within the region, or within the image if no region is set.
293
* @exception IllegalArgumentException if either period is
294
* negative or 0, or if either grid offset is negative or greater than
295
* the corresponding period.
296
* @exception IllegalStateException if the source region is such that
297
* the subsampled output would contain no pixels.
298
*/
299
public void setSourceSubsampling(int sourceXSubsampling,
300
int sourceYSubsampling,
301
int subsamplingXOffset,
302
int subsamplingYOffset) {
303
if (sourceXSubsampling <= 0) {
304
throw new IllegalArgumentException("sourceXSubsampling <= 0!");
305
}
306
if (sourceYSubsampling <= 0) {
307
throw new IllegalArgumentException("sourceYSubsampling <= 0!");
308
}
309
if (subsamplingXOffset < 0 ||
310
subsamplingXOffset >= sourceXSubsampling) {
311
throw new IllegalArgumentException
312
("subsamplingXOffset out of range!");
313
}
314
if (subsamplingYOffset < 0 ||
315
subsamplingYOffset >= sourceYSubsampling) {
316
throw new IllegalArgumentException
317
("subsamplingYOffset out of range!");
318
}
319
320
// Throw an IllegalStateException if region falls between subsamples
321
if (sourceRegion != null) {
322
if (subsamplingXOffset >= sourceRegion.width ||
323
subsamplingYOffset >= sourceRegion.height) {
324
throw new IllegalStateException("region contains no pixels!");
325
}
326
}
327
328
this.sourceXSubsampling = sourceXSubsampling;
329
this.sourceYSubsampling = sourceYSubsampling;
330
this.subsamplingXOffset = subsamplingXOffset;
331
this.subsamplingYOffset = subsamplingYOffset;
332
}
333
334
/**
335
* Returns the number of source columns to advance for each pixel.
336
*
337
* <p>If {@code setSourceSubsampling} has not been called, 1
338
* is returned (which is the correct value).
339
*
340
* @return the source subsampling X period.
341
*
342
* @see #setSourceSubsampling
343
* @see #getSourceYSubsampling
344
*/
345
public int getSourceXSubsampling() {
346
return sourceXSubsampling;
347
}
348
349
/**
350
* Returns the number of rows to advance for each pixel.
351
*
352
* <p>If {@code setSourceSubsampling} has not been called, 1
353
* is returned (which is the correct value).
354
*
355
* @return the source subsampling Y period.
356
*
357
* @see #setSourceSubsampling
358
* @see #getSourceXSubsampling
359
*/
360
public int getSourceYSubsampling() {
361
return sourceYSubsampling;
362
}
363
364
/**
365
* Returns the horizontal offset of the subsampling grid.
366
*
367
* <p>If {@code setSourceSubsampling} has not been called, 0
368
* is returned (which is the correct value).
369
*
370
* @return the source subsampling grid X offset.
371
*
372
* @see #setSourceSubsampling
373
* @see #getSubsamplingYOffset
374
*/
375
public int getSubsamplingXOffset() {
376
return subsamplingXOffset;
377
}
378
379
/**
380
* Returns the vertical offset of the subsampling grid.
381
*
382
* <p>If {@code setSourceSubsampling} has not been called, 0
383
* is returned (which is the correct value).
384
*
385
* @return the source subsampling grid Y offset.
386
*
387
* @see #setSourceSubsampling
388
* @see #getSubsamplingXOffset
389
*/
390
public int getSubsamplingYOffset() {
391
return subsamplingYOffset;
392
}
393
394
/**
395
* Sets the indices of the source bands to be used. Duplicate
396
* indices are not allowed.
397
*
398
* <p> A {@code null} value indicates that all source bands
399
* will be used.
400
*
401
* <p> At the time of reading, an
402
* {@code IllegalArgumentException} will be thrown by the
403
* reader or writer if a value larger than the largest available
404
* source band index has been specified or if the number of source
405
* bands and destination bands to be used differ. The
406
* {@code ImageReader.checkReadParamBandSettings} method may
407
* be used to automate this test.
408
*
409
* <p> Semantically, a copy is made of the array; changes to the
410
* array contents subsequent to this call have no effect on
411
* this {@code IIOParam}.
412
*
413
* @param sourceBands an array of integer band indices to be
414
* used.
415
*
416
* @exception IllegalArgumentException if {@code sourceBands}
417
* contains a negative or duplicate value.
418
*
419
* @see #getSourceBands
420
* @see ImageReadParam#setDestinationBands
421
* @see ImageReader#checkReadParamBandSettings
422
*/
423
public void setSourceBands(int[] sourceBands) {
424
if (sourceBands == null) {
425
this.sourceBands = null;
426
} else {
427
int numBands = sourceBands.length;
428
for (int i = 0; i < numBands; i++) {
429
int band = sourceBands[i];
430
if (band < 0) {
431
throw new IllegalArgumentException("Band value < 0!");
432
}
433
for (int j = i + 1; j < numBands; j++) {
434
if (band == sourceBands[j]) {
435
throw new IllegalArgumentException("Duplicate band value!");
436
}
437
}
438
439
}
440
this.sourceBands = (sourceBands.clone());
441
}
442
}
443
444
/**
445
* Returns the set of source bands to be used. The returned
446
* value is that set by the most recent call to
447
* {@code setSourceBands}, or {@code null} if there have
448
* been no calls to {@code setSourceBands}.
449
*
450
* <p> Semantically, the array returned is a copy; changes to
451
* array contents subsequent to this call have no effect on this
452
* {@code IIOParam}.
453
*
454
* @return the set of source bands to be used, or
455
* {@code null}.
456
*
457
* @see #setSourceBands
458
*/
459
public int[] getSourceBands() {
460
if (sourceBands == null) {
461
return null;
462
}
463
return (sourceBands.clone());
464
}
465
466
/**
467
* Sets the desired image type for the destination image, using an
468
* {@code ImageTypeSpecifier}.
469
*
470
* <p> When reading, if the layout of the destination has been set
471
* using this method, each call to an {@code ImageReader}
472
* {@code read} method will return a new
473
* {@code BufferedImage} using the format specified by the
474
* supplied type specifier. As a side effect, any destination
475
* {@code BufferedImage} set by
476
* {@code ImageReadParam.setDestination(BufferedImage)} will
477
* no longer be set as the destination. In other words, this
478
* method may be thought of as calling
479
* {@code setDestination((BufferedImage)null)}.
480
*
481
* <p> When writing, the destination type maybe used to determine
482
* the color type of the image. The {@code SampleModel}
483
* information will be ignored, and may be {@code null}. For
484
* example, a 4-banded image could represent either CMYK or RGBA
485
* data. If a destination type is set, its
486
* {@code ColorModel} will override any
487
* {@code ColorModel} on the image itself. This is crucial
488
* when {@code setSourceBands} is used since the image's
489
* {@code ColorModel} will refer to the entire image rather
490
* than to the subset of bands being written.
491
*
492
* @param destinationType the {@code ImageTypeSpecifier} to
493
* be used to determine the destination layout and color type.
494
*
495
* @see #getDestinationType
496
*/
497
public void setDestinationType(ImageTypeSpecifier destinationType) {
498
this.destinationType = destinationType;
499
}
500
501
/**
502
* Returns the type of image to be returned by the read, if one
503
* was set by a call to
504
* {@code setDestination(ImageTypeSpecifier)}, as an
505
* {@code ImageTypeSpecifier}. If none was set,
506
* {@code null} is returned.
507
*
508
* @return an {@code ImageTypeSpecifier} describing the
509
* destination type, or {@code null}.
510
*
511
* @see #setDestinationType
512
*/
513
public ImageTypeSpecifier getDestinationType() {
514
return destinationType;
515
}
516
517
/**
518
* Specifies the offset in the destination image at which future
519
* decoded pixels are to be placed, when reading, or where a
520
* region will be written, when writing.
521
*
522
* <p> When reading, the region to be written within the
523
* destination {@code BufferedImage} will start at this
524
* offset and have a width and height determined by the source
525
* region of interest, the subsampling parameters, and the
526
* destination bounds.
527
*
528
* <p> Normal writes are not affected by this method, only writes
529
* performed using {@code ImageWriter.replacePixels}. For
530
* such writes, the offset specified is within the output stream
531
* image whose pixels are being modified.
532
*
533
* <p> There is no {@code unsetDestinationOffset} method;
534
* simply call {@code setDestinationOffset(new Point(0, 0))} to
535
* restore default values.
536
*
537
* @param destinationOffset the offset in the destination, as a
538
* {@code Point}.
539
*
540
* @exception IllegalArgumentException if
541
* {@code destinationOffset} is {@code null}.
542
*
543
* @see #getDestinationOffset
544
* @see ImageWriter#replacePixels
545
*/
546
public void setDestinationOffset(Point destinationOffset) {
547
if (destinationOffset == null) {
548
throw new IllegalArgumentException("destinationOffset == null!");
549
}
550
this.destinationOffset = (Point)destinationOffset.clone();
551
}
552
553
/**
554
* Returns the offset in the destination image at which pixels are
555
* to be placed.
556
*
557
* <p> If {@code setDestinationOffsets} has not been called,
558
* a {@code Point} with zero X and Y values is returned
559
* (which is the correct value).
560
*
561
* @return the destination offset as a {@code Point}.
562
*
563
* @see #setDestinationOffset
564
*/
565
public Point getDestinationOffset() {
566
return (Point)destinationOffset.clone();
567
}
568
569
/**
570
* Sets the {@code IIOParamController} to be used
571
* to provide settings for this {@code IIOParam}
572
* object when the {@code activateController} method
573
* is called, overriding any default controller. If the
574
* argument is {@code null}, no controller will be
575
* used, including any default. To restore the default, use
576
* {@code setController(getDefaultController())}.
577
*
578
* @param controller An appropriate
579
* {@code IIOParamController}, or {@code null}.
580
*
581
* @see IIOParamController
582
* @see #getController
583
* @see #getDefaultController
584
* @see #hasController
585
* @see #activateController()
586
*/
587
public void setController(IIOParamController controller) {
588
this.controller = controller;
589
}
590
591
/**
592
* Returns whatever {@code IIOParamController} is currently
593
* installed. This could be the default if there is one,
594
* {@code null}, or the argument of the most recent call
595
* to {@code setController}.
596
*
597
* @return the currently installed
598
* {@code IIOParamController}, or {@code null}.
599
*
600
* @see IIOParamController
601
* @see #setController
602
* @see #getDefaultController
603
* @see #hasController
604
* @see #activateController()
605
*/
606
public IIOParamController getController() {
607
return controller;
608
}
609
610
/**
611
* Returns the default {@code IIOParamController}, if there
612
* is one, regardless of the currently installed controller. If
613
* there is no default controller, returns {@code null}.
614
*
615
* @return the default {@code IIOParamController}, or
616
* {@code null}.
617
*
618
* @see IIOParamController
619
* @see #setController(IIOParamController)
620
* @see #getController
621
* @see #hasController
622
* @see #activateController()
623
*/
624
public IIOParamController getDefaultController() {
625
return defaultController;
626
}
627
628
/**
629
* Returns {@code true} if there is a controller installed
630
* for this {@code IIOParam} object. This will return
631
* {@code true} if {@code getController} would not
632
* return {@code null}.
633
*
634
* @return {@code true} if a controller is installed.
635
*
636
* @see IIOParamController
637
* @see #setController(IIOParamController)
638
* @see #getController
639
* @see #getDefaultController
640
* @see #activateController()
641
*/
642
public boolean hasController() {
643
return (controller != null);
644
}
645
646
/**
647
* Activates the installed {@code IIOParamController} for
648
* this {@code IIOParam} object and returns the resulting
649
* value. When this method returns {@code true}, all values
650
* for this {@code IIOParam} object will be ready for the
651
* next read or write operation. If {@code false} is
652
* returned, no settings in this object will have been disturbed
653
* (<i>i.e.</i>, the user canceled the operation).
654
*
655
* <p> Ordinarily, the controller will be a GUI providing a user
656
* interface for a subclass of {@code IIOParam} for a
657
* particular plug-in. Controllers need not be GUIs, however.
658
*
659
* @return {@code true} if the controller completed normally.
660
*
661
* @exception IllegalStateException if there is no controller
662
* currently installed.
663
*
664
* @see IIOParamController
665
* @see #setController(IIOParamController)
666
* @see #getController
667
* @see #getDefaultController
668
* @see #hasController
669
*/
670
public boolean activateController() {
671
if (!hasController()) {
672
throw new IllegalStateException("hasController() == false!");
673
}
674
return getController().activate(this);
675
}
676
}
677
678