Background is black when rotating an image - java

I'm trying to rotate an image using this code:
File imgPath = new File("c:\\tmp\\7.jpg");
BufferedImage src = ImageIO.read(imgPath);
AffineTransform tx = new AffineTransform();
int width = src.getWidth();
int height = src.getHeight();
tx.rotate(radiant ,width, height);
AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BICUBIC);
BufferedImage out = op.filter(src, null);
File outFile = new File("c:\\tmp\\out.jpg");
ImageIO.write(out, "jpg", outFile);
For some reason the background after the rotation is black.
How can make the background white or transparent?

When you are using AffineTransformOp.filter(src, null) for creating new images, the new image uses the same ColorModel as the source image.
Your input image is a jpeg, which means it is not transparent, so the destination image is an RGB image, without the alpha (transparency) level.
When rotated with such a small angle, the image no longer occupies exactly the same bounds, so the background is visible in its edges and because there is no alpha level, it is normal that the background is black.
However, if you save it to a format that supports transparency like gif or png, your image will not display the black background anymore.
ImageIO.write(out, "gif", outFile);
The full code:
try {
File imgPath = new File("d:\\downloads\\about.jpg");
BufferedImage src = ImageIO.read(imgPath);
AffineTransform tx = new AffineTransform();
int width = src.getWidth();
int height = src.getHeight();
tx.rotate(0.02050493823247637, width, height);
AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BICUBIC);
BufferedImage out = op.filter(src, null);
File outFile = new File("d:\\downloads\\about0.gif");
ImageIO.write(out, "gif", outFile);
} catch (Exception e) {
e.printStackTrace();
}
Take a look at this for even more information and tricks.
Here is my image after rotation to gif:

Related

How can i auto-size image when frame is maximised? [duplicate]

I have a PNG image and I want to resize it. How can I do that? Though I have gone through this I can't understand the snippet.
If you have an java.awt.Image, resizing it doesn't require any additional libraries. Just do:
Image newImage = yourImage.getScaledInstance(newWidth, newHeight, Image.SCALE_DEFAULT);
Obviously, replace newWidth and newHeight with the dimensions of the specified image.
Notice the last parameter: it tells the runtime the algorithm you want to use for resizing.
There are algorithms that produce a very precise result, however these take a large time to complete.
You can use any of the following algorithms:
Image.SCALE_DEFAULT: Use the default image-scaling algorithm.
Image.SCALE_FAST: Choose an image-scaling algorithm that gives higher priority to scaling speed than smoothness of the scaled image.
Image.SCALE_SMOOTH: Choose an image-scaling algorithm that gives higher priority to image smoothness than scaling speed.
Image.SCALE_AREA_AVERAGING: Use the Area Averaging image scaling algorithm.
Image.SCALE_REPLICATE: Use the image scaling algorithm embodied in the ReplicateScaleFilter class.
See the Javadoc for more info.
We're doing this to create thumbnails of images:
BufferedImage tThumbImage = new BufferedImage( tThumbWidth, tThumbHeight, BufferedImage.TYPE_INT_RGB );
Graphics2D tGraphics2D = tThumbImage.createGraphics(); //create a graphics object to paint to
tGraphics2D.setBackground( Color.WHITE );
tGraphics2D.setPaint( Color.WHITE );
tGraphics2D.fillRect( 0, 0, tThumbWidth, tThumbHeight );
tGraphics2D.setRenderingHint( RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR );
tGraphics2D.drawImage( tOriginalImage, 0, 0, tThumbWidth, tThumbHeight, null ); //draw the image scaled
ImageIO.write( tThumbImage, "JPG", tThumbnailTarget ); //write the image to a file
Try this:
ImageIcon icon = new ImageIcon(UrlToPngFile);
Image scaleImage = icon.getImage().getScaledInstance(28, 28,Image.SCALE_DEFAULT);
Resize image with high quality:
private static InputStream resizeImage(InputStream uploadedInputStream, String fileName, int width, int height) {
try {
BufferedImage image = ImageIO.read(uploadedInputStream);
Image originalImage= image.getScaledInstance(width, height, Image.SCALE_DEFAULT);
int type = ((image.getType() == 0) ? BufferedImage.TYPE_INT_ARGB : image.getType());
BufferedImage resizedImage = new BufferedImage(width, height, type);
Graphics2D g2d = resizedImage.createGraphics();
g2d.drawImage(originalImage, 0, 0, width, height, null);
g2d.dispose();
g2d.setComposite(AlphaComposite.Src);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ImageIO.write(resizedImage, fileName.split("\\.")[1], byteArrayOutputStream);
return new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
} catch (IOException e) {
// Something is going wrong while resizing image
return uploadedInputStream;
}
}
int newHeight = 150;
int newWidth = 150;
holder.iv_arrow.requestLayout();
holder.iv_arrow.getLayoutParams().height = newHeight;
holder.iv_arrow.getLayoutParams().width = newWidth;
holder.iv_arrow.setScaleType(ImageView.ScaleType.FIT_XY);
holder.iv_arrow.setImageResource(R.drawable.video_menu);
Simple way in Java
public void resize(String inputImagePath,
String outputImagePath, int scaledWidth, int scaledHeight)
throws IOException {
// reads input image
File inputFile = new File(inputImagePath);
BufferedImage inputImage = ImageIO.read(inputFile);
// creates output image
BufferedImage outputImage = new BufferedImage(scaledWidth,
scaledHeight, inputImage.getType());
// scales the input image to the output image
Graphics2D g2d = outputImage.createGraphics();
g2d.drawImage(inputImage, 0, 0, scaledWidth, scaledHeight, null);
g2d.dispose();
// extracts extension of output file
String formatName = outputImagePath.substring(outputImagePath
.lastIndexOf(".") + 1);
// writes to output file
ImageIO.write(outputImage, formatName, new File(outputImagePath));
}
Design jLabel first:
JLabel label1 = new JLabel("");
label1.setHorizontalAlignment(SwingConstants.CENTER);
label1.setBounds(628, 28, 169, 125);
frame1.getContentPane().add(label1); //frame1 = "Jframe name"
Then you can code below code:
ImageIcon imageIcon1 = new ImageIcon(new ImageIcon("add location url").getImage().getScaledInstance(100, 100, Image.SCALE_DEFAULT)); //100, 100 add your own size
label1.setIcon(imageIcon1);

Improving Java ImageIO read/write with PNG that has alpha

I have a large PNG image (600x600) and my application makes the image opaque and writes out the file. The problem is that the performance with ImageIO is terrible. Are there any other alternatives? I require the image to be opaque. Below is what I am doing:
BufferedImage buf = ImageIO.read(localUrl);
float[] scales = {1f, 1f, 1f, 1f}; // R, G, B, A
float[] offsets = {0f, 0f, 0f, 1f}; // R, G, B, A
RescaleOp rescaler = new RescaleOp(scales, offsets, null);
BufferedImage opaque = rescaler.filter(buf, null);
File outputfile = new File(localUrl.getPath());
ImageIO.write(opaque, "png", outputfile);
Using a RescaleOp isn't entirely necessary here if you just want to get rid of transparency. A simpler solution would be drawing the image on a background like so:
Color bgColor = Color.WHITE;
BufferedImage foreground = ImageIO.read(localUrl);
int width = foreground.getWidth();
int height = foreground.getHeight();
BufferedImage background = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = background.createGraphics();
g.setColor(bgColor);
g.fillRect(0, 0, width, height);
g.drawImage(foreground, 0, 0, null);
g.dispose();
File outputfile = new File(localUrl.getPath());
ImageIO.write(background, "png", outputfile);
This seems like a simpler method of doing things and would probably require less processing power, but I doubt there would be a huge difference. If you're not satisfied with the speed the image can be read / written from the hard drive, there's little you can do to speed that up.
With PNGJ:
private static void removeAlpha(File file1,File file2) {
PngReaderByte reader = new PngReaderByte(file1);
ImageInfo info = reader.imgInfo;
PngWriter writer = new PngWriter(file2,info);
writer.setFilterPreserve(true);
writer.setCompLevel(6);
writer.copyChunksFrom(reader.getChunksList(), ChunkCopyBehaviour.COPY_ALL_SAFE);
if( info.bitDepth != 8 ||info.channels!=4) throw new RuntimeException("expected 8bits RGBA ");
while(reader.hasMoreRows()) {
ImageLineByte line = reader.readRowByte();
byte [] buf = line.getScanlineByte();
for(int i=0,j=3;i<info.cols;i++,j+=4)
buf[j]=(byte)255;
writer.writeRow(line);
}
reader.end();
writer.end();
}
I'm not sure if this would enhance the perfomance. Bear in mind, also that (contrarily to Parker Hoyes' answer) this simply kills the alpha channel, but it does not blend with some background color (hence the "original" color will appear in the previously-transparent now-opaque regions).

How to blur a portion of an image with JAVA

How to blur a portion of an image, to hide some privates parts like credit card informations.
I try to use ConvolveOp.class like :
float[] matrix = new float[400];
for (int i = 0; i < 400; i++)
matrix[i] = 1.0f/500.0f;
BufferedImage sourceImage = (BufferedImage) image; ;
BufferedImage destImage = null ;
BufferedImageOp op = new ConvolveOp( new Kernel(20, 20, matrix), ConvolveOp.EDGE_NO_OP, null );
BufferedImage blurredImage = op.filter(sourceImage, destImage);
it seems to work, except that the image is completely blurred.
In the case you want to focus on the application and not on the specifics of image processing, you can use an image processing framework like Marvin. Thus, you can do more with less code.
Input image:
Output image:
Source code:
import static marvin.MarvinPluginCollection.*;
public class PortionBlur {
public PortionBlur(){
// 1. Load image
MarvinImage image = MarvinImageIO.loadImage("./res/credit_card.jpg");
// 2. Create masks for each blurred region
MarvinImageMask mask1 = new MarvinImageMask(image.getWidth(), image.getHeight(), 38,170,345,24);
MarvinImageMask mask2 = new MarvinImageMask(image.getWidth(), image.getHeight(), 52,212,65,24);
MarvinImageMask mask3 = new MarvinImageMask(image.getWidth(), image.getHeight(), 196,212,65,20);
MarvinImageMask mask4 = new MarvinImageMask(image.getWidth(), image.getHeight(), 38,240,200,20);
// 3. Process Image with each mask
GaussianBlur gaussianBlur = new GaussianBlur();
gaussianBlur.load();
gaussianBlur.attributes.set("radius",15);
gaussianBlur.process(image.clone(), image, mask1);
gaussianBlur.process(image.clone(), image, mask2);
gaussianBlur.process(image.clone(), image, mask3);
gaussianBlur.process(image.clone(), image, mask4);
// 4. Save the final image
MarvinImageIO.saveImage(image, "./res/credit_card_out.jpg");
}
public static void main(String[] args) {
new PortionBlur();
System.exit(0);
}
}
Gaussian blur algorithm source code:
https://github.com/gabrielarchanjo/marvinproject/blob/master/marvinproject/dev/MarvinPlugins/src/org/marvinproject/image/blur/gaussianBlur/GaussianBlur.java
I don't know whether this can be done by changing the matrix values, but this should definitely be possible by filtering a subimage, since, according to the BufferedImage.getSubimage() documentation:
The returned BufferedImage shares the same data array as the original image.
So the original BufferedImage should change with code like this:
BufferedImage image = /* ... */;
BufferedImage subImage = image.getSubimage(10, 20, 30, 40); // x, y, width, height
new ConvolveOp(new Kernel(20, 20, matrix), ConvolveOp.EDGE_NO_OP, null).filter(subImage, subImage);
I didn't test this though, and I can imagine that filter doesn't work as expected if source and destination are the same, in which case you could use a copy of the subimage, using the solution from this question:
BufferedImage image = /* ... */;
BufferedImage dest = image.getSubimage(10, 20, 30, 40); // x, y, width, height
ColorModel cm = dest.getColorModel();
BufferedImage src = new BufferedImage(cm, dest.copyData(dest.getRaster().createCompatibleWritableRaster()), cm.isAlphaPremultiplied(), null).getSubimage(0, 0, dest.getWidth(), dest.getHeight());
new ConvolveOp(new Kernel(20, 20, matrix), ConvolveOp.EDGE_NO_OP, null).filter(src, dest);
After that, continue working with image (not subImage, src or dest!)

how to rotate a bufferd-image in java?

I am having a bufferd-image i.e:
BufferedImage buffer = ImageIO.read(new File(file));
now i want to rotate it.. So how i can do it??
Previously i have used the image format i.e:
Image image = ImageIO.read(new File(file));
and could easily rotate a image using:
AffineTransform at = new AffineTransform();
at.rotate(0.5 * angle * Math.PI, width/2, height/2);
But i dont noe how to do it with the bufferd-image?? Can you help me??
Example:
BufferedImage buffer = ImageIO.read(new File(file));
AffineTransform tx = new AffineTransform();
//tx.scale(scalex, scaley);
//tx.shear(shiftx, shifty);
//tx.translate(x, y);
tx.rotate(radians, buffer.getWidth()/2, buffer.getHeight()/2);
AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
buffer = op.filter(buffer, null);
See also:
Rotate an image in java
Rotating BufferedImage instances
AffineTransform truncates image, what do I wrong?

BufferedImage turns all black after scaling via canvas

I have a method which purpose is to receive an image and return it scaled down.
The reason I'm using canvas is that I believe that it will scale the image automatically for me.
After the conversion the outputimage is completely black. Anyone have any clue on how to fix this?
try {
InputStream in = new ByteArrayInputStream(f.getBytes());
BufferedImage image = ImageIO.read(in);
File beforescale = new File("beforescale.jpg");
ImageIO.write(image, "jpg", beforescale); //works
Canvas canvas = new Canvas();
canvas.setSize(100, 100);
canvas.paint(image.getGraphics());
image = canvasToImage(canvas);
File outputfile = new File("testing.jpg");
ImageIO.write(image, "jpg", outputfile); //all black
response.getWriter().print(canvas);
} catch (Exception ex) {
ex.printStackTrace();
}
}
private BufferedImage canvasToImage(Canvas cnvs) {
int w = cnvs.getWidth();
int h = cnvs.getHeight();
int type = BufferedImage.TYPE_INT_RGB;
BufferedImage image = new BufferedImage(w,h,type);
Graphics2D g2 = image.createGraphics();
cnvs.paint(g2);
g2.dispose();
return image;
}
The problem is, here you use canvas#paint(Graphics) to paint the image on the canvas:
canvas.paint(image.getGraphics());
And here you canvas#paint(Graphics) again to paint the canvas on the image:
cnvs.paint(g2);
Obviously one of these two fails. You can only use this method to paint the canvas on the image.
The solution is to use getScaledInstance() on image.
BufferedImage image = ImageIO.read(in);
Image smallerImg = image.getScaledInstance(100,100,Image.SCALE_SMOOTH);
ImageIO.write(smallerImg, "jpg", outputfile);

Categories

Resources