I am new to Processing , and have been playing around with its features but can't for the life of me figure out how to resize an image properly. Below is an example of a function where from the tutorials, but I cant seem to resize the image properly so that it fits the window, has anyone any suggestion s ??
import processing.core.*;
public class Adjusting_image_brightness extends PApplet
{
//intiallize image
PImage img;
public void setup()
{
//set the size
size(320,240);
//load the image
img = loadImage("Conn4Board2.jpg");
//img.resize(400, 400);
}
public void draw()
{
//call the pixels
loadPixels();
//run through the pixels
for(int x = 0; x < img.width; x++)
{
for(int y = 0; y <img.height ; y++)
{
//calculate the 1D pixel location
int loc = x + y*width;
//get the R G B values from the picture
float r = red(img.pixels[loc]);
float b= blue(img.pixels[loc]);
float g = green(img.pixels[loc]);
//change the brightness acording to the mouse here
double adjustBrightness = ((float) mouseX / width) * 8.0;
r *= adjustBrightness;
b *= adjustBrightness;
g *= adjustBrightness;
//Constrainr RGB to between 0 - 255
r = constrain(r, 0 , 255);
g = constrain(g, 0 , 255);
b = constrain(b, 0, 255);
//make a new colour and set pixel in the window
int c = color(r,g,b);
pixels[loc] = c;
}
}
updatePixels();
}
}
Thanks
Stephen.
Too much code if all you want is to resize the image so it fits in the window. The image() function already lets you say which bounding box it should fit in, so just use this:
image(img, 0, 0, width, height);
and your image will draw scaled-to-fit.
Related
I was basically trying to use a slider that would change the brightness of any image that the user loads.
The code below at the moment has a slider and a button that loads the image. What I want is once the image has been loaded using the load button, if the user slides the slider up and down to change the brightness of the image.
There is another file connected to the current file, but I am not able to send that one as it is too big
Here is the link for the whole file https://github.com/Muhammad-786/Test2
PImage sourceImage;
PImage outputImage;
SimpleUI myUI;
void setup() {
size(1000, 1000);
myUI = new SimpleUI();
Slider slider = myUI.addSlider("greys", 155, 885);
slider.setSliderValue(0.5);
myUI.addSimpleButton("Load file", 350,885);
}
void draw() {
loadPixels();
updatePixels();
if( sourceImage != null ){
image(sourceImage,100,50);
}
if(outputImage != null){
image(outputImage, 100, 50);
}
myUI.update();
}
void handleUIEvent(UIEventData uied) {
uied.print(2);
if(uied.eventIsFromWidget("Load file")){
myUI.openFileLoadDialog("Load an image");
}
if(uied.eventIsFromWidget("fileLoadDialog")){
sourceImage = loadImage(uied.fileSelection);
}
if (uied.eventIsFromWidget("greys")) {
outputImage = SLIDER(sourceImage);
}
}
PImage SLIDER(PImage sliderw){
PImage outputImage = createImage(sliderw.width,sliderw.height,RGB);
outputImage.loadPixels();
for (int x = 0; x < sliderw.width; x++ ) {
for (int y = 0; y < sliderw.height; y++ ) {
int loc = x + y*sliderw.width;
float r = red (sliderw.pixels[loc]);
float g = green(sliderw.pixels[loc]);
float b = blue (sliderw.pixels[loc]);
float adjustBrightness = map(height, 0, width, 0, 8);
r *= adjustBrightness;
g *= adjustBrightness;
b *= adjustBrightness;
r = constrain(r, 0, 255);
g = constrain(g, 0, 255);
b = constrain(b, 0, 255);
color c = color(r, g, b);
pixels[loc] = c;
outputImage.set(x,y, color(r,g, b));
}
}
outputImage.loadPixels();
return outputImage;
}
You were setting the brightness wrong.
In your code, you use:
float adjustBrightness = map(height, 0, width, 0, 8);
You are mapping height which is the height of the canvas size from 0~width to 0~8. Since the canvas size never changes, the value of adjustBrightness also never changes. That is why it suddenly becomes bright once in the beginning, then never change.
I've edited that part of the code to below (and other changes to make it work):
//declared globally
int sliderStartX = 155;
...
Slider slider = myUI.addSlider("greys", sliderStartX, 885);
...
float adjustBrightness = map(mouseX, sliderStartX, sliderStartX + 102, 0, 8);
I saved the x position of the left of slider in sliderStartX, and used that as the lower limit of the source range in map, and 102 is the width of the slider element that I found on SimpleUI.pde, hence sliderStartX + 102 is the upper limit of the source range.
So now, you are mapping mouseX from this range to your desired range.
However, this approach does not utilize the slider AT ALL. As you can see, we are only using slider's xpos and width. A more elegant approach would be to actually use the sliderValue inside the Slider instance, and map it from 0~1 (as sliderValue seems to be in that range, looking at the console) to your desired range 0~8. I'm not familiar at all with this SimpleUI library, so I couldn't really get the time to study it and make that part of it work.
Hope this helps you in writing the code you need!
Tile seamless is an image operation that is available in GIMP. It transforms the image so that it can cover a surface smoothly with a repeatable pattern. The edges will not be visible and the pieces will fit perfectly when tiled together. It makes senses for grass, floors, walls, etc... As far as the example shown in the GIMP documentation though, it is not good (the Taj Mahal https://docs.gimp.org/2.10/en/gimp-filter-tile-seamless.html) but it gives an idea of how it works.
A transparent layer is applied over the image. It's a translation of half the size of the image (modulo image size) and the closer to the center, the more transparent it gets to show more of the original image. I took a look at the algorithm used in GIMP but it was pretty hard to read (https://gitlab.gnome.org/GNOME/gegl/-/blob/master/operations/common/tile-seamless.c).
So instead I remembered Pythagore to compute the distance to the center.
Then I apply a pro-rata to have an alpha between 0 and 255 :
0 => fully transparent => center
255 => fully opaque => corner
So here is the code :
public class TileSeamless {
public static BufferedImage createSeamlessTile(BufferedImage inputImage) {
int w = inputImage.getWidth();
int h = inputImage.getHeight();
BufferedImage seamlessTile = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
seamlessTile.getGraphics().drawImage(inputImage, 0, 0, null);
seamlessTile.getGraphics().drawImage(createLayerImage(inputImage), 0, 0, null);
return seamlessTile;
}
public static BufferedImage createLayerImage(BufferedImage inputImage) {
int w = inputImage.getWidth();
int h = inputImage.getHeight();
BufferedImage layerImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
for (int x = 0; x < w; x++) {
for (int y = 0; y < h; y++) {
Color color = new Color(inputImage.getRGB((x + w / 2) % w, (y + h / 2) % h));
int alpha = (int) Math.round(255 * distanceToCenter(x, y, w, h) / distanceToCenter(0, 0, w, h));
Color newColor = new Color(color.getRed(), color.getGreen(), color.getBlue(), alpha);
layerImage.setRGB(x, y, newColor.getRGB());
}
}
return layerImage;
}
public static double distanceToCenter(int x, int y, int w, int h) {
double distanceToCenterX = x - w / 2d;
double distanceToCenterY = y - h / 2d;
return Math.sqrt(distanceToCenterX * distanceToCenterX + distanceToCenterY * distanceToCenterY);
}
public static void main(String[] args) throws IOException {
File inputFile = new File(args[0]);
File outputFile = new File(args[1]);
BufferedImage inputImage = ImageIO.read(inputFile);
BufferedImage seamlessTile = TileSeamless.createSeamlessTile(inputImage);
ImageIO.write(seamlessTile, "png", outputFile);
}
The result is not too bad. It looks a bit different from the one produced by GIMP.
It's a bit blury.
Any idea how I can have a slighly more neat result?
For an automation tool I'm working on I need to compare 2 images.
My code works perfectly when I have "normal" images, but it fails when one of the images has a transparent area.
I'm reducing the color between the images for each pixel and creating a negative image that shows the difference. For images with transparent area the negative image is whole white, I can't see any shape or other info.
How to ignore the transparent area (shown in the images as gray color)?
My code:
private static BufferedImage createDiffImage(BufferedImage img1, BufferedImage img2) {
BufferedImage result = new BufferedImage(img1.getWidth(), img1.getHeight(), img1.getType());
int color;
for(int x = 0; x < img1.getWidth(); x++)
for(int y = 0; y < img1.getHeight(); y++) {
color = Math.abs(img2.getRGB(x, y) - img1.getRGB(x, y));
result.setRGB(x, y, color);
}
return result;
}
I found the solution:
private static BufferedImage createDiffImage(BufferedImage img1, BufferedImage img2) {
BufferedImage result = new BufferedImage(img1.getWidth(), img1.getHeight(), img1.getType());
for(int x = 0; x < img1.getWidth(); x++)
for(int y = 0; y < img1.getHeight(); y++) {
Color c1 = new Color(img1.getRGB(x,y));
Color c2 = new Color(img2.getRGB(x,y));
int alpha = 255;
int red = Math.abs(c1.getRed() - c2.getRed());
int green = Math.abs(c1.getGreen() - c2.getGreen());
int blue = Math.abs(c1.getBlue() - c2.getBlue());
Color negativeColor = new Color(red,green,blue, alpha);
result.setRGB(x, y, negativeColor.getRGB());
}
return result;
}
public static BufferedImage split(BufferedImage img) {
BufferedImage pic = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics g = pic.getGraphics();
int width = 2000/2;
int height = 2000/2;
int imageW = pic.getWidth();
int imageH = pic.getHeight();
// Tile the image to fill our area.
for (int x = 0; x < width; x += imageW) {
for (int y = 0; y < height; y += imageH) {
g.drawImage(pic, x, y, null);
}
}
return pic ;
}
the point of the code is to create a tile of 2x2 of the image (same image reproduce at a smaller size in a 2x2 grid). i want to updated pic so i can print it onto a jpanel. all i get is black image. can someone tell me whats wrong with the code. or tell me how to create a better piece of code.
I want to make four smaller images of the original and place it in a grid of 2x2 that is the same size as the original image
Something like...
public static BufferedImage split(BufferedImage img) {
BufferedImage pic = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics g = pic.getGraphics();
int width = pic.getWidth() / 4;
int height = pic.getHeight() / 4;
Image scaled = img.getScaledInstance(width, height, Image.SCALE_SMOOTH);
// Tile the image to fill our area.
for (int x = 0; x < pic.getWidth(); x += width) {
for (int y = 0; y < pic.getHeight(); y += height) {
g.drawImage(scaled, x, y, null);
}
}
g.dispose();
return pic;
}
You may also like to have a look at Java: maintaining aspect ratio of JPanel background image and Quality of Image after resize very low -- Java for more details about how you can improve the scaling algorithm
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);
}
}}