package br.com.etyllica.loader.image; /** * PCX Image loader * * include ported C code from: * * PCXLoad * Author : Mustata Bogdan (LoneRunner) * Contact : lonerunner@planetquake.com (e-mail don't exist anymore) * * @author Michele Marcon * * * Updated by yuripourre to work with Etyllica Engine * * This code had a minor bug and didn't open images smaller than 256x256 pixels. * * I talked to a homonymous (Michele Marcon) who might be the owner. * * See the e-mails below: * * 2013/3/21 Yuri Pourre <yuripourre@gmail.com> * * Hi Michele, * * I found a PCX Image Loader on Internet(sorry, I lost the link) and the author identify yourself just with Michele Marcon. * * I want to publish it under LGPL. So I'm looking for the authors. * * Reply me please. * * * Best Regards * * Yuri * * * 2013/3/22 Michele Marcon <michelemarcon77@gmail.com> * * How did you get my email? * * Well, I remember that about 10 or more years ago I did convert some C code to Java for importing Quake models... but a lot of time has passed, and I don't even remember if I finished the work and what I did with it. :( * * I probably am the author but I'm not sure... * * However, I'm not against publishing it under LGPL. * * * 2013/3/22 Yuri Pourre <yuripourre@gmail.com> * * Hi, * * I found your e-mail on google code, don't ask me how. Was a blind shot. * * I'm developing a Java Game Engine since 2009 http://yuripourre.github.com/etyllica/ * * If you want to be assure I am attaching the class with few modifications, I lost the original code, sorry. * * * Thank You for allow me to publish it as LGPL. * * Best Regards * * Yuri * * * 2013/3/25 Michele Marcon <michelemarcon77@gmail.com> * This code is probably mine, but again, I'm not 100% sure. * */ import java.awt.image.BufferedImage; import java.io.IOException; import java.io.InputStream; import java.net.URL; public class PCXReader implements ImageReader { private static class PCXHeader { private char manufacturer; private char version; private char encoding; private char bits_per_pixel; private short xmin,ymin,xmax,ymax; private short hres,vres; private int palette[]=new int[48]; private char reserved; private char color_planes; private short bytes_per_line; private short palette_type; private byte filler[]=new byte[58]; private byte[] data; PCXHeader(byte[] raw){ manufacturer=(char)raw[0]; version=(char)raw[1]; encoding=(char)raw[2]; bits_per_pixel=(char)raw[3]; xmin=(short)((raw[4]+(raw[5]<<8))&0xff); ymin=(short)((raw[6]+(raw[7]<<8))&0xff); xmax=(short)((raw[8]+(raw[9]<<8))&0xff); ymax=(short)((raw[10]+(raw[11]<<8))&0xff); hres=(short)((raw[12]+(raw[13]<<8))&0xff); vres=(short)((raw[14]+(raw[15]<<8))&0xff); for (int i = 0; i < 48; i++) palette[i]=(raw[16+i]&0xff); reserved=(char)raw[64]; color_planes=(char)raw[65]; bytes_per_line=(short)((raw[66]+(raw[67]<<8))&0xff); palette_type=(short)((raw[68]+(raw[69]<<8))&0xff); for (int i = 0; i < 58; i++) filler[i]=raw[70+i]; data=new byte[raw.length-128]; for (int i = 0; i < raw.length-128; i++) data[i]=raw[128+i]; } } public BufferedImage loadImage(URL url) throws IOException{ // // load the file // InputStream f = url.openStream(); int len=f.available(); byte[] buffer = new byte[len+1]; buffer[len] = 0; for (int i = 0; i < len; i++){ buffer[i] = (byte)f.read(); } f.close(); // // parse the PCX file // PCXHeader pcx = new PCXHeader(buffer); byte[] raw = pcx.data; if (pcx.manufacturer != 0x0a || pcx.version != 5 || pcx.encoding != 1 || pcx.bits_per_pixel != 8 || pcx.xmax >= 640 || pcx.ymax >= 480) { System.err.println("Bad pcx file "+ url); return null; } int palette[] = new int[768]; for (int i = 0; i < 768; i++){ if ((len-128-768+i)<pcx.data.length){ palette[i]=pcx.data[len-128-768+i]&0xff; } } int imageWidth = pcx.xmax+1; int imageHeight = pcx.ymax+1; int[] out = new int[(pcx.ymax+1) * (pcx.xmax+1)]; int[] pic = out; int[] pix = out; int pixcount = 0; int rawcount = 0; int dataByte, runLength; for (int y=0 ; y<= pcx.ymax ; y++, pixcount += pcx.xmax+1){ for (int x=0 ; x<=pcx.xmax ; ){ dataByte = raw[rawcount++]; if((dataByte & 0xC0) == 0xC0){ runLength = dataByte & 0x3F; dataByte = raw[rawcount++]; } else{ runLength = 1; } while(runLength-- > 0){ pix[pixcount+x++] = dataByte&0xff; } } } if (pic == null || palette == null){ return null; } byte[] imageData = new byte [(imageWidth+1)*(imageHeight+1)* 3]; //convert to rgb format for (int k=0; k<(imageWidth*imageHeight); k++) { imageData[k * 3] = (byte)palette[pic[k] * 3 ]; imageData[k * 3 + 1] = (byte)palette[pic[k] * 3 + 1]; imageData[k * 3 + 2] = (byte)palette[pic[k] * 3 + 2]; } //Convert to BufferedImage int pixel[] = new int[imageWidth*imageHeight*3]; int z=0; int w=0; for (int i = 0; i < imageWidth; i++){ for (int j = 0; j < imageHeight; j++){ pixel[z++]=(0xff<<24) |((imageData[w++]&0x00ff)<<16) |((imageData[w++]&0x0000ff)<<8) |((imageData[w++]&0x000000ff)); } } BufferedImage bimg = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_ARGB); bimg.setRGB(0, 0, imageWidth,imageHeight, pixel, 0,imageWidth); return bimg; } }