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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
package jogamp.opengl.util.pngj;
import jogamp.opengl.util.pngj.ImageLine.SampleType;
/**
* Wraps in a matrix a set of image rows, not necessarily contiguous - but equispaced.
*
* The fields mirrors those of {@link ImageLine}, and you can access each row as a ImageLine backed by the matrix row,
* see {@link #getImageLineAtMatrixRow(int)}
*/
public class ImageLines {
public final ImageInfo imgInfo;
public final int channels;
public final int bitDepth;
public final SampleType sampleType;
public final boolean samplesUnpacked;
public final int elementsPerRow;
public final int rowOffset;
public final int nRows;
public final int rowStep;
public final int[][] scanlines;
public final byte[][] scanlinesb;
/**
* Allocates a matrix to store {@code nRows} image rows. See {@link ImageLine} and {@link PngReader#readRowsInt()}
* {@link PngReader#readRowsByte()}
*
* @param imgInfo
* @param stype
* @param unpackedMode
* @param rowOffset
* @param nRows
* @param rowStep
*/
public ImageLines(ImageInfo imgInfo, SampleType stype, boolean unpackedMode, int rowOffset, int nRows, int rowStep) {
this.imgInfo = imgInfo;
channels = imgInfo.channels;
bitDepth = imgInfo.bitDepth;
this.sampleType = stype;
this.samplesUnpacked = unpackedMode || !imgInfo.packed;
elementsPerRow = unpackedMode ? imgInfo.samplesPerRow : imgInfo.samplesPerRowPacked;
this.rowOffset = rowOffset;
this.nRows = nRows;
this.rowStep = rowStep;
if (stype == SampleType.INT) {
scanlines = new int[nRows][elementsPerRow];
scanlinesb = null;
} else if (stype == SampleType.BYTE) {
scanlinesb = new byte[nRows][elementsPerRow];
scanlines = null;
} else
throw new PngjExceptionInternal("bad ImageLine initialization");
}
/**
* Warning: this always returns a valid matrix row (clamping on 0 : nrows-1, and rounding down) Eg:
* rowOffset=4,rowStep=2 imageRowToMatrixRow(17) returns 6 , imageRowToMatrixRow(1) returns 0
*/
public int imageRowToMatrixRow(int imrow) {
int r = (imrow - rowOffset) / rowStep;
return r < 0 ? 0 : (r < nRows ? r : nRows - 1);
}
/**
* Same as imageRowToMatrixRow, but returns negative if invalid
*/
public int imageRowToMatrixRowStrict(int imrow) {
imrow -= rowOffset;
int mrow = imrow >= 0 && imrow % rowStep == 0 ? imrow / rowStep : -1;
return mrow < nRows ? mrow : -1;
}
/**
* Converts from matrix row number (0 : nRows-1) to image row number
*
* @param mrow
* Matrix row number
* @return Image row number. Invalid only if mrow is invalid
*/
public int matrixRowToImageRow(int mrow) {
return mrow * rowStep + rowOffset;
}
/**
* Returns a ImageLine is backed by the matrix, no allocation done
*
* @param mrow
* Matrix row, from 0 to nRows This is not necessarily the image row, see
* {@link #imageRowToMatrixRow(int)} and {@link #matrixRowToImageRow(int)}
* @return A new ImageLine, backed by the matrix, with the correct ('real') rownumber
*/
public ImageLine getImageLineAtMatrixRow(int mrow) {
if (mrow < 0 || mrow > nRows)
throw new PngjException("Bad row " + mrow + ". Should be positive and less than " + nRows);
ImageLine imline = sampleType == SampleType.INT ? new ImageLine(imgInfo, sampleType, samplesUnpacked,
scanlines[mrow], null) : new ImageLine(imgInfo, sampleType, samplesUnpacked, null, scanlinesb[mrow]);
imline.setRown(matrixRowToImageRow(mrow));
return imline;
}
}
|