Mar 06

Often when doing image processing we need to change the color of the image pixels. This ultimately involves iterating through all the pixels of an image changing values as required. This can be a slow process, especially for large images.

When you want to change all pixels of one colour to another then you can avoid iterating over the entire image by instead changing the ColorModel. The ColorModel specifies the mapping between pixel values and their color. Changing this mapping allows us to change the color of pixels without manipulating the actual pixel value.

The following gives a simple example to demonstrate the concept by changing the ColorModel of the displayed images as the mouse is moved over it.

import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.IndexColorModel;
import java.awt.image.Raster;
import java.awt.image.SampleModel;
import java.awt.image.SinglePixelPackedSampleModel;
import java.awt.image.WritableRaster;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class ImageExample extends JLabel
	implements MouseMotionListener {

	private BufferedImage image = createImage();

	public ImageExample() {
		setIcon(new ImageIcon(image));

		addMouseMotionListener(this);
	}

	@Override
	public void mouseMoved(MouseEvent e) {

		// here we want to change the color model
		// to do that we create a new image using a new color model
		// nb. there is no need to change the source pixels

		image = new BufferedImage(createColorModel(e.getX()),
				image.getRaster(), false, null);
		setIcon(new ImageIcon(image));
	}

	@Override
	public void mouseDragged(MouseEvent e) {
	}

	private static BufferedImage createImage() {

		int width = 200;
		int height = 200;

		// Generate the source pixels for our image
		// Lets just keep it to a simple blank image for now

		byte[] pixels = new byte[width * height];
		DataBuffer dataBuffer = new DataBufferByte(pixels, width*height, 0);
		SampleModel sampleModel = new SinglePixelPackedSampleModel(
        	DataBuffer.TYPE_BYTE, width, height, new int[] {(byte)0xf});
		WritableRaster raster = Raster.createWritableRaster(
			sampleModel, dataBuffer, null);

		return new BufferedImage(createColorModel(0), raster, false, null);
	}

	private static ColorModel createColorModel(int n) {

		// Create a simple color model with all values mapping to
		// a single shade of gray
		// nb. this could be improved by reusing the byte arrays

		byte[] r = new byte[16];
		byte[] g = new byte[16];
		byte[] b = new byte[16];

		for (int i = 0; i < r.length; i++) {
			r[i] = (byte) n;
			g[i] = (byte) n;
			b[i] = (byte) n;
		}
		return new IndexColorModel(4, 16, r, g, b);
	}

	public static void main(String[] args) {

		JFrame frame = new JFrame();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.add(new ImageExample());
		frame.pack();
		frame.setVisible(true);
	}
}

written by objects \\ tags: , , , ,

Aug 12

Multipart emails can be used to send html content with JavaMail. If you want to use images in the html content you can either specify the url of the image on an external server, or you can embed the image in the email itself.

To embed an image in your mail you need to assign it a cid, which you can then reference in your html img tag. Here is an example that demonstrates embedding an image and use of cid.

Properties sessionProperties = System.getProperties();
sessionProperties.put("mail.smtp.host", smtpServer);
Session session = Session.getDefaultInstance(sessionProperties, null);

// Create message

Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(
		to, false));
message.setSubject(subject);

// Add html content
// Specify the cid of the image to include in the email

String html = "<html><body><b>Test</b> email <img src='cid:my-image-id'></body></html>";
Multipart mp = new MimeMultipart();
MimeBodyPart htmlPart = new MimeBodyPart();
htmlPart.setContent(html, "text/html");
mp.addBodyPart(htmlPart);

// add image in another part

MimeBodyPart imagePart = new MimeBodyPart();
DataSource fds = new FileDataSource(imagePath);
imagePart.setDataHandler(new DataHandler(fds));
// assign a cid to the image
imagePart.setHeader("Content-ID", "my-image-id");
mp.addBodyPart(imagePart);

message.setContent(mp);

// Send the message

Transport.send(message);

written by objects \\ tags: , , ,

May 23
// Load the image

image = new ImageIcon(image).getImage();

// Determine transparency for BufferedImage
// http://helpdesk.objects.com.au/java/how-to-determine-if-image-supports-alpha

boolean hasAlpha = hasAlpha(image);
int transparency = hasAlpha ? Transparency.BITMASK : Transparency.OPAQUE;

// Create the buffered image

GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gs = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = gs.getDefaultConfiguration();
BufferedImage bufferedImage = gc.createCompatibleImage(image.getWidth(null),
		image.getHeight(null), transparency);

if (bufferedImage == null) {

	// if that failed then use the default color model

	int type = hasAlpha ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB;
	bufferedImage = new BufferedImage(image.getWidth(null), image.getHeight(null), type);
}

// Copy image

Graphics g = bufferedImage.createGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();

written by objects \\ tags: , , ,