I'm pasting plenty of face images (face_50xx.png) to the one big canvas (Faces.png) using drawImage(),
but every face turns into the whole black.
Here is my source code:
import java.io.*;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.Color;
public class maa{
static BufferedImage in;
static BufferedImage out;
public static void main(String[] args) {
String A = "face_";
String B = "png";
int j = 0;
try{
in = ImageIO.read(new File(A + 5001 + "." + B));
}
catch(java.io.IOException e){
}
out = new BufferedImage(1920, 14592, in.getType());
for(int i = 1; i < 760; i++){
String num;
j = i + 5000;
num = Integer.toString(j);
try{
in = ImageIO.read(new File("face_" + num + "." + "png"));
Graphics g = in.getGraphics();
g.drawImage(out, (i%10)*192, (i/10)*192, null);
}
catch(java.io.IOException e){
continue;
}
}
try{
ImageIO.write(out,"png",new File("Faces." + B));
}
catch(java.io.IOException e){
}
}
}
Please teach me what's the problem. Thanks.
You are doing absolutely nothing to the out image, and so when you write it to file, it will be blank.
You appear to be drawing on the wrong image. You want to get the Graphics object, g, from
the out image, and draw the in images onto out.
You should never ignore exceptions as you are doing. At least print out a stack trace:
e.g.,
catch(IOException e) {
e.printStackTrace();
}
The basic structure of your program should be:
create out image
get Out's Graphics object, g
for Loop through all of the `in` images
Draw each in image onto out using out's Graphics context, g
end for loop
dispose of g
Write the out image to file
Edit: You state in comment,
Graphics g = in.getGraphics(); is a command that transporting the in image into g, isn't it?
No, you've got things backwards. Think of the Graphics object, g, as a pen that allows you to draw onto the image that you obtained it from. So a Graphics object, g, from an in image allows me to draw on the in image.
replace:
Graphics g = in.getGraphics();
g.drawImage(out, (i%10)*192, (i/10)*192, null);
by: in.getGraphics().drawImage(out, (i%10)*192, (i/10)*192, null);
Related
This code works, it reads a file in byte type and after assigning the image it creates a copy in the directory where the other part is located with a different name, I must do the same, create a new file, I just have to make it rotate on the X and Y axes as the final 180 degree image without creating a library to do the job.
Can you help me with the code or madnar information
Thank you!
public class BMPRotations {
public static void main(String[] args) throws IOException {
int contador=0;
int datos_entrada[] = new int[921655];
try {
FileInputStream archivo_lectura = new FileInputStream("Ruta__picture.bmp");
boolean final_ar = false;
while(!final_ar) {
int byte_entrada = archivo_lectura.read();
if(byte_entrada!=-1)
datos_entrada[contador]=byte_entrada;
else
final_ar=true;
//Muestra todos los bytes
//System.out.println(datos_entrada[contador]);
contador++;
}
archivo_lectura.close();
}catch(IOException e) {
System.out.print("Error");
}
System.out.print("Bystes de la imagen: " + contador);
crea_fichero(datos_entrada);
}
static void crea_fichero(int datos_nuevo_fichero[]) {
try {
FileOutputStream fichero_nuevo = new FileOutputStream("Ruta_picture.bmp");
for(int i=0; i<datos_nuevo_fichero.length;i++) {
fichero_nuevo.write(datos_nuevo_fichero[i]);
}
fichero_nuevo.close();
}catch(IOException e) {
System.out.println("Error ");
}
}
Here is a reference image.
640X480 in 24-bit format
https://i.stack.imgur.com/pz4A4.png
This isn't a full answer but I hope it points you in right direction for what looks like homework.
What you have implemented so far is simply copying a file with hard-coded size 921655, and does not deal with an image - just any file. You could replace the entire program with:
File input = new File("Ruta__picture.bmp");
File output = new File("Ruta_picture.bmp");
Files.copy(input.toPath(), output.toPath(), StandardCopyOption.REPLACE_EXISTING);
To deal with images, look at javax.imageio.ImageIO class. This shows how to load any supported JDK image type and write it back:
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
BufferedImage image = ImageIO.read(input);
// TODO: TRANSFORM "image" here
BufferedImage modified = image;
ImageIO.write(modified , "bmp", output);
Note that ImageIO.write supports other types such as "jpg".
I am working with a Java to create a small applet. I am interested if there is a way I can "scan" an image to get the color values of a certain pixel. I would prefer to not have to display the image on the screen, but if you find that is the only way, please tell me. I would ideally like to be able to have my applet scan an image file and create an image on the screen according to the image. Please try to keep the answers a little bit simple, as I am still getting used to all of the technical terms.
Thanks,
~Rane
What I have so far:
import java.applet.Applet;
public class LoadGuideImage {
Applet applet;
public LoadGuideImage(Applet applet){
this.applet = applet;
}
public String getPixelColor(String pathToImage, int Xpix, int Ypix){
int redC = 0;
int greenC = 0;
int blueC = 0;
//Get Pixel colors here and save to ints
return redC + " " + greenC + " " + blueC;
}
}
Are you suggesting something like this 'the other guy'?:
BufferedImage img = (BufferedImage) getImage(pathToImage);
System.out.println("Color: " + img.getRGB(3, 3));
getImage method:
public Image getImage(String path) {
Image img;
URL url = null;
try {
url = applet.getDocumentBase();
} catch (Exception e){
// TODO: handle exception
}
img = applet.getImage(url, path);
return img;
}
nice name by the way. So I was in the same position a while ago.
use this for your get image method, just tweak it and use it to benefit you:
public class ImageLoader {
public BufferedImage load(String path){
try {
return ImageIO.read(getClass().getResource(path));
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
I have a been making a game that uses individual pixels to load those pixels and then put tiles where certain pixels are located in the map. If you would like to take my code snippet from there let me know and ill hook you up :P
I want to XOR two images pixel by pixel. I am using the following code.
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.*;
import java.io.IOException;
import javax.imageio.ImageIO;
import java.util.Scanner;
import java.security.*;
import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
public class sefi
{
public static void main(String[] args) throws Exception
{
encdec ed = new encdec();
String plainimagename = args[0];
String keyfilename = args[1];
String choice = args[2];
BufferedImage bikey = ImageIO.read(new File(keyfilename));
BufferedImage biplain = ImageIO.read(new File(plainimagename));
BufferedImage resizedImage = new BufferedImage(biplain.getWidth(), biplain.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(bikey, 0, 0, biplain.getWidth(), biplain.getHeight(), null);
g.dispose();
ImageIO.write(resizedImage, "jpg", new File("resizeimage.jpg"));
if(choice.equals("enc"))
{
ed.encrypt(resizedImage,biplain);
}
else if(choice.equals("dec"))
{
ed.decrypt(resizedImage,biplain);
}
}
}
class encdec
{
public void encrypt(BufferedImage bikey, BufferedImage biplain) throws Exception
{
BufferedImage xoredimage = xor(bikey, biplain);
File xored = new File("xored.jpg");
ImageIO.write(xoredimage, "JPEG", xored);
}
public void decrypt(BufferedImage bikey, BufferedImage biplain) throws Exception
{
BufferedImage xoredimage = xor(bikey, biplain);
File xored = new File("newplain.jpg");
ImageIO.write(xoredimage, "JPEG", xored);
}
private BufferedImage xor(BufferedImage image1, BufferedImage image2) throws Exception
{
BufferedImage outputimage = new BufferedImage(image1.getWidth(), image1.getHeight(), BufferedImage.TYPE_INT_RGB);
for (int y = 0; y < image1.getHeight(); y++)
{
for (int x = 0; x < image1.getWidth(); x++)
{
outputimage.setRGB(x,y,((image1.getRGB(x, y))^(image2.getRGB(x, y))));
System.out.println("one:" + image1.getRGB(x, y) + "\ttwo:" + image2.getRGB(x, y) + "\txor:" + ((image1.getRGB(x, y))^(image2.getRGB(x, y))));
System.out.println("one:" + Integer.toBinaryString(image1.getRGB(x, y)) + "\ttwo:" + Integer.toBinaryString(image2.getRGB(x, y)) + "\txor:" + Integer.toBinaryString((image1.getRGB(x, y)^image2.getRGB(x, y))));
}
}
return outputimage;
}
}
First time I run this code where image1 is a 4-pixel colored image and image2 is a 4-pixel white image, I get the output as:
input: #java sefi white.jpg key.jpg enc
one:-201053 two:-1 xor:201052
one:11111111111111001110111010100011 two:11111111111111111111111111111111 xor:110001000101011100
one:-265579 two:-1 xor:265578
one:11111111111110111111001010010101 two:11111111111111111111111111111111 xor:1000000110101101010
one:-664247 two:-1 xor:664246
one:11111111111101011101110101001001 two:11111111111111111111111111111111 xor:10100010001010110110
one:-925624 two:-1 xor:925623
one:11111111111100011110000001001000 two:11111111111111111111111111111111 xor:11100001111110110111
Next time I run with image1 as the xored image file and image 2 as the 4-pixel colored file, which should give me the original white image as output. But I get this as output instead:
Input:#java sefi xored.jpg key.jpg dec
one:-1 two:-16773753 xor:16773752
one:11111111111111111111111111111111 two:11111111000000000000110110000111 xor:111111111111001001111000
one:-1 two:-16773753 xor:16773752
one:11111111111111111111111111111111 two:11111111000000000000110110000111 xor:111111111111001001111000
one:-1 two:-15786601 xor:15786600
one:11111111111111111111111111111111 two:11111111000011110001110110010111 xor:111100001110001001101000
one:-1 two:-15786601 xor:15786600
one:11111111111111111111111111111111 two:11111111000011110001110110010111 xor:111100001110001001101000
If you look at the output we can see that the colors of the xored image from first time has changed.
I am not able to understand why I am getting different color value for the same image file.
There's something wrong with your image selection. If you were selecting the RGB for the generated image then the first pixel would be 110001000101011100 and not 11111111000000000000110110000111.
So my advice is for you to check if you are using the correct images on the second step.
Your code looks ok, although you'd have to paste the whole code for me to have a better idea.
Found the Answer.
It is because I am using JPEG images. JPEG compresses raw image, but when it decompress it does not guarantee to produce the exact same colors as it was before compression. Thus the different color values before and after.
When I used bmp images, I got the same colors before and after.
I am trying to replace some pixels from my source image(PNG format). But i am end up with some confusing result. Basically i am replacing a particular RGB values with black and white colors. Here is my code,
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import javax.imageio.ImageIO;
public class ChangePixel
{
public static void main(String args[]) throws IOException
{
File file = new File(System.getProperty("user.dir"), "D4635.png");
FileInputStream fis = new FileInputStream(file);
BufferedImage image = ImageIO.read(fis);
int[] replaceColors = new int[2];
replaceColors[0] = Color.BLACK.getRGB();
replaceColors[1] = Color.WHITE.getRGB();
Color src = new Color(133, 101, 51);
int srcRGBvalue = src.getRGB();
changeAlg2(image, srcRGBvalue, replaceColors);
}
private static void changeAlg2(BufferedImage image, int srcRGBvalue, int[] replaceColors) throws IOException
{
for (int width = 0; width < image.getWidth(); width++)
{
for (int height = 0; height < image.getHeight(); height++)
{
if (image.getRGB(width, height) == srcRGBvalue)
{
image.setRGB(width, height, ((width + height) % 2 == 0 ? replaceColors[0] : replaceColors[1]));
}
}
}
File file = new File(System.getProperty("user.dir"), "107.png");
ImageIO.write(image, "png", file);
}
}
It changes my source pixels to black and some other color, instead of white. Please advice me, what's going wrong here.
Since this is my first post, I can't able to attach my images. Sorry for the inconvenience.
Edit: I have uploaded the source and the output images in a site. Here is the URL,
Source : http://s20.postimage.org/d7zdt7kwt/D4635.png
Output : http://s20.postimage.org/kdr4vntzx/107.png
Expected output : After the black pixel, white pixel has to come.
Edit : Resolved code as per Jan Dvorak advice,
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import javax.imageio.ImageIO;
public class ChangePixel
{
public static void main(String args[]) throws IOException
{
File file = new File(System.getProperty("user.dir"), "D12014.gif");
FileInputStream fis = new FileInputStream(file);
BufferedImage image = ImageIO.read(fis);
Color src = new Color(223, 170, 66);
int srcRGBvalue = src.getRGB();
int[] replaceColors = new int[2];
replaceColors[0] = Color.MAGENTA.getRGB();
replaceColors[1] = Color.CYAN.getRGB();
changeAlg2(image, srcRGBvalue, replaceColors);
}
private static void changeAlg2(BufferedImage image, int srcRGBvalue, int[] replaceColors) throws IOException
{
BufferedImage image2 = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_RGB);
for (int width = 0; width < image.getWidth(); width++)
{
for (int height = 0; height < image.getHeight(); height++)
{
if (image.getRGB(width, height) == srcRGBvalue)
{
image2.setRGB(width, height, ((width + height) % 2 == 0 ? replaceColors[0] : replaceColors[1]));
}
else
{
image2.setRGB(width, height, image.getRGB(width, height));
}
}
}
File file = new File(System.getProperty("user.dir"), "110.gif");
ImageIO.write(image2, "gif", file);
}
}
Regards
Raja.
Since you are adding colors that are not present in the original image palette, the pixels you are trying to set are clipped to the nearest color in the palette. You need to set a new color mode. Either convert to 24bpp RGB (true-color) or extend the palette with the new colors.
It doesn't seem to be possible to modify an existing BufferedImage ColorModel or assign a new one, but you can create a new buffer and copy the data there. Creating a new BufferedImage with the same Raster might work as well (only if the bit depth does not change?).
If you don't mind, you can always create a True-color image. try:
{
BufferedImage old = image;
image = new BufferedImage(
old.getWidth(),
old.getHeight(),
BufferedImage.TYPE_INT_RGB
);
image.setData(old.getRaster());
} // old is no longer needed
API reference: http://docs.oracle.com/javase/1.4.2/docs/api/java/awt/image/BufferedImage.html
You could try to detect if the image is already in true-color (image.getColorModel() instanceof ???) to avoid having to copy the buffer when not needed.
You could try to extend the existing palette. If that is not possible (there is no palette to start with or there is not enough space), you have to fallback to RGB.
See:
http://docs.oracle.com/javase/1.4.2/docs/api/java/awt/image/BufferedImage.html (getColorModel and the constructor taking a ColorModel and type)
http://docs.oracle.com/javase/1.4.2/docs/api/java/awt/image/IndexColorModel.html (getMapSize, getRGBs and the corresponding constructor)
From seeing your actual palette, you'll need some sort of deduplication logic because your palette is already 256 bytes - the maximum size of a PNG palette. Note that you should not save the image with larger palette than there are colors in the image (especially when you want to add new colors later). your original file could have been saved with a 2-color palette, saving 762 bytes.
Note that you don't gain much from storing the image as indexed as opposed to true-color with the same number of colors. The reason is that the byte stream (palette = 1 byte per pixel, true-color = 3 or 4 bytes per pixel) is losslessly compressed (with DEFLATE) anyways. Indexed can save you a few bytes (or lose you a few bytes, if the palette is big), but it won't reduce the file size to one third.
I am trying to implement a simple class that will allow a user to crop an image to be used for their profile picture. This is a java web application.
I have done some searching and found that java.awt has a BufferedImage class, and this appears (at first glance) to be perfect for what I need. However, it seems that there is a bug in this (or perhaps java, as I have seen suggested) that means that the cropping does not always work correctly.
Here is the code I am using to try to crop my image:
BufferedImage profileImage = getProfileImage(form, modelMap);
if (profileImage != null) {
BufferedImage croppedImage = profileImage
.getSubimage(form.getStartX(), form.getStartY(), form.getWidth(), form.getHeight());
System.err.println(form.getStartX());
System.err.println(form.getStartY());
File finalProfileImage = new File(form.getProfileImage());
try {
String imageType = getImageType(form.getProfileImage());
ImageIO.write(croppedImage, imageType, finalProfileImage);
}
catch (Exception e) {
logger.error("Unable to write cropped image", e);
}
}
return modelAndView;
}
protected BufferedImage getProfileImage(CropImageForm form, Map<String, Object> modelMap) {
String profileImageFileName = form.getProfileImage();
if (validImage(profileImageFileName) && imageExists(profileImageFileName)) {
BufferedImage image = null;
try {
image = getCroppableImage(form, ImageIO.read(new File(profileImageFileName)), modelMap);
}
catch (IOException e) {
logger.error("Unable to crop image, could not read profile image: [" + profileImageFileName + "]");
modelMap.put("errorMessage", "Unable to crop image. Please try again");
return null;
}
return image;
}
modelMap.put("errorMessage", "Unable to crop image. Please try again.");
return null;
}
private boolean imageExists(String profileImageFileName) {
return new File(profileImageFileName).exists();
}
private BufferedImage getCroppableImage(CropImageForm form, BufferedImage image, Map<String, Object> modelMap) {
int cropHeight = form.getHeight();
int cropWidth = form.getWidth();
if (cropHeight <= image.getHeight() && cropWidth <= image.getWidth()) {
return image;
}
modelMap.put("errorMessage", "Unable to crop image. Crop size larger than image.");
return null;
}
private boolean validImage(String profileImageFileName) {
String extension = getImageType(profileImageFileName);
return (extension.equals("jpg") || extension.equals("gif") || extension.equals("png"));
}
private String getImageType(String profileImageFileName) {
int indexOfSeparator = profileImageFileName.lastIndexOf(".");
return profileImageFileName.substring(indexOfSeparator + 1);
}
The form referred to in this code snippet is a simple POJO which contains integer values of the upper left corner to start cropping (startX and startY) and the width and height to make the new image.
What I end up with, however, is a cropped image that always starts at 0,0 rather than the startX and startY position. I have inspected the code to make sure the proper values are being passed in to the getSubimage method, and they appear to be.
Are there simple alternatives to using BufferedImage for cropping an image. I have taken a brief look at JAI. I would rather add a jar to my application than update the jdk installed on all of the production boxes, as well as any development/testing servers and local workstations.
My criteria for selecting an alternative are:
1) simple to use to crop an image as this is all I will be using it for
2) if not built into java or spring, the jar should be small and easily deployable in a web-app
Any suggestions?
Note: The comment above that there is an issue with bufferedImage or Java was something I saw in this posting: Guidance on the BufferedImage.getSubimage(int x, int y, int w, int h) method?
I have used getSubimage() numerous times before without any problems. Have you added a System.out.println(form.getStartX() + " " + form.getStartY()) before that call to make sure they're not both 0?
Also, are you at least getting an image that is form.getWidth() x form.getHeight()?
Do make sure you are not modifying/disposing profileImage in any way since the returned BufferedImage shares the same data array as the parent.
The best way is to just simply draw it across if you want a completely new and independent BufferedImage:
BufferedImage croppedImage = new BufferedImage(form.getWidth(),form.getHeight(),BufferedImage.TYPE_INT_ARGB);
Graphics g = croppedImage.getGraphics();
g.drawImage(profileImage,0,0,form.getWidth(),form.getHeight(),form.getStartX(),form.getStartY(),form.getWidth(),form.getHeight(),null);
g.dispose();
You can do it in this manner as well (code is not 100% tested as I adopted for example from an existing app i did):
import javax.imageio.*;
import java.awt.image.*;
import java.awt.geom.*;
...
BufferedImage img = ImageIO.read(imageStream);
...
/*
* w = image width, h = image height, l = crop left, t = crop top
*/
ColorModel dstCM = img.getColorModel();
BufferedImage dst = new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(w, h), dstCM.isAlphaPremultiplied(), null);
Graphics2D g = dst.createGraphics();
g.drawRenderedImage(img, AffineTransform.getTranslateInstance(-l,-t));
g.dispose();
java.io.File outputfile = new java.io.File(sessionScope.get('absolutePath') + java.io.File.separator + sessionScope.get('lastUpload'));
ImageIO.write(dst, 'png', outputfile);
Thanks for all who replied. It turns out that the problem was not in the cropping code at all.
When I displayed the image to be cropped, I resized it to fit into my layout nicely, then used a javascript cropping tool to figure out the coordinates to crop.
Since I had resized my image, but didn't take the resizing into account when I was determining the cropping coordinates, I ended up with coordinates that appeared to coincide with the top left corner.
I have changed the display to no longer resize the image, and now cropping is working beautifully.