The "basic" idea is to use a combination of LinearGradientPaint
and AlphaComposite
to apply an alpha based "mask" to the core map image - now, this assumes you have an image based map.
Start by taking a look at:
Basically, we create a alpha based "mask":
BufferedImage alphaMask = new BufferedImage(baseMap.getWidth(), baseMap.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = alphaMask.createGraphics();
Color opaqueColor = new Color(0, 0, 0, 255);
Color alphaColor = new Color(0, 0, 0, 0);
LinearGradientPaint lgp = new LinearGradientPaint(
new Point(0, 0),
new Point(baseMap.getWidth(), 0),
new float[]{0f, 0.1f, 0.25f, 0.75f, 0.9f, 1f},
new Color[]{alphaColor, alphaColor, opaqueColor, opaqueColor, alphaColor, alphaColor}
);
g2d.setPaint(lgp);
g2d.fillRect(0, 0, alphaMask.getWidth(), alphaMask.getHeight());
g2d.dispose();
Note, we're not really interested in the color, just there alpha values.
Next, we use a AlphaComposite.DST_IN
to "mask" the source image, this done via a utility method...
public static BufferedImage applyMask(BufferedImage sourceImage, BufferedImage maskImage, int method) {
BufferedImage maskedImage = null;
if (sourceImage != null) {
int width = maskImage.getWidth();
int height = maskImage.getHeight();
maskedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D mg = maskedImage.createGraphics();
int x = (width - sourceImage.getWidth()) / 2;
int y = (height - sourceImage.getHeight()) / 2;
mg.drawImage(sourceImage, x, y, null);
mg.setComposite(AlphaComposite.getInstance(method));
mg.drawImage(maskImage, 0, 0, null);
mg.dispose();
}
return maskedImage;
}
Runnable example

NB: The component's background is set to red to demonstrate the alpha masking
import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.LinearGradientPaint;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
try {
frame.add(new TestPane());
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private BufferedImage maskedMap;
public TestPane() throws IOException {
BufferedImage baseMap = ImageIO.read(getClass().getResource("/images/MiddleEarth.jpeg"));
BufferedImage alphaMask = new BufferedImage(baseMap.getWidth(), baseMap.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = alphaMask.createGraphics();
Color opaqueColor = new Color(0, 0, 0, 255);
Color alphaColor = new Color(0, 0, 0, 0);
LinearGradientPaint lgp = new LinearGradientPaint(
new Point(0, 0),
new Point(baseMap.getWidth(), 0),
new float[]{0f, 0.1f, 0.25f, 0.75f, 0.9f, 1f},
new Color[]{alphaColor, alphaColor, opaqueColor, opaqueColor, alphaColor, alphaColor}
);
g2d.setPaint(lgp);
g2d.fillRect(0, 0, alphaMask.getWidth(), alphaMask.getHeight());
g2d.dispose();
maskedMap = applyMask(baseMap, alphaMask, AlphaComposite.DST_IN);
// Just to prove the point
setBackground(Color.RED);
}
@Override
public Dimension getPreferredSize() {
return maskedMap == null ? new Dimension(200, 200) : new Dimension(maskedMap.getWidth(), maskedMap.getHeight());
}
public static BufferedImage applyMask(BufferedImage sourceImage, BufferedImage maskImage, int method) {
BufferedImage maskedImage = null;
if (sourceImage != null) {
int width = maskImage.getWidth();
int height = maskImage.getHeight();
maskedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D mg = maskedImage.createGraphics();
int x = (width - sourceImage.getWidth()) / 2;
int y = (height - sourceImage.getHeight()) / 2;
mg.drawImage(sourceImage, x, y, null);
mg.setComposite(AlphaComposite.getInstance(method));
mg.drawImage(maskImage, 0, 0, null);
mg.dispose();
}
return maskedImage;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
RenderingHints hints = new RenderingHints(
RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON
);
g2d.setRenderingHints(hints);
int x = (getWidth() - maskedMap.getWidth()) / 2;
int y = (getHeight() - maskedMap.getHeight()) / 2;
g2d.drawImage(maskedMap, x, y, this);
g2d.setColor(Color.BLACK);
g2d.setStroke(new BasicStroke(3f));
// There's a nice and interesting effect ;)
g2d.setComposite(AlphaComposite.SrcOver.derive(0.9f));
int diameter = getWidth() / 4;
x = ((getWidth() / 2) - diameter) / 2;
y = (getHeight() - diameter) / 2;
g2d.fillOval(x, y, diameter, diameter);
x = getWidth() - (((getWidth() / 2) + diameter) / 2);
g2d.fillOval(x, y, diameter, diameter);
g2d.dispose();
}
}
}