📄 pngimage.java
字号:
return;
}
int bytesPerRow = (inputBands*passWidth*bitDepth + 7)/8;
byte[] curr = new byte[bytesPerRow];
byte[] prior = new byte[bytesPerRow];
// Decode the (sub)image row-by-row
int srcY, dstY;
for (srcY = 0, dstY = yOffset;
srcY < passHeight;
srcY++, dstY += yStep) {
// Read the filter type byte and a row of data
int filter = 0;
try {
filter = dataStream.read();
dataStream.readFully(curr, 0, bytesPerRow);
} catch (Exception e) {
// empty on purpose
}
switch (filter) {
case PNG_FILTER_NONE:
break;
case PNG_FILTER_SUB:
decodeSubFilter(curr, bytesPerRow, bytesPerPixel);
break;
case PNG_FILTER_UP:
decodeUpFilter(curr, prior, bytesPerRow);
break;
case PNG_FILTER_AVERAGE:
decodeAverageFilter(curr, prior, bytesPerRow, bytesPerPixel);
break;
case PNG_FILTER_PAETH:
decodePaethFilter(curr, prior, bytesPerRow, bytesPerPixel);
break;
default:
// Error -- uknown filter type
throw new RuntimeException("PNG filter unknown.");
}
processPixels(curr, xOffset, xStep, dstY, passWidth);
// Swap curr and prior
byte[] tmp = prior;
prior = curr;
curr = tmp;
}
}
void processPixels(byte curr[], int xOffset, int step, int y, int width) {
int srcX, dstX;
int out[] = getPixel(curr);
int sizes = 0;
switch (colorType) {
case 0:
case 3:
case 4:
sizes = 1;
break;
case 2:
case 6:
sizes = 3;
break;
}
if (image != null) {
dstX = xOffset;
int yStride = (sizes*this.width*(bitDepth == 16 ? 8 : bitDepth)+ 7)/8;
for (srcX = 0; srcX < width; srcX++) {
setPixel(image, out, inputBands * srcX, sizes, dstX, y, bitDepth, yStride);
dstX += step;
}
}
if (palShades) {
if ((colorType & 4) != 0) {
if (bitDepth == 16) {
for (int k = 0; k < width; ++k)
out[k * inputBands + sizes] >>>= 8;
}
int yStride = this.width;
dstX = xOffset;
for (srcX = 0; srcX < width; srcX++) {
setPixel(smask, out, inputBands * srcX + sizes, 1, dstX, y, 8, yStride);
dstX += step;
}
}
else { //colorType 3
int yStride = this.width;
int v[] = new int[1];
dstX = xOffset;
for (srcX = 0; srcX < width; srcX++) {
int idx = out[srcX];
if (idx < trans.length)
v[0] = trans[idx];
setPixel(smask, v, 0, 1, dstX, y, 8, yStride);
dstX += step;
}
}
}
else if (genBWMask) {
switch (colorType) {
case 3: {
int yStride = (this.width + 7) / 8;
int v[] = new int[1];
dstX = xOffset;
for (srcX = 0; srcX < width; srcX++) {
int idx = out[srcX];
if (idx < trans.length)
v[0] = (trans[idx] == 0 ? 1 : 0);
setPixel(smask, v, 0, 1, dstX, y, 1, yStride);
dstX += step;
}
break;
}
case 0: {
int yStride = (this.width + 7) / 8;
int v[] = new int[1];
dstX = xOffset;
for (srcX = 0; srcX < width; srcX++) {
int g = out[srcX];
v[0] = (g == transRedGray ? 1 : 0);
setPixel(smask, v, 0, 1, dstX, y, 1, yStride);
dstX += step;
}
break;
}
case 2: {
int yStride = (this.width + 7) / 8;
int v[] = new int[1];
dstX = xOffset;
for (srcX = 0; srcX < width; srcX++) {
int markRed = inputBands * srcX;
v[0] = (out[markRed] == transRedGray && out[markRed + 1] == transGreen
&& out[markRed + 2] == transBlue ? 1 : 0);
setPixel(smask, v, 0, 1, dstX, y, 1, yStride);
dstX += step;
}
break;
}
}
}
}
static int getPixel(byte image[], int x, int y, int bitDepth, int bytesPerRow) {
if (bitDepth == 8) {
int pos = bytesPerRow * y + x;
return image[pos] & 0xff;
}
else {
int pos = bytesPerRow * y + x / (8 / bitDepth);
int v = image[pos] >> (8 - bitDepth * (x % (8 / bitDepth))- bitDepth);
return v & ((1 << bitDepth) - 1);
}
}
static void setPixel(byte image[], int data[], int offset, int size, int x, int y, int bitDepth, int bytesPerRow) {
if (bitDepth == 8) {
int pos = bytesPerRow * y + size * x;
for (int k = 0; k < size; ++k)
image[pos + k] = (byte)data[k + offset];
}
else if (bitDepth == 16) {
int pos = bytesPerRow * y + size * x;
for (int k = 0; k < size; ++k)
image[pos + k] = (byte)(data[k + offset] >>> 8);
}
else {
int pos = bytesPerRow * y + x / (8 / bitDepth);
int v = data[offset] << (8 - bitDepth * (x % (8 / bitDepth))- bitDepth);
image[pos] |= v;
}
}
int[] getPixel(byte curr[]) {
switch (bitDepth) {
case 8: {
int out[] = new int[curr.length];
for (int k = 0; k < out.length; ++k)
out[k] = curr[k] & 0xff;
return out;
}
case 16: {
int out[] = new int[curr.length / 2];
for (int k = 0; k < out.length; ++k)
out[k] = ((curr[k * 2] & 0xff) << 8) + (curr[k * 2 + 1] & 0xff);
return out;
}
default: {
int out[] = new int[curr.length * 8 / bitDepth];
int idx = 0;
int passes = 8 / bitDepth;
int mask = (1 << bitDepth) - 1;
for (int k = 0; k < curr.length; ++k) {
for (int j = passes - 1; j >= 0; --j) {
out[idx++] = (curr[k] >>> (bitDepth * j)) & mask;
}
}
return out;
}
}
}
private static void decodeSubFilter(byte[] curr, int count, int bpp) {
for (int i = bpp; i < count; i++) {
int val;
val = curr[i] & 0xff;
val += curr[i - bpp] & 0xff;
curr[i] = (byte)val;
}
}
private static void decodeUpFilter(byte[] curr, byte[] prev,
int count) {
for (int i = 0; i < count; i++) {
int raw = curr[i] & 0xff;
int prior = prev[i] & 0xff;
curr[i] = (byte)(raw + prior);
}
}
private static void decodeAverageFilter(byte[] curr, byte[] prev,
int count, int bpp) {
int raw, priorPixel, priorRow;
for (int i = 0; i < bpp; i++) {
raw = curr[i] & 0xff;
priorRow = prev[i] & 0xff;
curr[i] = (byte)(raw + priorRow/2);
}
for (int i = bpp; i < count; i++) {
raw = curr[i] & 0xff;
priorPixel = curr[i - bpp] & 0xff;
priorRow = prev[i] & 0xff;
curr[i] = (byte)(raw + (priorPixel + priorRow)/2);
}
}
private static int paethPredictor(int a, int b, int c) {
int p = a + b - c;
int pa = Math.abs(p - a);
int pb = Math.abs(p - b);
int pc = Math.abs(p - c);
if ((pa <= pb) && (pa <= pc)) {
return a;
} else if (pb <= pc) {
return b;
} else {
return c;
}
}
private static void decodePaethFilter(byte[] curr, byte[] prev,
int count, int bpp) {
int raw, priorPixel, priorRow, priorRowPixel;
for (int i = 0; i < bpp; i++) {
raw = curr[i] & 0xff;
priorRow = prev[i] & 0xff;
curr[i] = (byte)(raw + priorRow);
}
for (int i = bpp; i < count; i++) {
raw = curr[i] & 0xff;
priorPixel = curr[i - bpp] & 0xff;
priorRow = prev[i] & 0xff;
priorRowPixel = prev[i - bpp] & 0xff;
curr[i] = (byte)(raw + paethPredictor(priorPixel,
priorRow,
priorRowPixel));
}
}
static class NewByteArrayOutputStream extends ByteArrayOutputStream {
public byte[] getBuf() {
return buf;
}
}
/**
* Gets an <CODE>int</CODE> from an <CODE>InputStream</CODE>.
*
* @param is an <CODE>InputStream</CODE>
* @return the value of an <CODE>int</CODE>
*/
public static final int getInt(InputStream is) throws IOException {
return (is.read() << 24) + (is.read() << 16) + (is.read() << 8) + is.read();
}
/**
* Gets a <CODE>word</CODE> from an <CODE>InputStream</CODE>.
*
* @param is an <CODE>InputStream</CODE>
* @return the value of an <CODE>int</CODE>
*/
public static final int getWord(InputStream is) throws IOException {
return (is.read() << 8) + is.read();
}
/**
* Gets a <CODE>String</CODE> from an <CODE>InputStream</CODE>.
*
* @param is an <CODE>InputStream</CODE>
* @return the value of an <CODE>int</CODE>
*/
public static final String getString(InputStream is) throws IOException {
StringBuffer buf = new StringBuffer();
for (int i = 0; i < 4; i++) {
buf.append((char)is.read());
}
return buf.toString();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -