Image crop, Remove unwanted white portion of Image using Java [duplicate] - java

This question already has answers here:
Crop/trim a JPG file with empty space with Java
(3 answers)
Closed 3 years ago.
Image crop, Remove unwanted white portion of Image using Java.
How can we Remove unwanted white portion of Image using Java? I am having image which have plan white region, I want to remove that unused white part of Image apart from my useful main image using JAVA Code. you can get clear idea form below shown image. i need to perform this task using Java code.
Click here to view image

This is a (very) simple example of a brute force method. Basically, it walks the image until the color changes from the desired fill color
This is woefully inefficient. I had thought about using a divide and conquer approach, but I really don't have the time to flesh it out.
import java.awt.Color;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
public class Test {
public static void main(String[] args) throws IOException {
BufferedImage img = ImageIO.read(new File("/Users/swhitehead/Downloads/47hb1.png"));
Rectangle bounds = getBounds(img, Color.WHITE);
System.out.println(bounds);
BufferedImage trimmed = img.getSubimage(bounds.x, bounds.y, bounds.width, bounds.height);
JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(trimmed)));
}
public static Rectangle getBounds(BufferedImage img, Color fillColor) {
int top = getYInset(img, 20, 0, 1, fillColor);
int bottom = getYInset(img, 20, img.getHeight() - 1, -1, fillColor);
int left = getXInset(img, 0, top, 1, fillColor);
int right = getXInset(img, img.getWidth() - 1, top, -1, fillColor);
return new Rectangle(left, top, right - left, bottom - top);
}
public static int getYInset(BufferedImage img, int x, int y, int step, Color fillColor) {
while (new Color(img.getRGB(x, y), true).equals(fillColor)) {
y += step;
}
return y;
}
public static int getXInset(BufferedImage img, int x, int y, int step, Color fillColor) {
while (new Color(img.getRGB(x, y), true).equals(fillColor)) {
x += step;
}
return x;
}
}

You can use an image processing framework to make image manipulation more easy.
In the example below I used Marvin. My approach:
Use gray scale thresholding to separate the white pixels from the rest of the image.
Find the bounding-box of the black segment
Crop the original image using segment detected in previous step.
Input:
Output (board_cropped.png):
Source code:
import static marvin.MarvinPluginCollection.*;
import java.awt.Rectangle;
import marvin.image.MarvinImage;
import marvin.io.MarvinImageIO;
public class BoardSegmentation {
public BoardSegmentation() {
MarvinImage imageOriginal = MarvinImageIO.loadImage("./res/board.png");
MarvinImage image = imageOriginal.clone();
thresholding(image, 250);
Rectangle rect = getBoundingBox(image);
crop(imageOriginal, image, rect.x, rect.y, rect.width, rect.height);
MarvinImageIO.saveImage(image, "./res/board_cropped.png");
}
public Rectangle getBoundingBox(MarvinImage image) {
Rectangle r = new Rectangle();
r.x = -1; r.y = -1; r.width = -1; r.height = -1;
for(int y=0; y<image.getHeight(); y++) {
for(int x=0; x<image.getWidth(); x++) {
if(image.getIntColor(x, y) == 0xFF000000) {
if(r.x == -1 || x < r.x) { r.x = x; }
if(r.width == -1 || x > r.x + r.width) { r.width = x - r.x; }
if(r.y == -1 || x < r.y) { r.y = y; }
if(r.height == -1 || y > r.y + r.height) { r.height = y - r.y; }
}
}
}
return r;
}
public static void main(String[] args) {
new BoardSegmentation();
}
}

Related

Image Processing and comparing in java

I need to compare two images of similar kind but both have different size in JAVA, i.e one has low background width and another one has high background width.
And size of images are also different.
I have attached two files.
In which person and t-shirt are same so I need to show result as Image is Same.
But when I go with pixel wise image matching then it does not show me the true result due to different width of background.
Then I have tried to remove background and then comparing it still same issue.
Please fine the attached images and code.
Please Help
Links to images :
Image one&
Image two
Code:
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import javax.swing.JOptionPane;
public class ImageProcesing extends Canvas {
private static int x1 = 0, y1 = 0;
private static int h, w;
private static final Random random = new Random();
private Color mycolor;
BufferedImage img, img1;
public BufferedImage scaleImage(int WIDTH, int HEIGHT, String filename) {
BufferedImage bi = null;
try {
ImageIcon ii = new ImageIcon(filename);//path to image
h = 512;
w = 512;
bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = (Graphics2D) bi.createGraphics();
g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY));
g2d.drawImage(ii.getImage(), 0, 0, w, h, null);
} catch (Exception e) {
e.printStackTrace();
return null;
}
return bi;
}
public BufferedImage scaleImage2(String filename) {
BufferedImage bi = null;
try {
ImageIcon ii = new ImageIcon(filename);//path to image
bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = (Graphics2D) bi.createGraphics();
g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY));
g2d.drawImage(ii.getImage(), 0, 0, w, h, null);
} catch (Exception e) {
e.printStackTrace();
return null;
}
return bi;
}
public ImageProcesing() {
try {
this.img = scaleImage(512, 512, "D:\\I Tech Solutions\\Rahul Ratda\\Experiments\\1.jpeg");
this.img1 = scaleImage2("D:\\I Tech Solutions\\Rahul Ratda\\Experiments\\3.jpeg");
} catch (Exception ex) {
Logger.getLogger(ImageProcesing.class.getName()).log(Level.SEVERE, null, ex);
}
}
#Override
public void paint(Graphics g) {
int n = 0, k = 0, l = 0;
int tp = 0;
super.paint(g);
Color oldColor = new Color(img1.getRGB(0, 0));
for (int x = 0; x < h; x++) {
tp = 0;
w=512;
for (int y = 0; y < w; y++) {
oldColor = new Color(img1.getRGB(y, x));
mycolor = new Color(img.getRGB(y, x));
if (tp == 0 && oldColor.equals(Color.WHITE)) {
continue;
} else {
if (tp == 0) {
tp = 1;
w = w - y;
}
k++;
if ((mycolor.equals(oldColor))) {
g.setColor(mycolor);
g.drawLine(y, x, y, x);
n++;
}
}
}
}
System.out.println("K : "+k+"\n N : "+n);
if (n >= (k * 0.70)) {
System.out.println("Same");
}
else
System.out.println("Not Same");
/* oldColor=new Color(img1.getRGB(0,0));
for(int i = 0 ; i < WIDTH1; i++) {
for(int y = 0; y < HEIGHT1; y++) {
mycolor=new Color(img1.getRGB(i,y));
if((mycolor.equals(oldColor))){
y1++;
g.setColor(mycolor);
g.drawLine(i, y, i, y);
}
else
oldColor=mycolor;
}
}*/
/*if(x1>y1)
{
if(x1*0.6<y1)
JOptionPane.showMessageDialog(null,"Images are More than 60% Equal.");
else
JOptionPane.showMessageDialog(null,"Images are Less than 60% Equal.");
}
else{
if(y1*0.6<x1)
JOptionPane.showMessageDialog(null,"Images are More than 60% Equal.");
else
JOptionPane.showMessageDialog(null,"Images are Less than 60% Equal.");
}*/
}
/* private Color randomColor() {
return new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256));
}*/
public static void main(String[] args) {
JFrame frame = new JFrame();
System.out.println("width = " + w);
System.out.println("height = " + h);
frame.setSize(1000, 1000);
frame.add(new ImageProcesing());
frame.setVisible(true);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
}
You can develop your own algorithm for this kind of structure.
As I can see that background of your images are white so first of all you perform background removal operation on your images.
Then you resize your image to lower level like 256x256 or something likethat.
No you have only object in the image as color is already moved out.
So you can go with your pixel by pixel comparison and keeping thrshold of 84-90% would give you expected result which you want.
Direct image comparison by pixel by pixel will not work as images are different in size as well as backgrounds space is also different and also objects size varies.
You need to apply some image processing technique like histogram before comparing the images. Java API of opencv is a nice tool for such operations.See the link

Drawing fully transparent "white" in Java BufferedImage

This might sound like a bit of strange title, but bear with me, there is a reason:
I am trying to generate a white glow around a text on a gray background.
To generate the glow, I created a new BufferedImage that's bigger than the text, then I drew the text in white onto the canvas of the image and ran a Gaussian Blur over the image via a ConvolveOp, hoping for something like this:
At first I was a bit surprised when the glow turned out darker than the gray background of the text:
But after a bit of thinking, I understood the problem:
The convolution operates on each color channel (R, G, B, and A) independently to calculate the blurred image. The transparent background of the picture has color value 0x00000000, i.e. a fully transparent black! So, when the convolution filter runs over the image, it not only blends the alpha value, but also mixes the black into the RGB values of the white pixels. This is why the glow comes out dark.
To fix this, I need to initialize the image to 0x00FFFFFF, i.e. a fully transparent white instead, but if I just set that color and fill a rectangle with it, it simply does nothing as Java says "well, it's a fully transparent rectangle that you're drawing! That's not going to change the image... Let me optimize that away for you... Done... You're welcome.".
If I instead set the color to 0x01FFFFFF, i.e. an almost fully transparent white, it does draw the rectangle and the glow looks beautiful, except I end up with a very faint white box around it...
Is there a way I can initialize the image to 0x00FFFFFF everywhere?
UPDATE:
I found one way, but it's probably as non-optimal as you can get:
I draw an opaque white rectangle onto the image and then I run a RescaleOp over the image that sets all alpha values to 0. This works, but it's probably a terrible approach as far as performance goes.
Can I do better somehow?
PS: I'm also open to entirely different suggestions for creating such a glow effect
The main reason why the glow appeared darker with your initial approach is most likely that you did not use an image with a premultiplied alpha component. The JavaDoc of ConvolveOp contains some information about how the alpha component is treated during a convolution.
You could work around this with an "almost fully transparent white". But alternatively, you may simply use an image with premultiplied alpha, i.e. one with the type TYPE_INT_ARGB_PRE.
Here is a MCVE that draws a panel with some text, and some pulsing glow around the text (remove the timer and set a fixed radius to remove the pulse - I couldn't resist playing around a little here ...).
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class TextGlowTest
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
createAndShowGUI();
}
});
}
private static void createAndShowGUI()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(new TextGlowPanel());
f.setSize(300,200);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
class TextGlowPanel extends JPanel
{
private BufferedImage image;
private int radius = 1;
TextGlowPanel()
{
Timer t = new Timer(50, new ActionListener()
{
long startMillis = -1;
#Override
public void actionPerformed(ActionEvent e)
{
if (startMillis == -1)
{
startMillis = System.currentTimeMillis();
}
long d = System.currentTimeMillis() - startMillis;
double s = d / 1000.0;
radius = (int)(1 + 15 * (Math.sin(s * 3) * 0.5 + 0.5));
repaint();
}
});
t.start();
}
#Override
protected void paintComponent(Graphics gr)
{
super.paintComponent(gr);
gr.setColor(Color.GRAY);
int w = getWidth();
int h = getHeight();
gr.fillRect(0, 0, w, h);
if (image == null || image.getWidth() != w || image.getHeight() != h)
{
// Must be prmultiplied!
image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE);
}
Graphics2D g = image.createGraphics();
Font font = g.getFont().deriveFont(70.0f).deriveFont(Font.BOLD);
g.setFont(font);
g.setComposite(AlphaComposite.Src);
g.setColor(new Color(255,255,255,0));
g.fillRect(0,0,w,h);
g.setComposite(AlphaComposite.SrcOver);
g.setColor(new Color(255,255,255,0));
g.fillRect(0,0,w,h);
g.setColor(Color.WHITE);
g.drawString("Glow!", 50, 100);
image = getGaussianBlurFilter(radius, true).filter(image, null);
image = getGaussianBlurFilter(radius, false).filter(image, null);
g.dispose();
g = image.createGraphics();
g.setFont(font);
g.setColor(Color.BLUE);
g.drawString("Glow!", 50, 100);
g.dispose();
gr.drawImage(image, 0, 0, null);
}
// From
// http://www.java2s.com/Code/Java/Advanced-Graphics/GaussianBlurDemo.htm
public static ConvolveOp getGaussianBlurFilter(
int radius, boolean horizontal)
{
if (radius < 1)
{
throw new IllegalArgumentException("Radius must be >= 1");
}
int size = radius * 2 + 1;
float[] data = new float[size];
float sigma = radius / 3.0f;
float twoSigmaSquare = 2.0f * sigma * sigma;
float sigmaRoot = (float) Math.sqrt(twoSigmaSquare * Math.PI);
float total = 0.0f;
for (int i = -radius; i <= radius; i++)
{
float distance = i * i;
int index = i + radius;
data[index] =
(float) Math.exp(-distance / twoSigmaSquare) / sigmaRoot;
total += data[index];
}
for (int i = 0; i < data.length; i++)
{
data[i] /= total;
}
Kernel kernel = null;
if (horizontal)
{
kernel = new Kernel(size, 1, data);
}
else
{
kernel = new Kernel(1, size, data);
}
return new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
}
}
I've found that clearRect should paint a transparent color.
g.setBackground(new Color(0x00FFFFFF, true));
g.clearRect(0, 0, img.getWidth(), img.getHeight());
You should also be able to force the BufferedImage to fill with a transparent color by setting the pixel data directly.
public static void forceFill(BufferedImage img, int rgb) {
for(int x = 0; x < img.getWidth(); x++) {
for(int y = 0; y < img.getHeight(); y++) {
img.setRGB(x, y, rgb);
}
}
}
It is not clearly documented but I tested it and setRGB appears to accept an ARGB value.

Is there a "fill" function for arbitrary shapes in javafx?

I need to know in which way I can color the following image (PNG) by using JavaFX. This image is currently included in a ImageView of JavaFX:
I want to color region 1 blue, the second one red, and the last two purple. How can I do this in JavaFX? Isn't there some kind of function as in Windows Paint? (You know, the painting bucket that fills a certain area with a color between borders).
Suggested Approach
You can use a flood fill algorithm.
Sample Code
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Point2D;
import javafx.scene.Scene;
import javafx.scene.image.*;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import java.util.Stack;
public class UnleashTheKraken extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(final Stage stage) {
Image original = new Image(
"http://s12.postimg.org/wofhjvy2h/image_2.jpg"
);
WritableImage updateable = new WritableImage(
original.getPixelReader(),
(int) original.getWidth(),
(int) original.getHeight()
);
Kraken kraken = new Kraken(updateable, Color.WHITE);
kraken.unleash(new Point2D(40, 40), Color.BLUE);
kraken.unleash(new Point2D(40, 100), Color.RED);
kraken.unleash(new Point2D(100, 100), Color.GREEN);
kraken.unleash(new Point2D(120, 40), Color.YELLOW);
ImageView originalView = new ImageView(original);
ImageView filledView = new ImageView(updateable);
HBox layout = new HBox(10, originalView, filledView);
layout.setPadding(new Insets(10));
stage.setScene(new Scene(layout));
stage.show();
}
class Kraken {
private final WritableImage image;
private final Color colorToFill;
// tolerance for color matching (on a scale of 0 to 1);
private final double E = 0.3;
public Kraken(WritableImage image, Color colorToFill) {
this.image = image;
this.colorToFill = colorToFill;
}
public void unleash(Point2D start, Color color) {
PixelReader reader = image.getPixelReader();
PixelWriter writer = image.getPixelWriter();
Stack<Point2D> stack = new Stack<>();
stack.push(start);
while (!stack.isEmpty()) {
Point2D point = stack.pop();
int x = (int) point.getX();
int y = (int) point.getY();
if (filled(reader, x, y)) {
continue;
}
writer.setColor(x, y, color);
push(stack, x - 1, y - 1);
push(stack, x - 1, y );
push(stack, x - 1, y + 1);
push(stack, x , y + 1);
push(stack, x + 1, y + 1);
push(stack, x + 1, y );
push(stack, x + 1, y - 1);
push(stack, x, y - 1);
}
}
private void push(Stack<Point2D> stack, int x, int y) {
if (x < 0 || x > image.getWidth() ||
y < 0 || y > image.getHeight()) {
return;
}
stack.push(new Point2D(x, y));
}
private boolean filled(PixelReader reader, int x, int y) {
Color color = reader.getColor(x, y);
return !withinTolerance(color, colorToFill, E);
}
private boolean withinTolerance(Color a, Color b, double epsilon) {
return
withinTolerance(a.getRed(), b.getRed(), epsilon) &&
withinTolerance(a.getGreen(), b.getGreen(), epsilon) &&
withinTolerance(a.getBlue(), b.getBlue(), epsilon);
}
private boolean withinTolerance(double a, double b, double epsilon) {
return Math.abs(a - b) < epsilon;
}
}
}
Answers to additional questions
But wouldn't the image be colored pixel by pixel?
Yes, that's the point, you need to shade the pixels. Everything in computer graphics with bitmapped displays eventually comes down to coloring pixels.
Is this an efficient way in coloring?
It's instantaneous (as far as I can tell) on the sample image you provided. Space-wise it takes up some memory, but all such algorithms will use memory. The sample code I provided is not the most efficient flood fill shading algorithm which could be devised (time or space wise). The wikipedia page I linked has alternate more efficient (and more complicated) algorithms you could apply if you needed to.
Alternate Approach
If you have a cut-out stencil shape for each area, you could stack the stencils and apply ColorAdjust effects to them (such as in: How to change color of image in JavaFX). The ColorAdjust is (likely) a hardware accelerated effect. This alternate is not a general approach though as it requires you to know the stencil shapes.
Shape circle = new Circle(x,y,r);
Shape rect = new Rectangle(x,y,w,h);
Shape region1 = Shape.subtract(circle, rect);// to "cut" the rect away from a circle.
// You'll need to do this twice for each piece.
region1 = Shape.subtract(region1,anotherRect);
region1.setFill(Color.BLUE);
// Then simply add your shape to a node and set it's translation.
The way this works is that where the rectangle overlaps the circle, that part of the circle will be removed.

How to change the brightness of an Image

My Question: I want to be able to change the brightness of a resource image and have three instances of it as ImageIcons. One at 50% brightness (so darker), another at 75% brightness (a little brighter), and finally another at 100% brightness (the same as the original image). I also want to preserve transparency.
What I've tried: I've searched around and it looks like the best solution is using RescaleOp, but I just can't figure it out. I don't know what the scaleFactor and the offset is all about. Here's my code for what I've tried.
public void initialize(String imageLocation, float regularBrightness, float focusedBrightness, float pressedBrightness, String borderTitle) throws IOException {
BufferedImage bufferedImage = ImageIO.read(ButtonIcon.class.getResource(imageLocation));
setRegularIcon(getAlteredImageIcon(bufferedImage, regularBrightness));
setFocusedIcon(getAlteredImageIcon(bufferedImage, focusedBrightness));
setPressedIcon(getAlteredImageIcon(bufferedImage, pressedBrightness));
setTitle(borderTitle);
init();
}
private ImageIcon getAlteredImageIcon(BufferedImage bufferedImage, float brightness) {
RescaleOp rescaleOp = new RescaleOp(brightness, 0, null);
return new ImageIcon(rescaleOp.filter(bufferedImage, null));
}
The call would be something like this:
seeATemplateButton.initialize("/resources/templateIcon-regular.png", 100f, 75f, 50f, "See A Template");
//I think my 100f, 75f, 50f variables need to change, but whenever I change them it behaves unexpectedly (changes colors and stuff).
What happens with that code: The image appears "invisible" I know it's there because it's on a JLabel with a mouse clicked event on it and that works just fine. If I just skip the brightness changing part and say setRegularIcon(new ImageIcon(Button.class.getResource(imageLocation)); it works just fine, but obviously it's not any darker.
What I think I need: Some help understanding what offset, scaleFactor, and the filter method mean/do, and consequently what numbers to give for the brightness variable.
Any help would be greatly appreciated! Thanks!
The doc says:
The pseudo code for the rescaling operation is as follows:
for each pixel from Source object {
for each band/component of the pixel {
dstElement = (srcElement*scaleFactor) + offset
}
}
It's just a linear transformation on every pixel. The parameters for that transformation are scaleFactor and offset. If you want 100% brightness, this transform must be an identity, i.e. dstElement = srcElement. Setting scaleFactor = 1 and offset = 0 does the trick.
Now suppose you want to make the image darker, at 75% brightness like you say. That amounts to multiplying the pixel values by 0.75. You want: dstElement = 0.75 * srcElement. So setting scaleFactor = 0.75 and offset = 0 should do the trick. The problem with your values is that they go from 0 to 100, you need to use values between 0 and 1.
I would suggest just writing over the image with a semi-transparent black.
Assuming you want to write directly on the image:
Graphics g = img.getGraphics();
float percentage = .5f; // 50% bright - change this (or set dynamically) as you feel fit
int brightness = (int)(256 - 256 * percentage);
g.setColor(new Color(0,0,0,brightness));
g.fillRect(0, 0, img.getWidth(), img.getHeight());
Or if you're just using the image for display purposes, do it in the paintComponent method. Here's an SSCCE:
import java.awt.*;
import java.awt.image.*;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
public class ImageBrightener extends JPanel{
BufferedImage img;
float percentage = 0.5f;
public Dimension getPreferredSize(){
return new Dimension(img.getWidth(), img.getHeight());
}
public ImageBrightener(){
try {
img = ImageIO.read(new URL("http://media.giantbomb.com/uploads/0/1176/230441-thehoff_super.jpeg"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(img, 0, 0, this);
int brightness = (int)(256 - 256 * percentage);
g.setColor(new Color(0,0,0,brightness));
g.fillRect(0, 0, getWidth(), getHeight());
}
public static void main(String[] args){
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new ImageBrightener());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
EDIT
Assuming the same code as above, you can manipulate everything besides the Alpha by messing with the rasterizer. Here's an example (paint shadedImage instead of img if using this exmaple). Please note this doesn't catch edge cases of RGB values greater than 256 and less than 0.
img = ImageIO.read(new URL("http://media.giantbomb.com/uploads/0/1176/230441-thehoff_super.jpeg"));
shadedImage = new BufferedImage(img.getWidth(), img.getWidth(), BufferedImage.TYPE_INT_ARGB);
shadedImage.getGraphics().drawImage(img, 0, 0, this);
WritableRaster wr = shadedImage.getRaster();
int[] pixel = new int[4];
for(int i = 0; i < wr.getWidth(); i++){
for(int j = 0; j < wr.getHeight(); j++){
wr.getPixel(i, j, pixel);
pixel[0] = (int) (pixel[0] * percentage);
pixel[1] = (int) (pixel[1] * percentage);
pixel[2] = (int) (pixel[2] * percentage);
wr.setPixel(i, j, pixel);
}
}
A few more examples for study:
AlphaTest rescales just the alpha transparency of an image between zero and one with no offsets. Coincidentally, it also resamples the image to three-quarter size.
RescaleOpTest does the same using a fixed scale and no offsets.
RescaleTest scales all bands of an image between zero and two with no offsets.
As noted in the API, the scale and offset are applied to each band as the slope and y-intercept, respectively, of a linear function.
dstElement = (srcElement*scaleFactor) + offset
Basic logic is take RGB value of each pixel ,add some factor to it,set it again to resulltant matrix(Buffered Image)
import java.io.*;
import java.awt.Color;
import javax.imageio.ImageIO;
import java.io.*;
import java.awt.image.BufferedImage;
class psp{
public static void main(String a[]){
try{
File input=new File("input.jpg");
File output=new File("output1.jpg");
BufferedImage picture1 = ImageIO.read(input); // original
BufferedImage picture2= new BufferedImage(picture1.getWidth(), picture1.getHeight(),BufferedImage.TYPE_INT_RGB);
int width = picture1.getWidth();
int height = picture1.getHeight();
int factor=50;//chose it according to your need(keep it less than 100)
for (int y = 0; y < height ; y++) {//loops for image matrix
for (int x = 0; x < width ; x++) {
Color c=new Color(picture1.getRGB(x,y));
//adding factor to rgb values
int r=c.getRed()+factor;
int b=c.getBlue()+factor;
int g=c.getGreen()+factor;
if (r >= 256) {
r = 255;
} else if (r < 0) {
r = 0;
}
if (g >= 256) {
g = 255;
} else if (g < 0) {
g = 0;
}
if (b >= 256) {
b = 255;
} else if (b < 0) {
b = 0;
}
picture2.setRGB(x, y,new Color(r,g,b).getRGB());
}
}
ImageIO.write(picture2,"jpg",output);
}catch(Exception e){
System.out.println(e);
}
}}

Making a Certain Color on a BufferedImage Become Transparent

A very similar question that has been answered: How to make a color transparent in a BufferedImage and save as PNG
Unfortunately I couldn't formulate an answer for myself out of that source.
Q: I draw a BufferedImage to my Canvas and would simply like to create a method that turns every pixel with the a certain color (in this case: [214, 127, 255] / 0xD67FFF) into a transparent one. The BufferedImage is of type ARGB.
I do not want to save the BufferedImage as a file, simply display it on my canvas.
Thanks in advance.
Iterate over all the pixels and perform the check and make transparent.
for (int y = 0; y < image.getHeight(); ++y) {
for (int x = 0; x < image.getWidth(); ++x) {
int argb = image.getRGB(x, y);
if ((argb & 0x00FFFFFF) == 0x00D67FFF)
{
image.setRGB(x, y, 0);
}
}
}
Make sure the BufferedImage uses an alpha channel, otherwise it will become black.
Note that this will affect your original image.
Edit: Note that I changed the check. Therefor it wouldn't have worked because of I assume your pixels were solid (alpha = 255).
(0xFFD67FFF & 0x00FFFFFF) will result in 0x00D67FFF
And, (0x00D67FFF == 0x00D67FFF)
For a complete solution, like loading, processing and writing, you can use this code:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class TransparentConverter {
private static final Color backColor = Color.GREEN;
private static final int THRESHOLD = 70;
private static final int TRANSPARENT = 0; // 0x00000000;
static File base = new File("C:\\images");
static File base2 = new File("C:\\images2");
public static void main(String[] args) throws IOException {
System.out.println("TransparentConverter.main()");
for (File file : base.listFiles()) {
System.out.println(file);
BufferedImage initImage = ImageIO.read(file);
int width = initImage.getWidth(null),
height = initImage.getHeight(null);
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics g = image.getGraphics();
g.drawImage(initImage, 0, 0, null);
//System.out.println("before: " + image.getRGB(0, 0));
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int pixel = image.getRGB(x, y);
Color color = new Color(pixel);
int dr = Math.abs(color.getRed() - backColor.getRed()),
dg = Math.abs(color.getGreen() - backColor.getGreen()),
db = Math.abs(color.getBlue() - backColor.getBlue());
if (dr < THRESHOLD && dg < THRESHOLD && db < THRESHOLD) {
image.setRGB(x, y, TRANSPARENT);
}
}
}
//System.out.println(" after: " + image.getRGB(0, 0));
file = new File(base2, file.getName());
//System.out.println(" " + file);
ImageIO.write(image, "png", file);
}
}
}

Categories