mirror of
https://github.com/moparisthebest/davmail
synced 2025-01-07 11:48:02 -05:00
32bit icon jsmooth patch with alpha channel support
git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@135 3d1905a2-6b24-0410-a738-b14d5a86fcbd
This commit is contained in:
parent
ae8ca73c50
commit
b65e64c474
@ -0,0 +1,506 @@
|
|||||||
|
/*
|
||||||
|
JSmooth: a VM wrapper toolkit for Windows
|
||||||
|
Copyright (C) 2003 Rodrigo Reyes <reyes@charabia.net>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.charabia.jsmoothgen.application;
|
||||||
|
|
||||||
|
import net.charabia.jsmoothgen.skeleton.*;
|
||||||
|
import net.charabia.jsmoothgen.pe.*;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.nio.*;
|
||||||
|
import java.nio.channels.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.image.*;
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
import net.charabia.util.codec.*;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
|
||||||
|
public class ExeCompiler
|
||||||
|
{
|
||||||
|
private java.util.Vector m_errors = new java.util.Vector();
|
||||||
|
private Vector m_listeners = new Vector();
|
||||||
|
|
||||||
|
public interface StepListener
|
||||||
|
{
|
||||||
|
public void setNewState(int percentComplete, String state);
|
||||||
|
public void failed();
|
||||||
|
public void complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addListener(ExeCompiler.StepListener listener)
|
||||||
|
{
|
||||||
|
m_listeners.add(listener);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cleanErrors()
|
||||||
|
{
|
||||||
|
m_errors.removeAllElements();
|
||||||
|
}
|
||||||
|
|
||||||
|
public java.util.Vector getErrors()
|
||||||
|
{
|
||||||
|
return m_errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CompilerRunner implements Runnable
|
||||||
|
{
|
||||||
|
private File m_skelroot;
|
||||||
|
private SkeletonBean m_skel;
|
||||||
|
private JSmoothModelBean m_data;
|
||||||
|
private File m_out;
|
||||||
|
private File m_basedir;
|
||||||
|
|
||||||
|
public CompilerRunner(File skelroot, SkeletonBean skel, File basedir, JSmoothModelBean data, File out)
|
||||||
|
{
|
||||||
|
m_skelroot = skelroot;
|
||||||
|
m_skel = skel;
|
||||||
|
m_data = data;
|
||||||
|
m_out = out;
|
||||||
|
m_basedir = basedir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
compile(m_skelroot, m_skel, m_basedir, m_data, m_out);
|
||||||
|
} catch (Exception exc)
|
||||||
|
{
|
||||||
|
exc.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExeCompiler getCompiler()
|
||||||
|
{
|
||||||
|
return ExeCompiler.this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExeCompiler.CompilerRunner getRunnable(File skelroot, SkeletonBean skel, File basedir, JSmoothModelBean data, File out)
|
||||||
|
{
|
||||||
|
return new CompilerRunner(skelroot, skel, basedir, data, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void compileAsync(File skelroot, SkeletonBean skel, File basedir, JSmoothModelBean data, File out)
|
||||||
|
{
|
||||||
|
Thread t = new Thread(new CompilerRunner(skelroot, skel, basedir, data, out));
|
||||||
|
t.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean compile(File skelroot, SkeletonBean skel, File basedir ,JSmoothModelBean data, File out) throws Exception
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
fireStepChange(0, "Starting compilation");
|
||||||
|
|
||||||
|
File pattern = new File(skelroot, skel.getExecutableName());
|
||||||
|
if (pattern.exists() == false)
|
||||||
|
{
|
||||||
|
m_errors.add("Error: Can't find any skeleton at " + skelroot);
|
||||||
|
fireFailedChange();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fireStepChange(10, "Scanning skeleton...");
|
||||||
|
PEFile pe = new PEFile(pattern);
|
||||||
|
pe.open();
|
||||||
|
PEResourceDirectory resdir = pe.getResourceDirectory();
|
||||||
|
|
||||||
|
boolean resb = false;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Adds the jar only if the user selected one
|
||||||
|
//
|
||||||
|
if (data.getEmbeddedJar() == true)
|
||||||
|
{
|
||||||
|
if (data.getJarLocation() == null)
|
||||||
|
{
|
||||||
|
m_errors.add("Error: Jar is not specified!");
|
||||||
|
fireFailedChange();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fireStepChange(40, "Loading Jar...");
|
||||||
|
File jarloc = concFile(basedir, new File(data.getJarLocation()));
|
||||||
|
if (jarloc.exists() == false)
|
||||||
|
{
|
||||||
|
m_errors.add("Error: Can't find jar at " + jarloc);
|
||||||
|
fireFailedChange();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBuffer jardata = load(jarloc);
|
||||||
|
|
||||||
|
fireStepChange(60, "Adding Jar to Resources...");
|
||||||
|
resb = resdir.replaceResource(skel.getResourceCategory(), skel.getResourceJarId(), 1033, jardata);
|
||||||
|
if (resb == false)
|
||||||
|
{
|
||||||
|
m_errors.add("Error: Can't replace jar resource! It is probably missing from the skeleton.");
|
||||||
|
fireFailedChange();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fireStepChange(70, "Adding Properties to Resources...");
|
||||||
|
String props = PropertiesBuilder.makeProperties(basedir, data);
|
||||||
|
ByteBuffer propdata = convert(props);
|
||||||
|
resb = resdir.replaceResource(skel.getResourceCategory(), skel.getResourcePropsId(), 1033, propdata);
|
||||||
|
|
||||||
|
if (data.getIconLocation() != null)
|
||||||
|
{
|
||||||
|
fireStepChange(80, "Loading icon...");
|
||||||
|
String iconpath;
|
||||||
|
if (new java.io.File(data.getIconLocation()).isAbsolute())
|
||||||
|
iconpath = data.getIconLocation();
|
||||||
|
else
|
||||||
|
iconpath = new java.io.File(basedir, data.getIconLocation()).getAbsolutePath();
|
||||||
|
|
||||||
|
Image img = getScaledImage(iconpath, 32, 32);
|
||||||
|
//Hashtable set = calculateColorCount(img);
|
||||||
|
// System.out.println("COLORS TOTAL 4: " + set.size());
|
||||||
|
|
||||||
|
if (img != null)
|
||||||
|
{
|
||||||
|
net.charabia.jsmoothgen.pe.res.ResIcon32 resicon = new net.charabia.jsmoothgen.pe.res.ResIcon32(img);
|
||||||
|
pe.replaceDefaultIcon(resicon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fireStepChange(90, "Saving exe...");
|
||||||
|
pe.dumpTo(out);
|
||||||
|
|
||||||
|
// System.out.println("PROPERTIES:\n" + props);
|
||||||
|
|
||||||
|
fireCompleteChange();
|
||||||
|
return true;
|
||||||
|
} catch (Exception exc)
|
||||||
|
{
|
||||||
|
m_errors.add("Error: " + exc.getMessage());
|
||||||
|
exc.printStackTrace();
|
||||||
|
fireFailedChange();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Image[] loadImages(String path)
|
||||||
|
{
|
||||||
|
File f = new File(path);
|
||||||
|
|
||||||
|
if (path.toUpperCase().endsWith(".ICO"))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Try to load with our ico codec...
|
||||||
|
//
|
||||||
|
try {
|
||||||
|
java.awt.Image[] images = net.charabia.util.codec.IcoCodec.loadImages(f);
|
||||||
|
if ((images != null) && (images.length>0))
|
||||||
|
{
|
||||||
|
return images;
|
||||||
|
}
|
||||||
|
} catch (java.io.IOException exc)
|
||||||
|
{
|
||||||
|
exc.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// defaults to the standard java loading process
|
||||||
|
//
|
||||||
|
BufferedImage bufferedImage;
|
||||||
|
try {
|
||||||
|
bufferedImage = ImageIO.read(f);
|
||||||
|
javax.swing.ImageIcon icon = new javax.swing.ImageIcon(bufferedImage, "default icon");
|
||||||
|
java.awt.Image[] imgs = new java.awt.Image[1];
|
||||||
|
imgs[0] = icon.getImage();
|
||||||
|
return imgs;
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkImageLoaded(Image img)
|
||||||
|
{
|
||||||
|
MediaTracker mtrack = new MediaTracker(new Canvas());
|
||||||
|
mtrack.addImage(img, 1);
|
||||||
|
try {
|
||||||
|
mtrack.waitForAll();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Hashtable calculateColorCount(Image img)
|
||||||
|
{
|
||||||
|
int width = img.getWidth(null);
|
||||||
|
int height = img.getHeight(null);
|
||||||
|
int[] pixels = new int[width*height];
|
||||||
|
PixelGrabber grabber = new PixelGrabber(img, 0, 0, width, height, pixels, 0, width);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
grabber.grabPixels();
|
||||||
|
} catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
System.err.println("interrupted waiting for pixels!");
|
||||||
|
// throw new Exception("Can't load the image provided",e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Hashtable result = new Hashtable();
|
||||||
|
int colorindex = 0;
|
||||||
|
for (int i=0; i<pixels.length; i++)
|
||||||
|
{
|
||||||
|
int pix = pixels[i];
|
||||||
|
if (((pix>>24)&0xFF) > 0)
|
||||||
|
{
|
||||||
|
pix &= 0x00FFFFFF;
|
||||||
|
Integer pixi = new Integer(pix);
|
||||||
|
Object o = result.get(pixi);
|
||||||
|
if (o == null)
|
||||||
|
{
|
||||||
|
result.put(pixi, new Integer(colorindex++));
|
||||||
|
}
|
||||||
|
// if (colorindex > 256)
|
||||||
|
// return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BufferedImage getQuantizedImage(Image img)
|
||||||
|
{
|
||||||
|
// 32 bit ico file already loaded as BufferedImage
|
||||||
|
if (img instanceof BufferedImage) {
|
||||||
|
return (BufferedImage) img;
|
||||||
|
} else {
|
||||||
|
int width = img.getWidth(null);
|
||||||
|
int height = img.getHeight(null);
|
||||||
|
int[][] data = new int[width][height];
|
||||||
|
|
||||||
|
int[] pixelbuffer = new int[width*height];
|
||||||
|
PixelGrabber grabber = new PixelGrabber(img, 0, 0, width, height, pixelbuffer, 0, width);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
grabber.grabPixels();
|
||||||
|
} catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
System.err.println("interrupted waiting for pixels!");
|
||||||
|
throw new RuntimeException("Can't load the image provided",e);
|
||||||
|
}
|
||||||
|
for (int i=0; i<pixelbuffer.length; i++)
|
||||||
|
{
|
||||||
|
data[i%width][i/width] = pixelbuffer[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
int[][] savedata = new int[width][height];
|
||||||
|
|
||||||
|
for(int y=0;y<height;y++)
|
||||||
|
for (int x=0;x<width;x++)
|
||||||
|
savedata[x][y] = data[x][y];
|
||||||
|
|
||||||
|
int[] palette = net.charabia.util.codec.Quantize.quantizeImage(data, 255);
|
||||||
|
byte[] cmap = new byte[256*4];
|
||||||
|
|
||||||
|
for (int i=0; i<palette.length; i++)
|
||||||
|
{
|
||||||
|
// System.out.println(" i= " + (i));
|
||||||
|
cmap[(i*4)] = (byte)((palette[i] >> 16) & 0xFF);
|
||||||
|
cmap[(i*4)+1] = (byte)((palette[i] >> 8) & 0xFF);
|
||||||
|
cmap[(i*4)+2] = (byte) (palette[i] & 0xFF);
|
||||||
|
cmap[(i*4)+3] = (byte) 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
IndexColorModel colmodel = new IndexColorModel(8, palette.length, cmap, 0, true, 0);
|
||||||
|
BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
|
||||||
|
//
|
||||||
|
// The normal manner of quantizing would be to run
|
||||||
|
// result.setRGB(0,0, width, height, pixelbuffer, 0, width);
|
||||||
|
// where result is a BufferedImage of
|
||||||
|
// BufferedImage.TYPE_BYTE_INDEXED type. Unfortunately, I
|
||||||
|
// couldn't make it work. So, here is a work-around that
|
||||||
|
// should work similarly.
|
||||||
|
//
|
||||||
|
java.util.Hashtable set = new java.util.Hashtable();
|
||||||
|
for (int y=0; y<height; y++)
|
||||||
|
{
|
||||||
|
for (int x=0; x<width; x++)
|
||||||
|
{
|
||||||
|
int alpha = (savedata[x][y]>>24)&0xFF;
|
||||||
|
if (alpha == 0)
|
||||||
|
{
|
||||||
|
result.setRGB(x,y, 0);
|
||||||
|
// System.out.print(".");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int rgb = colmodel.getRGB(data[x][y]);
|
||||||
|
rgb |= 0xFF000000;
|
||||||
|
set.put(new Integer(rgb), new Integer(rgb));
|
||||||
|
result.setRGB(x,y,rgb);
|
||||||
|
// System.out.print("*");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// System.out.println("");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Image checkImageSize(Image img, int width, int height)
|
||||||
|
{
|
||||||
|
int w = img.getWidth(null);
|
||||||
|
int h = img.getHeight(null);
|
||||||
|
if ((w == width) && (h == height))
|
||||||
|
return img;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Image getScaledImage(String path, int width, int height)
|
||||||
|
{
|
||||||
|
Image[] orgimages = loadImages(path);
|
||||||
|
|
||||||
|
if ((orgimages == null) || (orgimages.length == 0))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
for (int i=0; i<orgimages.length; i++)
|
||||||
|
checkImageLoaded(orgimages[i]);
|
||||||
|
|
||||||
|
// System.out.println("Loaded " + orgimages.length + " images");
|
||||||
|
for (int i=0; (i<orgimages.length); i++)
|
||||||
|
{
|
||||||
|
int w = orgimages[i].getWidth(null);
|
||||||
|
int h = orgimages[i].getHeight(null);
|
||||||
|
// System.out.println("Size of " + i + " = " + w + "," + h);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// We prefer 32x32 pictures, then 64x64, then 16x16...
|
||||||
|
//
|
||||||
|
Image selected = null;
|
||||||
|
for (int i=0; (i<orgimages.length) && (selected==null); i++)
|
||||||
|
selected = checkImageSize(orgimages[i], 32, 32);
|
||||||
|
for (int i=0; (i<orgimages.length) && (selected==null); i++)
|
||||||
|
selected = checkImageSize(orgimages[i], 64, 64);
|
||||||
|
for (int i=0; (i<orgimages.length) && (selected==null); i++)
|
||||||
|
selected = checkImageSize(orgimages[i], 16, 16);
|
||||||
|
|
||||||
|
if (selected != null)
|
||||||
|
{
|
||||||
|
return getQuantizedImage(selected);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// If there is no 32x32, 64x64, nor 16x16, then we scale the
|
||||||
|
// biggest image to be 32x32... This should happen mainly when
|
||||||
|
// loading an image from a png of gif file, and in most case
|
||||||
|
// there is only one image on the array.
|
||||||
|
//
|
||||||
|
int maxsize = 0;
|
||||||
|
Image biggest = null;
|
||||||
|
for (int i=0; (i<orgimages.length) && (selected==null); i++)
|
||||||
|
{
|
||||||
|
int size = orgimages[i].getWidth(null) * orgimages[i].getHeight(null);
|
||||||
|
if (size>maxsize)
|
||||||
|
{
|
||||||
|
maxsize = size;
|
||||||
|
biggest = orgimages[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (biggest != null)
|
||||||
|
{
|
||||||
|
Image result = biggest.getScaledInstance(32, 32, Image.SCALE_AREA_AVERAGING);
|
||||||
|
checkImageLoaded(result);
|
||||||
|
return getQuantizedImage(result);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Here, we have failed and return null
|
||||||
|
//
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private ByteBuffer load(File in) throws Exception
|
||||||
|
{
|
||||||
|
FileInputStream fis = new FileInputStream(in);
|
||||||
|
ByteBuffer data = ByteBuffer.allocate((int)in.length());
|
||||||
|
data.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
FileChannel fischan = fis.getChannel();
|
||||||
|
fischan.read(data);
|
||||||
|
data.position(0);
|
||||||
|
fis.close();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ByteBuffer convert(String data)
|
||||||
|
{
|
||||||
|
ByteBuffer result = ByteBuffer.allocate(data.length()+1);
|
||||||
|
result.position(0);
|
||||||
|
|
||||||
|
for (int i=0; i<data.length(); i++)
|
||||||
|
{
|
||||||
|
result.put((byte)data.charAt(i));
|
||||||
|
}
|
||||||
|
result.put((byte)0);
|
||||||
|
|
||||||
|
result.position(0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public File concFile(File root, File name)
|
||||||
|
{
|
||||||
|
if (name.isAbsolute())
|
||||||
|
return name;
|
||||||
|
|
||||||
|
return new File(root, name.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void fireStepChange(int percentComplete, String state)
|
||||||
|
{
|
||||||
|
for (Iterator i=m_listeners.iterator(); i.hasNext(); )
|
||||||
|
{
|
||||||
|
ExeCompiler.StepListener l = (ExeCompiler.StepListener)i.next();
|
||||||
|
l.setNewState(percentComplete, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void fireFailedChange()
|
||||||
|
{
|
||||||
|
for (Iterator i=m_listeners.iterator(); i.hasNext(); )
|
||||||
|
{
|
||||||
|
ExeCompiler.StepListener l = (ExeCompiler.StepListener)i.next();
|
||||||
|
l.failed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void fireCompleteChange()
|
||||||
|
{
|
||||||
|
for (Iterator i=m_listeners.iterator(); i.hasNext(); )
|
||||||
|
{
|
||||||
|
ExeCompiler.StepListener l = (ExeCompiler.StepListener)i.next();
|
||||||
|
l.complete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,160 @@
|
|||||||
|
/*
|
||||||
|
JSmooth: a VM wrapper toolkit for Windows
|
||||||
|
Copyright (C) 2003 Rodrigo Reyes <reyes@charabia.net>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.charabia.jsmoothgen.application.gui.editors;
|
||||||
|
|
||||||
|
import net.charabia.jsmoothgen.skeleton.*;
|
||||||
|
import net.charabia.jsmoothgen.application.*;
|
||||||
|
import net.charabia.jsmoothgen.application.gui.*;
|
||||||
|
import net.charabia.jsmoothgen.application.gui.util.*;
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.util.*;
|
||||||
|
import java.io.*;
|
||||||
|
import com.l2fprod.common.swing.*;
|
||||||
|
import com.l2fprod.common.propertysheet.*;
|
||||||
|
|
||||||
|
public class ExecutableIcon extends Editor
|
||||||
|
{
|
||||||
|
private FileSelectionTextField m_selector = new FileSelectionTextField();
|
||||||
|
private JLabel m_iconDisplay = new JLabel("(no image)");
|
||||||
|
|
||||||
|
public ExecutableIcon()
|
||||||
|
{
|
||||||
|
setLayout(new BorderLayout());
|
||||||
|
add(BorderLayout.CENTER, m_selector);
|
||||||
|
add(BorderLayout.SOUTH, m_iconDisplay);
|
||||||
|
|
||||||
|
m_iconDisplay.setHorizontalAlignment(JLabel.CENTER);
|
||||||
|
|
||||||
|
m_selector.addListener(new FileSelectionTextField.FileSelected() {
|
||||||
|
public void fileSelected(String filename)
|
||||||
|
{
|
||||||
|
// System.out.println("new icon: " + filename);
|
||||||
|
setIconLocation(new File(filename));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dataChanged()
|
||||||
|
{
|
||||||
|
if (getBaseDir() != null)
|
||||||
|
m_selector.setBaseDir(getBaseDir());
|
||||||
|
|
||||||
|
if (m_model.getIconLocation() != null)
|
||||||
|
{
|
||||||
|
m_selector.setFile(getAbsolutePath(new java.io.File(m_model.getIconLocation())));
|
||||||
|
setIconLocation(getAbsolutePath(new java.io.File(m_model.getIconLocation())));
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_selector.setFile(null);
|
||||||
|
setIconLocation(new File(""));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateModel()
|
||||||
|
{
|
||||||
|
File f = m_selector.getFile();
|
||||||
|
if (f != null)
|
||||||
|
m_model.setIconLocation(m_selector.getFile().toString());
|
||||||
|
else
|
||||||
|
m_model.setIconLocation(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLabel()
|
||||||
|
{
|
||||||
|
return "ICONLOCATION_LABEL";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription()
|
||||||
|
{
|
||||||
|
return "ICONLOCATION_HELP";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setIconLocation(File iconfile)
|
||||||
|
{
|
||||||
|
if (iconfile.isAbsolute() == false)
|
||||||
|
{
|
||||||
|
iconfile = new File(m_basedir, iconfile.toString());
|
||||||
|
}
|
||||||
|
ImageIcon icon = null;
|
||||||
|
|
||||||
|
// System.out.println("setIconLocation: " + iconfile);
|
||||||
|
|
||||||
|
if (iconfile.toString().toUpperCase().endsWith(".ICO"))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Try to load with our ico codec...
|
||||||
|
//
|
||||||
|
try {
|
||||||
|
java.awt.image.BufferedImage[] images = net.charabia.util.codec.IcoCodec.loadImages(iconfile);
|
||||||
|
if ((images != null) && (images.length>0))
|
||||||
|
{
|
||||||
|
java.awt.Image img = images[0];
|
||||||
|
icon = new ImageIcon(img);
|
||||||
|
}
|
||||||
|
} catch (java.io.IOException exc)
|
||||||
|
{
|
||||||
|
exc.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // Otherwise try with the standard toolkit functions...
|
||||||
|
{
|
||||||
|
BufferedImage bufferedImage;
|
||||||
|
try {
|
||||||
|
bufferedImage = ImageIO.read(iconfile);
|
||||||
|
icon = new javax.swing.ImageIcon(bufferedImage, "default icon");
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (icon != null)
|
||||||
|
{
|
||||||
|
int width = icon.getIconWidth();
|
||||||
|
int height = icon.getIconHeight();
|
||||||
|
|
||||||
|
m_iconDisplay.setIcon(icon);
|
||||||
|
m_iconDisplay.setText("");
|
||||||
|
m_model.setIconLocation(iconfile.getAbsolutePath());
|
||||||
|
this.validate();
|
||||||
|
this.invalidate();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_iconDisplay.setIcon(null);
|
||||||
|
m_iconDisplay.setText("(no image)");
|
||||||
|
m_model.setIconLocation(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
doLayout();
|
||||||
|
invalidate();
|
||||||
|
validate();
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,462 @@
|
|||||||
|
/*
|
||||||
|
JSmooth: a VM wrapper toolkit for Windows
|
||||||
|
Copyright (C) 2003 Rodrigo Reyes <reyes@charabia.net>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ResIcon.java
|
||||||
|
*
|
||||||
|
* Created on 17 août 2003, 22:51
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.charabia.jsmoothgen.pe.res;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.io.*;
|
||||||
|
import java.nio.*;
|
||||||
|
import java.nio.channels.*;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.image.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see
|
||||||
|
*/
|
||||||
|
public class ResIcon
|
||||||
|
{
|
||||||
|
public long Size; /* Size of this header in bytes DWORD*/
|
||||||
|
public long Width; /* Image width in pixels LONG*/
|
||||||
|
public long Height; /* Image height in pixels LONG*/
|
||||||
|
public int Planes; /* Number of color planes WORD*/
|
||||||
|
public int BitsPerPixel; /* Number of bits per pixel WORD*/
|
||||||
|
/* Fields added for Windows 3.x follow this line */
|
||||||
|
public long Compression; /* Compression methods used DWORD*/
|
||||||
|
public long SizeOfBitmap; /* Size of bitmap in bytes DWORD*/
|
||||||
|
public long HorzResolution; /* Horizontal resolution in pixels per meter LONG*/
|
||||||
|
public long VertResolution; /* Vertical resolution in pixels per meter LONG*/
|
||||||
|
public long ColorsUsed; /* Number of colors in the image DWORD*/
|
||||||
|
public long ColorsImportant; /* Minimum number of important colors DWORD*/
|
||||||
|
|
||||||
|
public PaletteElement[] Palette;
|
||||||
|
public short[] BitmapXOR;
|
||||||
|
public short[] BitmapAND;
|
||||||
|
|
||||||
|
public class PaletteElement
|
||||||
|
{
|
||||||
|
public int Blue;
|
||||||
|
public int Green;
|
||||||
|
public int Red;
|
||||||
|
public int Reserved;
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return "{"+Blue+","+Green+","+Red+","+Reserved+"}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResIcon(){};
|
||||||
|
/**
|
||||||
|
* Creates a new instance of ResIcon
|
||||||
|
* @see
|
||||||
|
* @param in
|
||||||
|
*/
|
||||||
|
public ResIcon(ByteBuffer in)
|
||||||
|
{
|
||||||
|
Size = in.getInt();
|
||||||
|
Width = in.getInt();
|
||||||
|
Height = in.getInt();
|
||||||
|
Planes = in.getShort();
|
||||||
|
BitsPerPixel = in.getShort();
|
||||||
|
Compression = in.getInt();
|
||||||
|
SizeOfBitmap = in.getInt();
|
||||||
|
HorzResolution = in.getInt();
|
||||||
|
VertResolution = in.getInt();
|
||||||
|
ColorsUsed = in.getInt();
|
||||||
|
ColorsImportant = in.getInt();
|
||||||
|
|
||||||
|
int cols = (int)ColorsUsed;
|
||||||
|
if (cols == 0)
|
||||||
|
cols = 1 << BitsPerPixel;
|
||||||
|
|
||||||
|
Palette = new PaletteElement[(int)cols];
|
||||||
|
for (int i=0; i<Palette.length; i++)
|
||||||
|
{
|
||||||
|
PaletteElement el = new PaletteElement();
|
||||||
|
el.Blue = in.get();
|
||||||
|
el.Green = in.get();
|
||||||
|
el.Red = in.get();
|
||||||
|
el.Reserved = in.get();
|
||||||
|
Palette[i] = el;
|
||||||
|
}
|
||||||
|
|
||||||
|
// int xorbytes = (((int)Height/2) * (int)Width * (int)BitsPerPixel) / 8;
|
||||||
|
int xorbytes = (((int)Height/2) * (int)Width);
|
||||||
|
// System.out.println("POSITION " + in.position() + " : xorbitmap = " + xorbytes + " bytes");
|
||||||
|
|
||||||
|
BitmapXOR = new short[xorbytes];
|
||||||
|
for (int i=0; i<BitmapXOR.length; i++)
|
||||||
|
{
|
||||||
|
switch(BitsPerPixel)
|
||||||
|
{
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
int pix = in.get();
|
||||||
|
BitmapXOR[i] = (short)((pix >> 4) & 0x0F);
|
||||||
|
i++;
|
||||||
|
BitmapXOR[i] = (short)(pix & 0x0F);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
{
|
||||||
|
BitmapXOR[i] = in.get();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int height = (int)(Height/2);
|
||||||
|
int rowsize = (int)Width / 8;
|
||||||
|
if ((rowsize%4)>0)
|
||||||
|
{
|
||||||
|
rowsize += 4 - (rowsize%4);
|
||||||
|
}
|
||||||
|
|
||||||
|
// System.out.println("POSITION " + in.position() + " : andbitmap = " + andbytes + " bytes");
|
||||||
|
|
||||||
|
int andbytes = height * rowsize; // (((int)Height/2) * (int)Width) / 8;
|
||||||
|
|
||||||
|
BitmapAND = new short[andbytes];
|
||||||
|
for (int i=0; i<BitmapAND.length; i++)
|
||||||
|
{
|
||||||
|
BitmapAND[i] = in.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creates a new instance based on the data of the Image argument.
|
||||||
|
* @param img
|
||||||
|
*/
|
||||||
|
public ResIcon(Image img) throws Exception
|
||||||
|
{
|
||||||
|
int width = img.getWidth(null);
|
||||||
|
int height = img.getHeight(null);
|
||||||
|
|
||||||
|
if ((width % 8) != 0)
|
||||||
|
width += (7-(width%8));
|
||||||
|
|
||||||
|
if ((height % 8) != 0)
|
||||||
|
height += (7-(height%8));
|
||||||
|
|
||||||
|
// System.out.println("FOUND WIDTH " + width + " (was " + img.getWidth(null) + ")");
|
||||||
|
// System.out.println("FOUND HEIGHT " + height + " (was " + img.getHeight(null) + ")");
|
||||||
|
|
||||||
|
// System.out.println("RESICON...");
|
||||||
|
if (img instanceof BufferedImage)
|
||||||
|
{
|
||||||
|
BufferedImage result = (BufferedImage)img;
|
||||||
|
|
||||||
|
for (int y=0; y<result.getHeight(); y++)
|
||||||
|
{
|
||||||
|
for (int x=0; x<result.getWidth(); x++)
|
||||||
|
{
|
||||||
|
int rgb = result.getRGB(x, y);
|
||||||
|
if (((rgb>>24)&0xFF)>0)
|
||||||
|
{
|
||||||
|
// System.out.print(".");
|
||||||
|
}
|
||||||
|
// else
|
||||||
|
// System.out.print("*");
|
||||||
|
}
|
||||||
|
// System.out.println("");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int[] pixelbuffer = new int[width*height];
|
||||||
|
PixelGrabber grabber = new PixelGrabber(img, 0, 0, width, height, pixelbuffer, 0, width);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
grabber.grabPixels();
|
||||||
|
} catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
System.err.println("interrupted waiting for pixels!");
|
||||||
|
throw new Exception("Can't load the image provided",e);
|
||||||
|
}
|
||||||
|
|
||||||
|
Hashtable colors = calculateColorCount(pixelbuffer);
|
||||||
|
|
||||||
|
// FORCE ALWAYS to 8
|
||||||
|
this.BitsPerPixel = 8;
|
||||||
|
|
||||||
|
Palette = new ResIcon.PaletteElement[1 << BitsPerPixel];
|
||||||
|
// System.out.println("Creating palette of " + Palette.length + " colors (" + colors.size() + ")");
|
||||||
|
for (Enumeration e=colors.keys(); e.hasMoreElements(); )
|
||||||
|
{
|
||||||
|
Integer pixi = (Integer)e.nextElement();
|
||||||
|
int pix = pixi.intValue();
|
||||||
|
int index = ((Integer)colors.get(pixi)).intValue();
|
||||||
|
// System.out.println("set pixel " + index);
|
||||||
|
|
||||||
|
Palette[index] = new ResIcon.PaletteElement();
|
||||||
|
Palette[index].Blue = pix & 0xFF;
|
||||||
|
Palette[index].Green = (pix >> 8) & 0xff;
|
||||||
|
Palette[index].Red = (pix >> 16) & 0xff;
|
||||||
|
}
|
||||||
|
for (int i=0; i<Palette.length; i++)
|
||||||
|
{
|
||||||
|
if (Palette[i] == null)
|
||||||
|
Palette[i] = new ResIcon.PaletteElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
this.Size = 40;
|
||||||
|
this.Width = width;
|
||||||
|
this.Height = height* 2;
|
||||||
|
this.Planes = 1;
|
||||||
|
this.Compression = 0;
|
||||||
|
|
||||||
|
this.SizeOfBitmap = 0;
|
||||||
|
this.HorzResolution = 0;
|
||||||
|
this.VertResolution = 0;
|
||||||
|
|
||||||
|
this.ColorsUsed = 0;
|
||||||
|
this.ColorsImportant = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// We calculate the rowsize in bytes. It seems that it must be
|
||||||
|
// aligned on a double word, although none of the
|
||||||
|
// documentation I have on the icon format states so.
|
||||||
|
//
|
||||||
|
int rowsize = width / 8;
|
||||||
|
if ((rowsize%4)>0)
|
||||||
|
{
|
||||||
|
rowsize += 4 - (rowsize%4);
|
||||||
|
}
|
||||||
|
|
||||||
|
BitmapXOR = new short[(((int)Height/2) * (int)Width * (int)BitsPerPixel) / 8];
|
||||||
|
BitmapAND = new short[((int)Height/2) * rowsize];
|
||||||
|
|
||||||
|
int bxl = BitmapXOR.length-1;
|
||||||
|
int bal = BitmapAND.length-1;
|
||||||
|
|
||||||
|
for (int i=0; i<pixelbuffer.length; i++)
|
||||||
|
{
|
||||||
|
int col = i%width;
|
||||||
|
int line = i/width;
|
||||||
|
|
||||||
|
bxl = (width * height) - (((i/width)+1)*width) + (i%width);
|
||||||
|
// bal = ((width * height)/8) - ((line+1)*(width/8)) + (col/8);
|
||||||
|
bal = (rowsize * height) - ((line+1)*(rowsize)) + (col/8);
|
||||||
|
|
||||||
|
// if ((pixelbuffer[i] & 0xFF000000) != 0x00000000)
|
||||||
|
|
||||||
|
//
|
||||||
|
// If the color is transparent, any color will suit
|
||||||
|
// (as it is not supposed to be displayed)
|
||||||
|
//
|
||||||
|
if ( (((pixelbuffer[i]>>24)& 0xFF) == 0))
|
||||||
|
{
|
||||||
|
BitmapAND[ bal ] |= 1 << (7-(i%8));
|
||||||
|
BitmapXOR[bxl] = 0xFF; // (short)getBrightest(); FF
|
||||||
|
|
||||||
|
// int pixel = pixelbuffer[i] & 0x00FFFFFF;
|
||||||
|
// pixel = 0x000000;
|
||||||
|
// Integer icol = (Integer)colors.get(new Integer(pixel));
|
||||||
|
// if (icol != null)
|
||||||
|
// {
|
||||||
|
// int palindex = icol.intValue();
|
||||||
|
// BitmapXOR[bxl] = (short)palindex;
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// BitmapXOR[bxl] = 0; // (short)getBrightest();
|
||||||
|
// System.out.println("Can't find TRANSP BLACK COL " + icol );
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int pixel = pixelbuffer[i] & 0x00FFFFFF;
|
||||||
|
// pixel = 0x000000;
|
||||||
|
Integer icol = (Integer)colors.get(new Integer(pixel));
|
||||||
|
if (icol != null)
|
||||||
|
{
|
||||||
|
int palindex = icol.intValue();
|
||||||
|
BitmapXOR[bxl] = (short)palindex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getBrightest()
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
int averesult = 0;
|
||||||
|
for (int i=0; i<Palette.length; i++)
|
||||||
|
{
|
||||||
|
int ave1 = (Palette[0].Red + Palette[0].Green + Palette[0].Blue)/3;
|
||||||
|
if (ave1 > averesult)
|
||||||
|
{
|
||||||
|
averesult = ave1;
|
||||||
|
result = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Hashtable calculateColorCount(int[] pixels)
|
||||||
|
{
|
||||||
|
Hashtable result = new Hashtable();
|
||||||
|
int colorindex = 0;
|
||||||
|
for (int i=0; i<pixels.length; i++)
|
||||||
|
{
|
||||||
|
int pix = pixels[i];
|
||||||
|
if (((pix>>24)&0xFF) > 0)
|
||||||
|
{
|
||||||
|
pix &= 0x00FFFFFF;
|
||||||
|
Integer pixi = new Integer(pix);
|
||||||
|
Object o = result.get(pixi);
|
||||||
|
if (o == null)
|
||||||
|
{
|
||||||
|
result.put(pixi, new Integer(colorindex++));
|
||||||
|
}
|
||||||
|
// if (colorindex > 256)
|
||||||
|
// return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creates and returns a ByteBuffer containing an image under
|
||||||
|
* the .ico format expected by Windows.
|
||||||
|
* @return a ByteBuffer with the .ico data
|
||||||
|
*/
|
||||||
|
public ByteBuffer getData()
|
||||||
|
{
|
||||||
|
int cols = (int)ColorsUsed;
|
||||||
|
if (cols == 0)
|
||||||
|
cols = 1 << BitsPerPixel;
|
||||||
|
|
||||||
|
int rowsize = (int)Width / 8;
|
||||||
|
if ((rowsize%4)>0)
|
||||||
|
{
|
||||||
|
rowsize += 4 - (rowsize%4);
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBuffer buf = ByteBuffer.allocate((int) (40 + (cols*4) + (Width*(Height/2)*BitsPerPixel)/8 + (rowsize*(Height/2))));
|
||||||
|
buf.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
buf.position(0);
|
||||||
|
|
||||||
|
buf.putInt((int)Size);
|
||||||
|
buf.putInt((int)Width);
|
||||||
|
buf.putInt((int)Height);
|
||||||
|
buf.putShort((short)Planes);
|
||||||
|
buf.putShort((short)BitsPerPixel);
|
||||||
|
buf.putInt((int)Compression);
|
||||||
|
buf.putInt((int)SizeOfBitmap);
|
||||||
|
buf.putInt((int)HorzResolution);
|
||||||
|
buf.putInt((int)VertResolution);
|
||||||
|
buf.putInt((int)ColorsUsed);
|
||||||
|
buf.putInt((int)ColorsImportant);
|
||||||
|
|
||||||
|
// System.out.println("GET DATA :: Palette.size= "+Palette.length + " // position=" + buf.position());
|
||||||
|
for (int i=0; i<Palette.length; i++)
|
||||||
|
{
|
||||||
|
PaletteElement el = Palette[i];
|
||||||
|
buf.put((byte)el.Blue);
|
||||||
|
buf.put((byte)el.Green);
|
||||||
|
buf.put((byte)el.Red);
|
||||||
|
buf.put((byte)el.Reserved);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (BitsPerPixel)
|
||||||
|
{
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
for (int i=0; i<BitmapXOR.length; i+=2)
|
||||||
|
{
|
||||||
|
int v1 = BitmapXOR[i];
|
||||||
|
int v2 = BitmapXOR[i+1];
|
||||||
|
buf.put((byte)( (v1<<4) | v2 ));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 8:
|
||||||
|
{
|
||||||
|
// System.out.println("GET DATA :: XORBitmap.size= "+BitmapXOR.length + " // position=" + buf.position());
|
||||||
|
for (int i=0; i<BitmapXOR.length; i++)
|
||||||
|
{
|
||||||
|
buf.put((byte)BitmapXOR[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("BitRes " + BitsPerPixel + " not supported!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// System.out.println("GET DATA :: AndBitmap.size= "+BitmapAND.length + " // position=" + buf.position());
|
||||||
|
for (int i=0; i<BitmapAND.length; i++)
|
||||||
|
{
|
||||||
|
buf.put((byte)BitmapAND[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// System.out.println("GET DATA END AT " + buf.position());
|
||||||
|
buf.position(0);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
StringBuffer out = new StringBuffer();
|
||||||
|
|
||||||
|
out.append("Size: " + Size);
|
||||||
|
out.append("\nWidth: " + Width);
|
||||||
|
out.append("\nHeight: " + Height);
|
||||||
|
out.append("\nPlanes: " + Planes);
|
||||||
|
out.append("\nBitsPerPixel: " + BitsPerPixel);
|
||||||
|
out.append("\nCompression: " + Compression);
|
||||||
|
out.append("\nSizeOfBitmap: " + SizeOfBitmap);
|
||||||
|
out.append("\nHorzResolution: " + HorzResolution);
|
||||||
|
out.append("\nVertResolution: " + VertResolution);
|
||||||
|
out.append("\nColorsUsed: " + ColorsUsed);
|
||||||
|
out.append("\nColorsImportant: " + ColorsImportant);
|
||||||
|
|
||||||
|
// for (int i = 0; i<Palette.length; i++)
|
||||||
|
// {
|
||||||
|
// out.append("\n");
|
||||||
|
// out.append(Palette[i].toString());
|
||||||
|
// }
|
||||||
|
out.append("\nBitmapXOR["+ BitmapXOR.length+ "]={");
|
||||||
|
for (int i=0; i<BitmapXOR.length; i++)
|
||||||
|
{
|
||||||
|
out.append((byte)BitmapXOR[i]);
|
||||||
|
}
|
||||||
|
out.append("}\nBitmapAnd["+ BitmapAND.length +"]={");
|
||||||
|
for (int i=0; i<BitmapAND.length; i++)
|
||||||
|
{
|
||||||
|
out.append((byte)BitmapAND[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return out.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[]args) throws Exception
|
||||||
|
{
|
||||||
|
net.charabia.jsmoothgen.pe.PEFile.main(args);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,126 @@
|
|||||||
|
package net.charabia.jsmoothgen.pe.res;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 32 bits res icon with alpha channel
|
||||||
|
*/
|
||||||
|
public class ResIcon32 extends ResIcon {
|
||||||
|
BufferedImage image;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance based on the data of the Image argument.
|
||||||
|
*
|
||||||
|
* @param img image
|
||||||
|
* @throws Exception on error
|
||||||
|
*/
|
||||||
|
public ResIcon32(Image img) throws Exception {
|
||||||
|
int width = img.getWidth(null);
|
||||||
|
int height = img.getHeight(null);
|
||||||
|
|
||||||
|
image = (BufferedImage) img;
|
||||||
|
|
||||||
|
this.BitsPerPixel = 32;
|
||||||
|
|
||||||
|
// header size
|
||||||
|
this.Size = 40;
|
||||||
|
this.Width = width;
|
||||||
|
this.Height = height * 2;
|
||||||
|
this.Planes = 1;
|
||||||
|
this.Compression = 0;
|
||||||
|
|
||||||
|
this.SizeOfBitmap = 0;
|
||||||
|
this.HorzResolution = 0;
|
||||||
|
this.VertResolution = 0;
|
||||||
|
|
||||||
|
this.ColorsUsed = 0;
|
||||||
|
this.ColorsImportant = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and returns a ByteBuffer containing an image under
|
||||||
|
* the .ico format expected by Windows.
|
||||||
|
*
|
||||||
|
* @return a ByteBuffer with the .ico data
|
||||||
|
*/
|
||||||
|
public ByteBuffer getData() {
|
||||||
|
// transparency mask rows must be double bytes aligned
|
||||||
|
int rowsize = (int) Width / 8;
|
||||||
|
int padding = 0;
|
||||||
|
if ((rowsize % 4) > 0) {
|
||||||
|
padding = (int) ((4 - Width / 8 % 4) * 8);
|
||||||
|
rowsize += 4 - (rowsize % 4);
|
||||||
|
}
|
||||||
|
// transparency line padding size
|
||||||
|
// create transparency mask buffer
|
||||||
|
int transparencyBytesSize = (int) (rowsize * (Height / 2));
|
||||||
|
int[] transparencyMask = new int[transparencyBytesSize];
|
||||||
|
|
||||||
|
// allocate header + pixel count * bytes / pixel + transparency mask size
|
||||||
|
ByteBuffer buf = ByteBuffer.allocate((int) (40 + (Width * ((Height) / 2) * BitsPerPixel/8) + transparencyBytesSize));
|
||||||
|
|
||||||
|
buf.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
buf.position(0);
|
||||||
|
|
||||||
|
// write header
|
||||||
|
buf.putInt((int) Size);
|
||||||
|
buf.putInt((int) Width);
|
||||||
|
buf.putInt((int) Height);
|
||||||
|
buf.putShort((short) Planes);
|
||||||
|
buf.putShort((short) BitsPerPixel);
|
||||||
|
buf.putInt((int) Compression);
|
||||||
|
buf.putInt((int) SizeOfBitmap);
|
||||||
|
buf.putInt((int) HorzResolution);
|
||||||
|
buf.putInt((int) VertResolution);
|
||||||
|
buf.putInt((int) ColorsUsed);
|
||||||
|
buf.putInt((int) ColorsImportant);
|
||||||
|
|
||||||
|
int pixelCount = 0;
|
||||||
|
for (int y = (int) ((Height / 2) - 1); y >= 0; y--) {
|
||||||
|
for (int x = 0; x < Width; x++) {
|
||||||
|
int pix = image.getRGB(x, y);
|
||||||
|
//System.out.println(x+" "+y+":"+Integer.toHexString((pix >> 24) & 0xff));
|
||||||
|
boolean isTransparent = ((pix >> 24) & 0xff) == 0;
|
||||||
|
if (isTransparent) {
|
||||||
|
int index = pixelCount / 8;
|
||||||
|
byte bitindex = (byte) (pixelCount % 8);
|
||||||
|
transparencyMask[index] |= 0x80 >> bitindex;
|
||||||
|
}
|
||||||
|
buf.putInt(pix);
|
||||||
|
pixelCount++;
|
||||||
|
}
|
||||||
|
// skip to next transparency line
|
||||||
|
pixelCount += padding;
|
||||||
|
}
|
||||||
|
|
||||||
|
// transparency mask
|
||||||
|
for (int x = 0; x < transparencyBytesSize; x++) {
|
||||||
|
buf.put((byte) (transparencyMask[x] & 0xff));
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.position(0);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
StringBuffer out = new StringBuffer();
|
||||||
|
|
||||||
|
out.append("Size: ").append(Size);
|
||||||
|
out.append("\nWidth: ").append(Width);
|
||||||
|
out.append("\nHeight: ").append(Height);
|
||||||
|
out.append("\nPlanes: ").append(Planes);
|
||||||
|
out.append("\nBitsPerPixel: ").append(BitsPerPixel);
|
||||||
|
out.append("\nCompression: ").append(Compression);
|
||||||
|
out.append("\nSizeOfBitmap: ").append(SizeOfBitmap);
|
||||||
|
out.append("\nHorzResolution: ").append(HorzResolution);
|
||||||
|
out.append("\nVertResolution: ").append(VertResolution);
|
||||||
|
out.append("\nColorsUsed: ").append(ColorsUsed);
|
||||||
|
out.append("\nColorsImportant: ").append(ColorsImportant);
|
||||||
|
|
||||||
|
return out.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
357
jsmooth-0.9.9-7-patch/src/net/charabia/util/codec/IcoCodec.java
Normal file
357
jsmooth-0.9.9-7-patch/src/net/charabia/util/codec/IcoCodec.java
Normal file
@ -0,0 +1,357 @@
|
|||||||
|
/*
|
||||||
|
JSmooth: a VM wrapper toolkit for Windows
|
||||||
|
Copyright (C) 2003 Rodrigo Reyes <reyes@charabia.net>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.charabia.util.codec;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import net.charabia.util.io.BinaryInputStream;
|
||||||
|
import java.awt.image.*;
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Rodrigo Reyes
|
||||||
|
*/
|
||||||
|
public class IcoCodec
|
||||||
|
{
|
||||||
|
static public class IconDir
|
||||||
|
{
|
||||||
|
int idType;
|
||||||
|
int idCount;
|
||||||
|
|
||||||
|
public IconDir(BinaryInputStream in) throws IOException
|
||||||
|
{
|
||||||
|
in.readUShortLE();
|
||||||
|
idType = in.readUShortLE();
|
||||||
|
idCount = in.readUShortLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return "{ idType=" + idType + ", " + idCount + " }";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static public class IconEntry
|
||||||
|
{
|
||||||
|
short bWidth;
|
||||||
|
short bHeight;
|
||||||
|
short bColorCount;
|
||||||
|
short bReserved;
|
||||||
|
int wPlanes;
|
||||||
|
int wBitCount;
|
||||||
|
long dwBytesInRes;
|
||||||
|
long dwImageOffset;
|
||||||
|
|
||||||
|
public IconEntry(BinaryInputStream in) throws IOException
|
||||||
|
{
|
||||||
|
bWidth = in.readUByte();
|
||||||
|
bHeight = in.readUByte();
|
||||||
|
bColorCount = in.readUByte();
|
||||||
|
bReserved = in.readUByte();
|
||||||
|
wPlanes = in.readUShortLE();
|
||||||
|
wBitCount = in.readUShortLE();
|
||||||
|
dwBytesInRes = in.readUIntLE();
|
||||||
|
dwImageOffset = in.readUIntLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
buffer.append("{ bWidth="+bWidth+"\n");
|
||||||
|
buffer.append(" bHeight="+bHeight+"\n");
|
||||||
|
buffer.append(" bColorCount="+bColorCount+"\n");
|
||||||
|
buffer.append(" wPlanes="+wPlanes+"\n");
|
||||||
|
buffer.append(" wBitCount="+wBitCount+"\n");
|
||||||
|
buffer.append(" dwBytesInRes="+dwBytesInRes+"\n");
|
||||||
|
buffer.append(" dwImageOffset="+dwImageOffset+"\n");
|
||||||
|
buffer.append("}");
|
||||||
|
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static public class IconHeader
|
||||||
|
{
|
||||||
|
public long Size; /* Size of this header in bytes DWORD 0*/
|
||||||
|
public long Width; /* Image width in pixels LONG 4*/
|
||||||
|
public long Height; /* Image height in pixels LONG 8*/
|
||||||
|
public int Planes; /* Number of color planes WORD 12 */
|
||||||
|
public int BitsPerPixel; /* Number of bits per pixel WORD 14 */
|
||||||
|
/* Fields added for Windows 3.x follow this line */
|
||||||
|
public long Compression; /* Compression methods used DWORD 16 */
|
||||||
|
public long SizeOfBitmap; /* Size of bitmap in bytes DWORD 20 */
|
||||||
|
public long HorzResolution; /* Horizontal resolution in pixels per meter LONG 24 */
|
||||||
|
public long VertResolution; /* Vertical resolution in pixels per meter LONG 28*/
|
||||||
|
public long ColorsUsed; /* Number of colors in the image DWORD 32 */
|
||||||
|
public long ColorsImportant; /* Minimum number of important colors DWORD 36 */
|
||||||
|
|
||||||
|
public IconHeader(BinaryInputStream in) throws IOException
|
||||||
|
{
|
||||||
|
Size = in.readUIntLE();
|
||||||
|
Width = in.readUIntLE();
|
||||||
|
Height = in.readUIntLE();
|
||||||
|
Planes = in.readUShortLE();
|
||||||
|
BitsPerPixel = in.readUShortLE();
|
||||||
|
Compression = in.readUIntLE();
|
||||||
|
SizeOfBitmap = in.readUIntLE();
|
||||||
|
HorzResolution = in.readUIntLE();
|
||||||
|
VertResolution = in.readUIntLE();
|
||||||
|
ColorsUsed = in.readUIntLE();
|
||||||
|
ColorsImportant = in.readUIntLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
buffer.append("Size="); buffer.append(Size);
|
||||||
|
buffer.append("\nWidth="); buffer.append(Width);
|
||||||
|
buffer.append("\nHeight="); buffer.append(Height);
|
||||||
|
buffer.append("\nPlanes="); buffer.append(Planes);
|
||||||
|
buffer.append("\nBitsPerPixel="); buffer.append(BitsPerPixel);
|
||||||
|
buffer.append("\nCompression="); buffer.append(Compression);
|
||||||
|
buffer.append("\nSizeOfBitmap="); buffer.append(SizeOfBitmap);
|
||||||
|
buffer.append("\nHorzResolution="); buffer.append(HorzResolution);
|
||||||
|
buffer.append("\nVertResolution="); buffer.append(VertResolution);
|
||||||
|
buffer.append("\nColorsUsed="); buffer.append(ColorsUsed);
|
||||||
|
buffer.append("\nColorsImportant="); buffer.append(ColorsImportant);
|
||||||
|
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static public BufferedImage[] loadImages(File f) throws IOException
|
||||||
|
{
|
||||||
|
InputStream istream = new FileInputStream(f);
|
||||||
|
BufferedInputStream buffin = new BufferedInputStream(istream);
|
||||||
|
BinaryInputStream in = new BinaryInputStream(buffin);
|
||||||
|
|
||||||
|
try {
|
||||||
|
in.mark(32000);
|
||||||
|
|
||||||
|
IconDir dir = new IconDir(in);
|
||||||
|
// System.out.println("DIR = " + dir);
|
||||||
|
|
||||||
|
IconEntry[] entries = new IconEntry[dir.idCount];
|
||||||
|
BufferedImage[] images = new BufferedImage[dir.idCount];
|
||||||
|
|
||||||
|
for (int i=0; i<dir.idCount; i++)
|
||||||
|
{
|
||||||
|
entries[i] = new IconEntry(in);
|
||||||
|
// System.out.println("ENTRY " + i + " = " + entries[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
IconEntry entry = entries[0];
|
||||||
|
// System.out.println("ENTRYx = " + entry);
|
||||||
|
|
||||||
|
for (int i=0; i<dir.idCount; i++)
|
||||||
|
{
|
||||||
|
in.reset();
|
||||||
|
in.skip(entries[i].dwImageOffset);
|
||||||
|
|
||||||
|
IconHeader header = new IconHeader(in);
|
||||||
|
// System.out.println("Header: " + header);
|
||||||
|
|
||||||
|
long toskip = header.Size - 40;
|
||||||
|
if (toskip>0)
|
||||||
|
in.skip((int)toskip);
|
||||||
|
|
||||||
|
// System.out.println("skipped data");
|
||||||
|
BufferedImage image = new BufferedImage((int)header.Width, (int)header.Height/2,
|
||||||
|
BufferedImage.TYPE_INT_ARGB);
|
||||||
|
|
||||||
|
switch(header.BitsPerPixel)
|
||||||
|
{
|
||||||
|
case 4:
|
||||||
|
case 8:
|
||||||
|
loadPalettedImage(in, entries[i], header, image);
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
load32bitsImage(in, entries[i], header, image);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new Exception("Unsupported ICO color depth: " + header.BitsPerPixel);
|
||||||
|
}
|
||||||
|
|
||||||
|
images[i] = image;
|
||||||
|
}
|
||||||
|
|
||||||
|
return images;
|
||||||
|
|
||||||
|
} catch (Exception exc)
|
||||||
|
{
|
||||||
|
exc.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static private void loadPalettedImage(BinaryInputStream in, IconEntry entry, IconHeader header, BufferedImage image) throws Exception
|
||||||
|
{
|
||||||
|
// System.out.println("Loading image...");
|
||||||
|
|
||||||
|
// System.out.println("Loading palette...");
|
||||||
|
|
||||||
|
//
|
||||||
|
// First, load the palette
|
||||||
|
//
|
||||||
|
int cols = (int)header.ColorsUsed;
|
||||||
|
if (cols == 0)
|
||||||
|
{
|
||||||
|
if (entry.bColorCount != 0)
|
||||||
|
cols = entry.bColorCount;
|
||||||
|
else
|
||||||
|
cols = 1 << header.BitsPerPixel;
|
||||||
|
}
|
||||||
|
|
||||||
|
int[] redp = new int[cols];
|
||||||
|
int[] greenp = new int[cols];
|
||||||
|
int[] bluep = new int[cols];
|
||||||
|
|
||||||
|
for (int i=0; i<cols; i++)
|
||||||
|
{
|
||||||
|
bluep[i] = in.readUByte();
|
||||||
|
greenp[i] = in.readUByte();
|
||||||
|
redp[i] = in.readUByte();
|
||||||
|
in.readUByte();
|
||||||
|
}
|
||||||
|
|
||||||
|
// System.out.println("Palette read!");
|
||||||
|
|
||||||
|
//
|
||||||
|
// Set the image
|
||||||
|
|
||||||
|
int xorbytes = (((int)header.Height/2) * (int)header.Width);
|
||||||
|
int readbytes = 0;
|
||||||
|
|
||||||
|
for (int y=(int)(header.Height/2)-1; y>=0; y--)
|
||||||
|
{
|
||||||
|
for (int x=0; x<header.Width; x++)
|
||||||
|
{
|
||||||
|
switch(header.BitsPerPixel)
|
||||||
|
{
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
int pix = in.readUByte();
|
||||||
|
readbytes++;
|
||||||
|
|
||||||
|
int col1 = (pix>>4) & 0x0F;
|
||||||
|
int col2 = pix & 0x0F;
|
||||||
|
image.setRGB(x, y, (0xFF<<24) | (redp[col1]<<16) | (greenp[col1]<<8) | bluep[col1]);
|
||||||
|
image.setRGB(++x, y, (0xFF<<24) | (redp[col2]<<16) | (greenp[col2]<<8) | bluep[col2]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
{
|
||||||
|
int col1 = in.readUByte();
|
||||||
|
readbytes++;
|
||||||
|
|
||||||
|
image.setRGB(x, y, (0xFF<<24) | (redp[col1]<<16) | (greenp[col1]<<8) | bluep[col1]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// System.out.println("XOR data read (" + readbytes + " bytes)");
|
||||||
|
|
||||||
|
int height = (int)(header.Height/2);
|
||||||
|
|
||||||
|
int rowsize = (int)header.Width / 8;
|
||||||
|
if ((rowsize%4)>0)
|
||||||
|
{
|
||||||
|
rowsize += 4 - (rowsize%4);
|
||||||
|
}
|
||||||
|
|
||||||
|
// System.out.println("rowsize = " + rowsize);
|
||||||
|
int[] andbytes = new int[rowsize * height ];
|
||||||
|
|
||||||
|
for (int i=0; i<andbytes.length; i++)
|
||||||
|
andbytes[i] = in.readUByte();
|
||||||
|
|
||||||
|
|
||||||
|
for (int y=height-1; y>=0; y--)
|
||||||
|
{
|
||||||
|
for (int x=0; x<header.Width; x++)
|
||||||
|
{
|
||||||
|
int offset = ((height - (y+1))*rowsize) + (x/8);
|
||||||
|
if ( (andbytes[offset] & (1<<(7-x%8))) != 0)
|
||||||
|
{
|
||||||
|
image.setRGB(x, y, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// for (int i=0; i<andbytes; i++)
|
||||||
|
// {
|
||||||
|
// int pix = in.readUByte();
|
||||||
|
// readbytes++;
|
||||||
|
|
||||||
|
// int xb = (i*8) % (int)header.Width;
|
||||||
|
// int yb = ((int)header.Height/2) - (((i*8) / (int)header.Width)+1);
|
||||||
|
|
||||||
|
// for (int offset=7; offset>=0; offset--)
|
||||||
|
// {
|
||||||
|
// //
|
||||||
|
// // Modify the transparency only if necessary
|
||||||
|
// //
|
||||||
|
// System.out.println("SET AND (" + xb + "," + yb + ")-" + (7-offset));
|
||||||
|
|
||||||
|
// if (((1<<offset) & pix)!=0)
|
||||||
|
// {
|
||||||
|
// int argb = image.getRGB(xb+(7-offset), yb);
|
||||||
|
// image.setRGB(xb+(7-offset), yb, argb & 0xFFFFFF);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// System.out.println("AND data read (" + readbytes + " bytes total)");
|
||||||
|
}
|
||||||
|
|
||||||
|
static private void load32bitsImage(BinaryInputStream in, IconEntry entry, IconHeader header, BufferedImage image) throws Exception {
|
||||||
|
for (int y = (int) ((header.Height) / 2) - 1; y >= 0; y--) {
|
||||||
|
for (int x = 0; x < header.Width; x++) {
|
||||||
|
byte alpha = in.readByte();
|
||||||
|
byte red = in.readByte();
|
||||||
|
byte green = in.readByte();
|
||||||
|
byte blue = in.readByte();
|
||||||
|
|
||||||
|
int pix = (alpha &0xff) | (red &0xff) <<8 | (green &0xff) << 16 | (blue &0xff) << 24;
|
||||||
|
image.setRGB(x, y, pix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static public void main(String[]args) throws Exception
|
||||||
|
{
|
||||||
|
File f = new File(args[0]);
|
||||||
|
Image img = IcoCodec.loadImages(f)[0];
|
||||||
|
// System.out.println("img = " + img);
|
||||||
|
|
||||||
|
javax.swing.JFrame jf = new javax.swing.JFrame("Test");
|
||||||
|
javax.swing.JButton button = new javax.swing.JButton(new javax.swing.ImageIcon(img));
|
||||||
|
jf.getContentPane().add(button);
|
||||||
|
jf.pack();
|
||||||
|
jf.setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user