DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
11 Monitoring and Observability Tools for 2023
Learn more

Inverting the Colour of Images

Jonathan Giles user avatar by
Jonathan Giles
·
Jan. 18, 10 · Interview
Like (1)
Save
Tweet
Share
13.22K Views

Join the DZone community and get the full member experience.

Join For Free

Today I was asked by a family member if I could help. They had purchased some hardware that scans in all their photo negatives, which whilst cool, has the unfortunate side-effect of resulting in images with inverted colours. Not exactly what you want to see in the (virtual) photo album!

It turns out that in the last year or so I’ve had a lot to do with image manipulation and editing in Java, so after having a brief look for a tool that they could use to batch invert their photos, I just jumped straight into Java to develop a solution. This was particularly fun as it’s been about six months since I’ve had to cut any Swing/Java2D Java code (I’m fairly fulltime JavaFX these days), so it was nice to just refresh myself after the time away.

The code below is what I ended up writing. There is almost certainly a better way to do it, but this runs perfectly well for the family member, so I didn’t go any further than that. It doesn’t have any dependencies on external libraries, and should probably run on most recent Java releases (probably 1.4+, but possibly even earlier). I’ve only tested it on my Java 6 install however. I thought I’d post it here in case anyone else is interested in batch inverting their images. For those not inclined to compile the code, you can also download the application and run it on your local machine (normally by double clicking on the file).

Warning: This code is certainly not good enough for a proper production system, as all the image processing is taking place within the user interface thread (i.e. on the Event Dispatch Thread as it’s known in Java). I was weary of posting too much code on this blog, and also the wrapping would get even worse than what is seen below. Because of this, if the code below is used in a ‘proper’ application, the user interface will freeze up whilst the images are being inverted. If you want to use this code in a proper application, please be sure to move the ImageIO stuff off onto a separate thread (e.g. by using a SwingWorker). This is very trivial, but if you have any questions please feel free to leave a comment.

Here’s the source code:

import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.LookupOp;
import java.awt.image.ShortLookupTable;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class ImageColourInverter extends JPanel {
private static final short[] invertTable;

private File selectedDir;

static {
invertTable = new short[256];
for (int i = 0; i < 256; i++) {
invertTable[i] = (short) (255 - i);
}
}

private BufferedImage invertImage(final BufferedImage src) {
final int w = src.getWidth();
final int h = src.getHeight();
final BufferedImage dst = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);

final BufferedImageOp invertOp = new LookupOp(new ShortLookupTable(0, invertTable), null);
return invertOp.filter(src, dst);
}

private JPanel getUIPanel() {
final JButton selectFolderBtn = new JButton(new AbstractAction("Select Folder") {

@Override
public void actionPerformed(final ActionEvent e) {
System.out.println("Select Folder");

final JFileChooser chooser = new JFileChooser();
chooser.setCurrentDirectory(new java.io.File("."));
chooser.setDialogTitle("Select folder to process");
chooser.setFileSelectionMode(
JFileChooser.DIRECTORIES_ONLY);

chooser.setAcceptAllFileFilterUsed(false);
if (chooser.showOpenDialog(ImageColourInverter.this) == JFileChooser.APPROVE_OPTION) {
System.out.println("Selected folder: " + chooser.getSelectedFile());
selectedDir = chooser.getSelectedFile();
}
}
});

final JButton processBtn = new JButton(new AbstractAction("Process!") {

@Override
public void actionPerformed(final ActionEvent e) {
if (selectedDir != null) {
final File[] files = selectedDir.listFiles(new FilenameFilter() {
@Override
public boolean accept(final File dir, final String name) {
if (! name.contains(".") {
return;
}
String ext = name.substring(name.lastIndexOf("."));
return ext.equalsIgnoreCase(".jpg");
}
});

for (final File file : files) {
BufferedImage orig;
BufferedImage inverted;
try {
System.out.println("processing file " + file);
orig = ImageIO.read(file);
inverted = invertImage(orig);
ImageIO.write(inverted, "jpg", file);
} catch (final IOException e1) {
e1.printStackTrace();
} finally {
orig = null;
inverted = null;
}
}

JOptionPane.showMessageDialog(null, "Done!");

selectedDir = null;
}
}
});

final JPanel panel = new JPanel();
panel.add(selectFolderBtn);
panel.add(processBtn);
return panel;
}

public static void main(final String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(
UIManager.getSystemLookAndFeelClassName());
} catch (final ClassNotFoundException e) {
e.printStackTrace();
} catch (final InstantiationException e) {
e.printStackTrace();
} catch (final IllegalAccessException e) {
e.printStackTrace();
} catch (final UnsupportedLookAndFeelException e) {
e.printStackTrace();
}

final JFrame f = new JFrame("Image Colour Inverter");
f.setResizable(false);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new ImageColourInverter().getUIPanel());
f.setSize(250, 70);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
});
}
}

From http://jonathangiles.net/

code style

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Container Security: Don't Let Your Guard Down
  • GitLab vs Jenkins: Which Is the Best CI/CD Tool?
  • Cloud Performance Engineering
  • Use Golang for Data Processing With Amazon Kinesis and AWS Lambda

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: