You guys do understand that modifying the image is pointless, right? It’s just a visual representation of a ZIP data stream. Any attempts to modify it would corrupt the JAR file, guaranteed.
Creating a program to reverse the process would work for the black and white images. (Not that I can figure out anything useful for it.) However, the conversion between RGB and YUV is fraught with rounding errors and would probably screw up the data.
[quote=“jbanes,post:21,topic:26221”]
I don’t think any colour space conversion applies in this case. PNG is a lossless format and it typically uses RGB.
I believe jbanes is refering to his own code for generating the colorized versions.
int Y = ((data & 0xE0) >> 6);
int U = ((data & 0x1C) >> 3);
int V = (data & 0x03);
double R = Math.abs(Y + 1.403 * V);
double G = Math.abs(Y - 0.344 * U - 0.714 * V);
double B = Math.abs(Y + 1.770 * U);
I do know that it is pointless, and I realized it’d work better with b&w, that’s why I suggested using those. I just tnink it’d be interesting to see, letting you convert to images and back (here’s my java source, encrypted. Decompile this: (sending png)). :>
My ARGB version is just fine. Each pixel contains 4 bytes of information and its lossless. You can also embedd some meta information in png files. So, you could write some loader which hooks such a png into the classpath and runs the main class specified in the tEXT chunk.
There had better be some serious geek cred in this. Here you go:
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import java.lang.reflect.*;
import java.net.*;
import java.util.jar.*;
import java.util.zip.*;
import javax.imageio.*;
public class ImageRunner4K
{
public static void main(String[] args) throws Exception
{
int[] buffer = new int[4096];
byte[] array = new byte[4096];
BufferedImage image;
ZipInputStream jarin;
ZipOutputStream jarout;
ZipEntry entry;
int data;
int index;
if(args.length < 1)
{
System.out.println("Usage: java ImageRunner4K <input>\n\nDo not pass the PNG extension.");
return;
}
image = ImageIO.read(new File(args[0]+".png"));
image.getRGB(0, 0, 64, 64, buffer, 0, 64);
for(int i=0; i<buffer.length; i++) array[i] |= (buffer[i] & 0xFF);
jarin = new ZipInputStream(new ByteArrayInputStream(array));
jarout = new ZipOutputStream(new FileOutputStream(args[0]+".jar"));
while(jarin.available() > 0)
{
index = 0;
entry = jarin.getNextEntry();
if(entry == null) break;
array = new byte[(int)entry.getSize()];
while(index < array.length) index += jarin.read(array, index, array.length-index);
jarout.putNextEntry(new ZipEntry(entry.getName()));
jarout.write(array, 0, array.length);
jarout.closeEntry();
}
jarout.close();
jarin.close();
URLClassLoader loader = new URLClassLoader(new URL[]{new File(args[0]+".jar").toURL()});
Manifest manifest = new Manifest(loader.findResource("META-INF/MANIFEST.MF").openStream());
Attributes attributes = manifest.getMainAttributes();
String className = attributes.getValue("Main-Class");
Class gameClass = loader.loadClass(className);
Method method = gameClass.getMethod("main", new Class[]{String[].class});
method.invoke(null, new Object[]{new String[0]});
}
}
It only works on the Grayscale images. You use it by running "java ImageRunner4K " where “name” is the name of the PNG file without the extension. Don’t run this in the same directory where you have your master JAR files or you may be in for a nasty surprise.
Edit: There are test files you can use in this post.
[quote=“Morre,post:30,topic:26221”]
Can you attach the image you’re using to a post? (Click on “Additional Options” below the text area to find the upload options.)
Edit: Never mind. I’ve reproduced it with IceJump4K. It looks like the size data is being stored improperly. I’ll try to find a workaround.
Edit 2: Okay, good news/bad news. I can work around the problem with the ZIP format, but you didn’t mark your class file as public.(Why not?) I’m going to have to muck with the security manager to see if I can forcably grant access.
I’m still working on the security issue (my memory is a bit rusty on working with Policies), but in the meantime, here’s a version that handles badly formed ZIP files:
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import java.lang.reflect.*;
import java.net.*;
import java.util.jar.*;
import java.util.zip.*;
import javax.imageio.*;
public class ImageRunner4K
{
public static void main(String[] args) throws Exception
{
int[] buffer = new int[4096];
byte[] array = new byte[4096];
BufferedImage image;
ZipInputStream jarin;
ZipOutputStream jarout;
ZipEntry entry;
int data;
int index;
if(args.length < 1)
{
System.out.println("Usage: java ImageRunner4K <input>\n\nDo not pass the PNG extension.");
return;
}
image = ImageIO.read(new File(args[0]+".png"));
image.getRGB(0, 0, 64, 64, buffer, 0, 64);
for(int i=0; i<buffer.length; i++) array[i] |= (buffer[i] & 0xFF);
jarin = new ZipInputStream(new ByteArrayInputStream(array));
jarout = new ZipOutputStream(new FileOutputStream(args[0]+".jar"));
entry = jarin.getNextEntry();
while(jarin.available() > 0)
{
index = 0;
if(entry == null) break;
jarout.putNextEntry(new ZipEntry(entry.getName()));
while((data = jarin.read()) >= 0)
{
jarout.write(data);
index++;
}
jarout.closeEntry();
entry = jarin.getNextEntry();
}
jarout.close();
jarin.close();
URLClassLoader loader = new URLClassLoader(new URL[]{new File(args[0]+".jar").toURL()});
Manifest manifest = new Manifest(loader.findResource("META-INF/MANIFEST.MF").openStream());
Attributes attributes = manifest.getMainAttributes();
String className = attributes.getValue("Main-Class");
Class gameClass = loader.loadClass(className);
Method method = gameClass.getMethod("main", new Class[]{String[].class});
method.setAccessible(true);
method.invoke(null, new Object[]{new String[0]});
}
}
Ok, the security issue is fixed. I’ve patched the code in my post above (added “method.setAccessible(true);”) and that grants access to the otherwise protected class.