/* * This file is part of the OdinMS Maple Story Server Copyright (C) 2008 ~ 2010 * Patrick Huy <patrick.huy@frz.cc> Matthias Butz <matze@odinms.de> Jan * Christian Meyer <vimes@odinms.de> * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU Affero General Public License version 3 as published by * the Free Software Foundation. You may not use, modify or distribute this * program under any other version of the GNU Affero General Public License. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more * details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package javastory.xml; import java.awt.Point; import java.awt.image.BufferedImage; import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.image.PixelInterleavedSampleModel; import java.awt.image.Raster; import java.awt.image.SampleModel; import java.awt.image.WritableRaster; import java.util.zip.DataFormatException; import java.util.zip.Inflater; import javastory.wz.WzCanvas; public class PngWzCanvas implements WzCanvas { private static final int[] ZAHLEN = new int[] { 2, 1, 0, 3 }; private final int height; private final int width; private final int dataLength; private final int format; private final byte[] data; public PngWzCanvas(final int width, final int height, final int dataLength, final int format, final byte[] data) { super(); this.height = height; this.width = width; this.dataLength = dataLength; this.format = format; this.data = data; } @Override public int getHeight() { return this.height; } @Override public int getWidth() { return this.width; } public int getFormat() { return this.format; } public byte[] getData() { return this.data; } @Override public BufferedImage getImage() { int sizeUncompressed = 0; int size8888 = 0; int maxWriteBuf = 2; int maxHeight = 3; byte[] writeBuf = new byte[maxWriteBuf]; switch (this.getFormat()) { case 1: case 513: sizeUncompressed = this.getHeight() * this.getWidth() * 4; break; case 2: sizeUncompressed = this.getHeight() * this.getWidth() * 8; break; case 517: sizeUncompressed = this.getHeight() * this.getWidth() / 128; break; } size8888 = this.getHeight() * this.getWidth() * 8; if (size8888 > maxWriteBuf) { maxWriteBuf = size8888; writeBuf = new byte[maxWriteBuf]; } if (this.getHeight() > maxHeight) { maxHeight = this.getHeight(); } final Inflater dec = new Inflater(); dec.setInput(this.getData(), 0, this.dataLength); int declen = 0; final byte[] uc = new byte[sizeUncompressed]; try { declen = dec.inflate(uc); } catch (final DataFormatException ex) { throw new RuntimeException("zlib fucks", ex); } dec.end(); // fuck the format if (this.getFormat() == 1) { for (int i = 0; i < sizeUncompressed; i++) { final byte low = (byte) (uc[i] & 0x0F); final byte high = (byte) (uc[i] & 0xF0); writeBuf[i << 1] = (byte) ((low << 4 | low) & 0xFF); writeBuf[(i << 1) + 1] = (byte) (high | high >>> 4 & 0xF); } } else if (this.getFormat() == 2) { writeBuf = uc; } else if (this.getFormat() == 513) { for (int i = 0; i < declen; i += 2) { final byte bBits = (byte) ((uc[i] & 0x1F) << 3); final byte gBits = (byte) ((uc[i + 1] & 0x07) << 5 | (uc[i] & 0xE0) >> 3); final byte rBits = (byte) (uc[i + 1] & 0xF8); writeBuf[i << 1] = (byte) (bBits | bBits >> 5); writeBuf[(i << 1) + 1] = (byte) (gBits | gBits >> 6); writeBuf[(i << 1) + 2] = (byte) (rBits | rBits >> 5); writeBuf[(i << 1) + 3] = (byte) 0xFF; } } else if (this.getFormat() == 517) { byte b = 0x00; int pixelIndex = 0; for (int i = 0; i < declen; i++) { for (int j = 0; j < 8; j++) { b = (byte) (((uc[i] & 0x01 << 7 - j) >> 7 - j) * 255); for (int k = 0; k < 16; k++) { pixelIndex = (i << 9) + (j << 6) + k * 2; writeBuf[pixelIndex] = b; writeBuf[pixelIndex + 1] = b; writeBuf[pixelIndex + 2] = b; writeBuf[pixelIndex + 3] = (byte) 0xFF; } } } } final DataBufferByte imgData = new DataBufferByte(writeBuf, sizeUncompressed); // SampleModel sm = new // PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE, c.getWidth(), // c.getHeight(), 4, c.getWidth() * 4, new int[] {2, 1, 0, 3}); final SampleModel sm = new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE, this.getWidth(), this.getHeight(), 4, this.getWidth() * 4, ZAHLEN); final WritableRaster imgRaster = Raster.createWritableRaster(sm, imgData, new Point(0, 0)); final BufferedImage aa = new BufferedImage(this.getWidth(), this.getHeight(), BufferedImage.TYPE_INT_ARGB); aa.setData(imgRaster); return aa; } }