[Release/Source] ImageSteg - hide one image in another 11-04-2012, 10:39 AM
#1
Hello HC.
This is steganography program. It uses the last 2-4 bits of every pixelcolor to save one image in another. Because the information is in the least significant bits you can't see the hidden image with the eye.
Of course the image quality suffers since some bits are lost in both pictures. Depending on the quality you choose in the program either the hidden image looks good and the image you see looks bad (good quality setting) or the other way around (bad quality setting). Once you have prepared an image, you can reveal the hidden image again. You have to choose the same quality option for extraction that has done the hiding, otherwise you will get whoosh.
Screenshot:
![[Image: bsa9epnd.png]](http://s7.directupload.net/images/110620/bsa9epnd.png)
It also has a CLI which is used if you give parameters (no parameters = GUI):
The main algorithm (excerpt):
LOC:
1029 without empty lines and comments
1273 with empty lines and comments
Download: http://www.file-upload.net/download-6772...g.zip.html
Have fun.
Deque
This is steganography program. It uses the last 2-4 bits of every pixelcolor to save one image in another. Because the information is in the least significant bits you can't see the hidden image with the eye.
Of course the image quality suffers since some bits are lost in both pictures. Depending on the quality you choose in the program either the hidden image looks good and the image you see looks bad (good quality setting) or the other way around (bad quality setting). Once you have prepared an image, you can reveal the hidden image again. You have to choose the same quality option for extraction that has done the hiding, otherwise you will get whoosh.
Screenshot:
![[Image: bsa9epnd.png]](http://s7.directupload.net/images/110620/bsa9epnd.png)
It also has a CLI which is used if you give parameters (no parameters = GUI):
Quote:SYNOPSIS:
java -jar imagesteg.jar -h filename -m filename -o filename [-b bits]
java -jar imagesteg.jar -e filename -o filename [-b bits]
OPTIONS:
-e inputfile to extract, default std input
-o outputfile, default std output
-b bits used for hidden image. 2, 3 or 4 bits
-v print version and exit
-m masking inputfile
-h inputfile to hide
The main algorithm (excerpt):
Code:
package control;
import gui.MainFrame;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import javax.swing.SwingUtilities;
public class ImageSteno {
public static final int ALPHA = 0;
public static final int RED = 1;
public static final int GREEN = 2;
public static final int BLUE = 3;
private BufferedImage mask;
private BufferedImage toHide;
private BufferedImage toExtract;
private Quality quality = Quality.GOOD;
public static void main(String[] args) throws IOException {
try {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
new MainFrame();
}
});
} catch (InterruptedException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
public void setQuality(Quality quality) {
this.quality = quality;
}
public BufferedImage extractHiddenImage() throws NoImageException {
if (toExtract == null) {
throw new NoImageException();
}
return extractHiddenImage(toExtract);
}
public BufferedImage extractHiddenImage(BufferedImage img) {
BufferedImage imgCopy = copyImage(img);
for (int x = 0; x < imgCopy.getWidth(); x++) {
for (int y = 0; y < imgCopy.getHeight(); y++) {
int rgb = imgCopy.getRGB(x, y);
rgb = extractRGB(rgb);
imgCopy.setRGB(x, y, rgb);
}
}
return imgCopy;
}
public static BufferedImage copyImage(BufferedImage image) {
BufferedImage destImage = new BufferedImage(image.getWidth(),
image.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g = destImage.createGraphics();
g.drawImage(image, null, 0, 0);
g.dispose();
return destImage;
}
public BufferedImage hideImage() throws NoImageException {
if (mask == null || toHide == null) {
throw new NoImageException();
}
BufferedImage maskCopy = getScaledInstance(copyImage(mask),
toHide.getWidth(), toHide.getHeight(),
RenderingHints.VALUE_INTERPOLATION_BICUBIC, false);
for (int x = 0; x < toHide.getWidth(); x++) {
for (int y = 0; y < toHide.getHeight(); y++) {
int destRGB = toHide.getRGB(x, y);
int oldRGB = maskCopy.getRGB(x, y);
int newRGB = computeNewRGB(oldRGB, destRGB);
maskCopy.setRGB(x, y, newRGB);
}
}
return maskCopy;
}
private int extractRGB(int rgb) {
int[] rgbArr = getRGBArray(rgb);
for (int i = 1; i <= 3; i++) {
rgbArr[i] = rgbArr[i] & quality.leastBitsSum;
rgbArr[i] = rgbArr[i] << quality.shift;
}
return getRGBFromArray(rgbArr);
}
private int computeNewRGB(int oldRGB, int destRGB) {
int[] dest = getRGBArray(destRGB);
int[] old = getRGBArray(oldRGB);
for (int i = 1; i <= 3; i++) {
old[i] = old[i] & quality.cuttingMask;
dest[i] = dest[i] >> quality.shift;
old[i] += dest[i];
}
return getRGBFromArray(old);
}
private int getRGBFromArray(int[] rgbArr) {
return new Color(rgbArr[RED], rgbArr[GREEN], rgbArr[BLUE]).getRGB();
}
private int[] getRGBArray(int rgb) {
return new int[] { (rgb >> 24) & 0xff, (rgb >> 16) & 0xff,
(rgb >> & 0xff, rgb & 0xff };
}
}
public enum Quality {
GOOD(4), MEDIUM(3), BAD(2);
public int leastBitsSum;
public int shift;
public int cuttingMask;
private Quality(int bits){
computeLeastBitsSum(bits);
computeCuttingMask(bits);
computeShift(bits);
}
private void computeShift(int bits) {
shift = 8 - bits;
}
private void computeLeastBitsSum(int bits) {
leastBitsSum = 0;
for(int i = 0; i < bits; i++){
leastBitsSum += Math.pow(2, i);
}
}
private void computeCuttingMask(int bits) {
cuttingMask = 255 - leastBitsSum;
}
}LOC:
1029 without empty lines and comments
1273 with empty lines and comments
Download: http://www.file-upload.net/download-6772...g.zip.html
Have fun.
Deque


![[+]](https://sinister.li/images/modern/collapse_collapsed.png)
![[Image: 2YpkRjy.png]](http://i.imgur.com/2YpkRjy.png)