slider.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
int val = slider.getValue();
for(int x = 0; x < image.getWidth(); x++) {
for(int y = 0; y < image.getHeight(); y++) {
image.setPixel(x, y, image.getPixel(x, y).brighter());
frame.repaint();
}
}
}
});
So this is my ChangeListener which I use to change the brightness of the image.
It works decent and the image gets brighter. The problem I'm having is that it doesn't matter what way I move the slider because it gets brighter either way.
The way I want it work is that the image should only get brighter when the slider is moved to the right.
You never use the value of val. Why not do something like this: image brightness slider Java
for(int x = 0; x < image.getWidth(); x++) {
for(int y = 0; y < image.getHeight(); y++) {
Color color = new Color(image.getRGB(x, y));
int r, g, b;
val = slider.getValue();
r = ((color.getRed() + (val/20)) % 255);
b = ((color.getBlue() + (val/20)));
g = ((color.getGreen() + (val/20)) % 255);
if(b > 255) b = 255;
color = new Color(r, g, b);
image.setRGB(x, y, color.getRGB());
}
}
I tested this on a background, not pixel by pixel, and the starting color was blue. You would have to change the code above based on the starting color, because brightness is increased by adding more color. Blue has a starting value of (0, 0, 255), so you cannot add any more blue to increase brightness.
Related
I would like to know how to isolate a certain color in an image and set the rest to gray using java.
So far I managed to do so, but in a hardcode way by looping through all the pixels of the image and then checking the RGB values.
I am using BufferedImage to load the image and the Color class to deal with RGB values.
The isColorRed checks if the color is red or not.
private static boolean isColorRed(Color color) {
int red = color.getRed();
int green = color.getGreen();
int blue = color.getBlue();
return ((red >= 70 && red <= 255) && (green >= 0 && green <= 80) && (blue >= 0 && blue <= 80));
}
The isolateColor method is responsible to set all pixels to grey except for the red ones.
private static void isolateColor(BufferedImage image) {
int width = image.getWidth();
int height = image.getHeight();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
Color c = new Color(image.getRGB(x, y));
if (!isColorRed(c)) {
int red = (int) (c.getRed() * 0.3);
int green = (int) (c.getGreen() * 0.587);
int blue = (int) (c.getBlue() * 0.114);
int gray = red + green + blue;
Color newColor = new Color(gray, gray, gray);
image.setRGB(x, y, newColor.getRGB());
} else {
Color newColor = new Color(c.getRed(), c.getGreen(), c.getBlue());
image.setRGB(x, y, newColor.getRGB());
}
}
}
File file;
try {
file = new File("src/grey.png");
ImageIO.write(image, "png", file);
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
The original image :
After the treatment :
Is there any API built-in or external that can isolate one color or more in a single image
I have implemented a method that applies Black & White over an image and I would like to know what would be the best alternative of the same algorithm but using Threads ?
public static void blackAndWhite()
{
for(int x = 0; x < img.getWidth(); x++)
{
for(int y = 0; y < img.getHeight(); y++)
{
int rgb = Main.img.getRGB(x, y);
Color c = new Color(rgb);
int grey = (int) (0.299 * c.getRed() + 0.587 * c.getGreen() + 0.114*c.getBlue());
Color c2 = new Color(grey, grey, grey);
Main.img.setRGB(x, y, c2.getRGB());
}
}
}
I thought of doing something like this but I get errors regarding 'final' status of x or y
Thread t = new Thread(() -> {
for(int x = 0; x < img.getWidth(); x++)
{
for(int y = 0; y < img.getHeight(); y++)
{
int rgb = Main.img.getRGB(x, y);
Color c = new Color(rgb);
int grey = (int) (0.299 * c.getRed() + 0.587 * c.getGreen() + 0.114*c.getBlue());
Color c2 = new Color(grey, grey, grey);
Main.img.setRGB(x, y, c2.getRGB());
}
}
});
t.start();
try{
t.join();
}catch(InterruptedException ie){
System.out.println(ie.getMessage());
}
Thank you !
i want to paint black and white stripes on the image, switching every 20th column both horizontally and vertically on top of an image while staying inside it's borders. so far i can get a black square with 1 pixel wide vertical stripes. i've tried to at least get skinny white stripes on my horizontal lines by switching things around but it's still vertical.
public void zebraStripes() {
Image img = ImageViewer.getImage();
double numPixelsWide = img.getWidth();
int numPixelsHigh = img.getHeight();
Color c = Color.WHITE;
Color b = Color.BLACK;
double i = numPixelsWide;
if (i % 20 == 0) {
for (int x = 0; x < numPixelsHigh; x++) {
for (int y = 0; y < i; y++) {
img.setPixelColor(y, x, b);
}
for (int z = 19; z < i; z = z + 20) {
img.setPixelColor(z, x, c);
}
}
}
}
// paint black and white stripes (left to right) on the image, switching
// every 20th row
public void jailBird() {
Image img = ImageViewer.getImage();
double numPixelsWide = img.getWidth();
double numPixelsHigh = img.getHeight();
Color c = Color.WHITE;
Color b = Color.BLACK;
double i = numPixelsHigh;
if (i % 20 == 0) {
for (int x = 0; x < numPixelsHigh; x++) {
for (int y = 0; y < i; y++) {
img.setPixelColor(y, x, b);
}
for (int z = 19; z < i; z = z + 20) {
img.setPixelColor(z, x, c);
}
}
}
}
}
how do i get the white stripes to be 20 pixels wide and horizontal?
Not tested! Hope it gets you going.
// paint a 20 pixels wide horizontal line for every 40 pixels
for (int y = 0; y < numPixelsHigh; y += 40) {
// paint a stripe
for (int ys = y; ys < y + 20; ys++) {
for (int x = 0; x < numPixelsWide; x++) {
img.setPixelColor(x, ys, Color.BLACK);
}
}
}
In the body of the Picture class create a new public method named "specialEffect" that has return type void and takes no parameters.
The method should contain four loops that each iterate over the pixels of an image in such a way that each loop iterates through 1/4 of the total number of pixels and performs a different effect as follows:
The first loop is to apply an effect that removes the both the blue and green component from each pixel leaving the red component unchanged.
The next loop continuing from where the last left off is to remove the blue and red component from each pixel leaving the green component unchanged.
The next loop continuing from where the last left off it to remove the green and red component from each pixel leaving the blue component unchanged.
The final loop continuing from where the last off is to convert each pixel to greyscale.
How would I go about doing that? I only know how to divide it in half and change the top part.. not sure how to go about doing sections.
Thanks!
The code below produces this picture:
private static BufferedImage specialEffect(BufferedImage in) {
BufferedImage out = new BufferedImage(in.getWidth(), in.getHeight(),
BufferedImage.TYPE_INT_ARGB);
for (int x = 0; x < out.getWidth() / 2; x++) {
for (int y = 0; y < out.getHeight() / 2; y++) {
Color c = new Color(in.getRGB(x, y));
out.setRGB(x, y, new Color(c.getRed(), 0, 0).getRGB());
}
}
for (int x = out.getWidth() / 2; x < out.getWidth(); x++) {
for (int y = 0; y < out.getHeight() / 2; y++) {
Color c = new Color(in.getRGB(x, y));
out.setRGB(x, y, new Color(0, c.getGreen(), 0).getRGB());
}
}
for (int x = 0; x < out.getWidth() / 2; x++) {
for (int y = out.getHeight() / 2; y < out.getHeight(); y++) {
Color c = new Color(in.getRGB(x, y));
out.setRGB(x, y, new Color(0, 0, c.getBlue()).getRGB());
}
}
for (int x = out.getWidth() / 2; x < out.getWidth(); x++) {
for (int y = out.getHeight() / 2; y < out.getHeight(); y++) {
Color c = new Color(in.getRGB(x, y));
int m = Math.max(c.getRed(),Math.max(c.getGreen(),c.getBlue()));
out.setRGB(x, y, new Color(m, m, m).getRGB());
}
}
return out;
}
public static void main(String[] args) throws IOException {
JFrame frame = new JFrame("Test");
frame.add(new JComponent() {
BufferedImage image = specialEffect(ImageIO.read(new URL("http://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png")));
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
});
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.setVisible(true);
}
I am assuming that your Picture class has the following methods:
int getNumberOfPixels()
float getRValueOfNthPixel(int n)
float getGValueOfNthPixel(int n)
float getBValueOfNthPixel(int n)
void setRValueOfNthPixel(int n, float r)
void setGValueOfNthPixel(int n, float g)
void setBValueOfNthPixel(int n, float b)
If the number of pixels is always a multiple of 4, then one possible implementation of "specialEffect" method would be:
public void specialEffect() {
int n = getNumberOfPixels();
int limit1 = 1 * n / 4;
int limit2 = 2 * n / 4;
int limit3 = 3 * n / 4;
int limit4 = 4 * n / 4;
/*
* The first loop is to apply an effect that removes the both the blue
* and green component from each pixel leaving the red component
* unchanged.
*/
for (int i = 0; i < limit1; i++) {
setBValueOfNthPixel(i, 0);
setGValueOfNthPixel(i, 0);
}
/*
* The next loop continuing from where the last left off is to remove
* the blue and red component from each pixel leaving the green
* component unchanged.
*/
for (int i = limit1; i < limit2; i++) {
setBValueOfNthPixel(i, 0);
setRValueOfNthPixel(i, 0);
}
/*
* The next loop continuing from where the last left off it to remove
* the green and red component from each pixel leaving the blue
* component unchanged.
*/
for (int i = limit2; i < limit3; i++) {
setGValueOfNthPixel(i, 0);
setRValueOfNthPixel(i, 0);
}
/*
* The final loop continuing from where the last off is to convert each
* pixel to greyscale.
*/
for (int i = limit3; i < limit4; i++) {
float grayValue = (getRValueOfNthPixel(i)
+ getGValueOfNthPixel(i)
+ getBValueOfNthPixel(i)) / 3;
setRValueOfNthPixel(i, grayValue);
setGValueOfNthPixel(i, grayValue);
setBValueOfNthPixel(i, grayValue);
}
}
I'm using the following piece of code to iterate over all pixels in an image and draw a red 1x1 square over the pixels that are within a certain RGB-tolerance. I guess there is a more efficient way to do this? Any ideas appreciated. (bi is a BufferedImage and g2 is a Graphics2D with its color set to Color.RED).
Color targetColor = new Color(selectedRGB);
for (int x = 0; x < bi.getWidth(); x++) {
for (int y = 0; y < bi.getHeight(); y++) {
Color pixelColor = new Color(bi.getRGB(x, y));
if (withinTolerance(pixelColor, targetColor)) {
g2.drawRect(x, y, 1, 1);
}
}
}
private boolean withinTolerance(Color pixelColor, Color targetColor) {
int pixelRed = pixelColor.getRed();
int pixelGreen = pixelColor.getGreen();
int pixelBlue = pixelColor.getBlue();
int targetRed = targetColor.getRed();
int targetGreen = targetColor.getGreen();
int targetBlue = targetColor.getBlue();
return (((pixelRed >= targetRed - tolRed) && (pixelRed <= targetRed + tolRed)) &&
((pixelGreen >= targetGreen - tolGreen) && (pixelGreen <= targetGreen + tolGreen)) &&
((pixelBlue >= targetBlue - tolBlue) && (pixelBlue <= targetBlue + tolBlue)));
}
if (withinTolerance(pixelColor, targetColor)) {
bi.setRGB( x, y, 0xFFFF0000 )
}
BufferedImage's setRGB method's third parameter, as explained in the Javadoc, takes a pixel of the TYPE_INT_ARGB form.
8 bits for the alpha (FF here, fully opaque)
8 bits for the red component (FF here, fully flashy red)
8 bits for the green component (0, no green)
8 bits for the blue component.