Java snap to grid - java

Okay so I'm trying to make things snap to a grid I have.
This is how I snap to the screen itself:
int finalCalcX = (mouseX / Handler.gridSpace32) * Handler.gridSpace32;
int finalCalcY = (mouseY / Handler.gridSpace32) * Handler.gridSpace32;
The variable names speak for themselves I think.
Mouse coordinates divided by my tiles being 32x32 pixels, times that again to get the snap-to-grid functionality.
Now this works fine for the screen, but when I want to add it to the "map" itself, I can't just add my map x and y offsets to that, it gets messed up.
I've played around with it for about two days, and I also got it to snap to the map itself, but when I'm say, halfway in the map on both axis, the mouseX and mouseY messes the grid thing up.
It's kind of hard for me to explain, but the offset from the 0, 0 (every origins position, even the screen) PLUS the maps offset when you move away from the origin, gets added to the distance between the cursor itself and the transparent snap-to-grid tile that I'm using to test.
Basically the offset between the maps origin, and the camera, is for some reason the same offset between the cursor and the transparent tile. So the further into the map i move, the further away the tile gets from the cursor, and eventually moves outside the screen width and height...
When I move further into the map, I want the snap-to-grid functionality to stay corret, no matter where on the map I am.
Render method:
for (int y = startY; y < endY; y++) {
for (int x = startX; x < endX; x++) {
gridSpace(graphics, (int) (x * Handler.gridSpace32 - handler.getCamera().getOffsetX()),
(int) (y * Handler.gridSpace32 - handler.getCamera().getOffsetY()));
checkHighlight(graphics);
}
}
The gridSpace is the grid itself.
Here is what's in the highlight at the moment:
int finalCalcX = (mouseX / Handler.gridSpace32) * Handler.gridSpace32;
int finalCalcY = (mouseY / Handler.gridSpace32) * Handler.gridSpace32;
graphics.setColor(new Color(100, 200, 100, 3));
graphics.fillRect(finalCalcX, finalCalcY, Handler.gridSpace32, Handler.gridSpace32);
Sorry for my terrible explanation skills, but that's the best I can do.
What am I doing wrong?

I think I recreated what you are getting, and the problem lies with usage of incorrect sign in calculations of camera position and translation. Executing code below you should get similar behavior to what you described, while uncommenting commented lines (while commenting out the ones that follow them) should give you correct behavior.
package test;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import javax.swing.*;
public class SnapToGrid extends JPanel implements MouseMotionListener{
private int[] camera;
private int[] mouse;
private final int gridSize = 16;
SnapToGrid() {
camera = new int[2];
mouse = new int[2];
setFocusable(true);
addMouseMotionListener(this);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
//g2.translate(-camera[0], -camera[1]);
g2.translate(camera[0], camera[1]);
//draw background
for (int i = 0; i < 9; i++)
for (int j = 0; j < 9; j++)
{
Color c = ((j*9) + i) % 2 == 0 ? Color.black : Color.white;
g2.setColor(c);
g2.fillRect(i*gridSize, j*gridSize, gridSize, gridSize);
}
g2.setColor(Color.blue);
int[] snappedPos = getSnappedMousePosition();
g2.fillRect(snappedPos[0], snappedPos[1], gridSize, gridSize);
}
private int[] getSnappedMousePosition() {
return new int[] {
camera[0] + mouse[0] - ((camera[0] + mouse[0]) % gridSize),
camera[1] + mouse[1] - ((camera[1] + mouse[1]) % gridSize)
};
}
public static void main (String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new SnapToGrid());
frame.pack();
frame.setVisible(true);
}
#Override
public void mouseDragged(MouseEvent e) {
//camera[0] -= e.getX() - mouse[0];
//camera[1] -= e.getY() - mouse[1];
camera[0] += e.getX() - mouse[0];
camera[1] += e.getY() - mouse[1];
mouse[0] = e.getX();
mouse[1] = e.getY();
repaint();
}
#Override
public void mouseMoved(MouseEvent e) {
mouse[0] = e.getX();
mouse[1] = e.getY();
repaint();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(gridSize * 18, gridSize * 18);
}
}
One thing that I really don't like with your code, is that you are not using transformations. Using transformations allows you to separate world from viewport, submits to far easier debugging of issues like this here, and most importantly, if you want to add things like scaling or rotating later on, you only need to add few lines, as opposed to rewriting half of your render method.

Related

How can I draw a circle that compounds your cursor movement?

I am trying to draw a circle with my cursor while I am moving it. I know the circle wont be perfect but that does not really matter I just need the circle to compound on top of my organic cursor movements. I originally tried to do this with java's awt robot class but that ended up being futile because anytime I moved my mouse massive lines would extend infinitely far from where I made that movement. Here are two sets of code I tried (keep in mind I am calling these from a nativeMousePress event so I am holding down the left click the whole time).
int radius = 100;
for (double i = 0; i < (2 * Math.PI) + Math.PI / 6; i = i + Math.PI / 6) {
PointerInfo pointerA = MouseInfo.getPointerInfo();
Point a = pointerA.getLocation();
int yStart = (int) a.getY();
int xStart = (int) a.getX();
robot.mouseMove((int) ((xStart) + (radius * Math.cos(i))), (int) ((yStart) + (radius * Math.sin(i))));
robot.delay(68);
}
Here is my another attempt I had. I also want to mention that I need the delay in between each stroke.
robot.mouseMove(getX() + 40, getY() + 20);
robot.delay(1000);
robot.mouseMove(getX() + 20, getY() + 40);
robot.delay(1000);
robot.mouseMove(getX() - 20, getY() + 40);
robot.delay(1000);
robot.mouseMove(getX() - 40, getY() + 20);
robot.delay(1000);
robot.mouseMove(getX() - 40, getY() - 20);
robot.delay(1000);
robot.mouseMove(getX() - 20, getY() - 40);
robot.delay(1000);
robot.mouseMove(getX() + 20, getY() - 40);
robot.delay(1000);
robot.mouseMove(getX() + 40, getY() - 20);
public int getX() {
PointerInfo pointerA = MouseInfo.getPointerInfo();
Point a = pointerA.getLocation();
return (int) a.getX();
}
public int getY() {
PointerInfo pointerA = MouseInfo.getPointerInfo();
Point a = pointerA.getLocation();
return (int) a.getY();
}
Ok now here is the image that shows what happens when I barely move my mouse. This happens with both sets of code even though each set of code makes the circle slightly different.
Now to reiterate what I am trying to do I want to be able to move my mouse freely around the canvas while the code tries to make circles which should likely lead to a compounding effect. The issue is when I tried to use the robot class it completely bugs out and makes massive lines every which way if you attempt to move the mouse. I already asked other people about this and no one could figure out a solution to this so I am wondering if there is another class I can access that can do what I am looking for. Anyways here is a picture of what I assume it would look like if I moved my cursor to the right and if my circle code worked. (I already figured out how to do the loop effect)
Lastly I wanted to mention that I dont want a solution that provides code that can make the shape I showed above because thats not the point since I plan to do more complex things with this later. I just really need to know how to automate moving my cursor while having its movements compound with my active mouse movements.
The java.awt.Robot generates inputs events automatically. In your code, for one human input event, robot is generating 12 input events over 68x12 milliseconds. So while robot is still generating 12 events if human gives more input events then mouse pointer location will jump back and forth between robot inputs and human inputs. The problem is both robots and human are giving mouse coordinates at the same time.
one solution could be to ignore human events while robot is generating click events. But distinguishing between robot generated events and human generated events will be very hard task. And things will get complicated.
I think the easiest option will be to draw one circle for one human mouse drag input. Think it as circle/spring pattern brush. Like they have air brush in drawing tools.
I know you don't want the code. But to convey my points better here is minimal code for the approach:
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class Test extends Frame implements MouseMotionListener {
private int x1, y1, x2, y2;
private double i, radius = 10;
private Object lock = new Object();
public void init() throws Exception {
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
dispose();
System.exit(0);
}
});
addMouseMotionListener(this);
setBounds(50, 50, 500, 550);
setVisible(true);
}
public static void main(String[] argv) throws Exception {
new Test().init();
}
public void update(Graphics g) {
paint(g);
}
public void paint(Graphics g) {
g.setColor(Color.black);
g.drawLine(x1, y1, x2, y2);
}
public void mouseDragged(MouseEvent me) {
me.consume();
//do this to avoid multiple circles drawing at the same time
synchronized (lock) {
int x = me.getX();
int y = me.getY();
if (x1 == 0) x1 = x;
if (y1 == 0) y1 = y;
i=Math.PI+(Math.PI/6)*2;
for (int j = 0; j < 13; j++, i +=(Math.PI / 6)) {
x2 = (int) (x + (radius * Math.cos(i)));
y2 = (int) (y + (radius * Math.sin(i)));
paint(getGraphics());
x1 = x2;
y1 = y2;
radius += 0.3;
}
try {
Thread.sleep(150); //change delay to suite ease of use
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void mouseMoved(MouseEvent me) { //reset
synchronized(lock) {
radius = 10;
x1 = 0;
y1 = 0;
}
}
}
And the output:

How to fill histogram with array data?

I am having trouble getting my histogram to fill correctly.
I was given a large data file full of doubles that represented GPAs, about 5500 of them. I created a method to calculate the count, mean, and standard deviation of the data, however my last problem is to graph the data.
I am to make a histogram for each of the possible grades (12 of them) and graph them about the total of each grade.
I think I have coded the total for each grade correctly, but when it comes to actually drawing the histogram I cannot figure out the 4 arguments needed for fillRect.
I've been playing around with different variables, but nothing seems to get me close.
Any help is appreciated.
private static int[] gradeCounts(double[] stats) throws Exception{
double stdv = 0;
double sum = 0;
double sum2 = 0;
double variance = 0;
Scanner fsc = new Scanner(new File("introProgGrades.txt"));
while (!fsc.hasNextDouble())
fsc.nextLine();
int[] binCounts = new int[NUM_OF_GRADE_CATEGORIES];
double x = 0;
while (fsc.hasNextDouble()){
stats[2]++;
x = fsc.nextDouble();
sum += x;
sum2 += x * x;
if (x == 0.0)
binCounts[0]++;
else if (x == 0.6666667)
binCounts[1]++;
else if (x == 1.0)
binCounts[2]++;
else if (x == 1.3333333)
binCounts[3]++;
else if (x == 1.6666667)
binCounts[4]++;
else if (x == 2.0)
binCounts[5]++;
else if (x == 2.3333333)
binCounts[6]++;
else if (x == 2.6666667)
binCounts[7]++;
else if (x == 3.0)
binCounts[8]++;
else if (x == 3.3333333)
binCounts[9]++;
else if (x == 3.6666667)
binCounts[10]++;
else
binCounts[11]++;
}
stats[0] = sum/stats[2];
variance = (stats[2] * sum2 - sum * sum) / (stats[2]*(stats[2]-1));
stdv = Math.sqrt(variance);
stats[1] = stdv;
return binCounts;
}
What I am having trouble with:
private static void plotHistogram(int[] binCounts){
int max = Arrays.stream(binCounts).max().getAsInt();
DrawingPanel panel = new DrawingPanel (800,800);
Graphics2D g = panel.getGraphics();
g.fillRect(0, 0, 800/binCounts.length,max);
}
I think I have to iterate through the data with a for loop, but it's the parameters of fillRect that I am clueless on.
but when it comes to actually drawing the histogram I cannot figure out the 4 arguments needed for fillRect.
The JavaDocs are quite explicit in the properties and their meanings, it's just a box, with a position (x/y) and size (width/height)
public abstract void fillRect​(int x,
int y,
int width,
int height)
Fills the specified rectangle. The left and right edges of the rectangle are at x and x +
width - 1. The top and bottom edges are at y and y + height - 1. The
resulting rectangle covers an area width pixels wide by height pixels
tall. The rectangle is filled using the graphics context's current
color. Parameters: x - the x coordinate of the rectangle to be filled.
y - the y coordinate of the rectangle to be filled. width - the width
of the rectangle to be filled. height - the height of the rectangle to
be filled.
I've been playing around with different variables, but nothing seems to get me close.
So, two things come to mind, the first comes from the JavaDocs above...
The rectangle is filled using the graphics context's current
color
This is something that's easy to forget
The second is it seems that you misunderstand how painting works in Swing.
Painting in Swing has a very specific and well documented workflow. The first thing you should do is go read Performing Custom Painting and Painting in AWT and Swing to get a better understanding of how painting works and how you should work with it.
There is never a good reason to call JComponent#getGraphics, apart from been able to return null, this is just a snapshot of the last paint cycle and will be wiped clean on the next paint pass (which may occur at any time for any number of reasons).
Instead, you will need a custom component and override it's paintComponent method instead.
You should then have a read through the 2D Graphics trail to get a better understanding of how the API works and what features/functionality it can provide.
For example....
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.util.Arrays;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
Random rnd = new Random();
int[] binCounts = new int[10];
for (int index = 0; index < binCounts.length; index++) {
binCounts[index] = rnd.nextInt(100);
}
JFrame frame = new JFrame();
frame.add(new DrawingPanel(binCounts));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class DrawingPanel extends JPanel {
private int[] binCounts;
private int max;
public DrawingPanel(int[] binCounts) {
this.binCounts = binCounts;
max = Arrays.stream(binCounts).max().getAsInt();
System.out.println(max);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(800, 800);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int barWidth = 800 / binCounts.length;
for (int i = 0; i < binCounts.length; i++) {
int barHeight = (int)((binCounts[i] / (double)max) * getHeight());
// I personally would cache this until the state of the component
// changes, but for brevity
Rectangle rect = new Rectangle(i * barWidth, getHeight() - barHeight, barWidth, barHeight);
g2d.setColor(Color.BLUE);
g2d.fill(rect);
g2d.setColor(Color.BLACK);
g2d.draw(rect);
}
g2d.dispose();
}
}
}

How do I flip the drawRect so that it draws up?

I have some code here, and it graphs exponentially but, it graphs the wrong way. negative exponential growth. Here is my code, I'm trying to flip it up. I'll be working on it, but if you have an answer please tell me.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Graphics extends JPanel{
public static void main(String[] args) {
JFrame f =new JFrame ("Function");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Graphics g = new Graphics();
f.add(g);
f.setSize(700, 700);
f.setVisible(true);
}
public void paintComponent (java.awt.Graphics g) {
super.paintComponent(g);
int i = this.getWidth()-this.getWidth() + 5;
int xoffset = this.getWidth()/2;
int yoffset = this.getHeight()/2;
for (int x = 0 ; x < 20 ; x++){
g.setColor(Color.BLACK);
this.setBackground(Color.WHITE);
int p = x*x;
g.fillRect(i+xoffset,10+yoffset,5,p);
i = i + 10;
}
}
}
Does anyone know how to fix this?
Change the x/y position at where the rectangle starts to draw from (it always draws right/down)
So instead of
g.fillRect(i+xoffset,10+yoffset,5,p);
you could have...
g.fillRect(i + xoffset, 10 + yoffset - p, 5, p);
I've got no idea what your intentions are for int i = this.getWidth()-this.getWidth() + 5;, but clearly makes no sense (width - width == 0?)

Java Swing GUI for equation 5((θ/β) - cos(2πθ/β)) - to draw continuous graph

This is an extension to my previous question posted here -- Java Swing GUI for equation 5((θ/β) - cos(2πθ/β))
I have implemented the Java program based on the answers provided in the post an here is my program:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class DisplacementFunctionNew extends JFrame {
public DisplacementFunctionNew() {
setLayout(new BorderLayout());
add(new CosGraph(), BorderLayout.CENTER);
}
public static void main(String[] args) {
DisplacementFunctionNew frame = new DisplacementFunctionNew();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(6000, 6000);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
frame.setTitle("SineWave");
}
class CosGraph extends JPanel {
public void paintComponent(Graphics g) {
int graphHeight = 5; // Declared this to set the height of graph based on the value given here.
super.paintComponent(g);
int xBase = 100;
int top = 100;
int yScale = 100;
int xAxis = 360;
int yBase = top + yScale;
g.drawLine(xBase, top, xBase, top + 2 * yScale);
g.drawLine(xBase, yBase, xBase + xAxis, yBase);
g.setColor(Color.red);
double maxY = 0;
for (int i = 0; i < 360; i++) {
maxY = Math.max(maxY, Math.abs(getValue(i)));
}
int x, y;
for (int i = 0; i < 360; i++) {
x = xBase + i;
y = yBase - (int) (getValue(i)*graphHeight / maxY * yScale);
g.drawLine(x, y, x, y);
}
}
private double getValue(int theta) {
int beta = 45;
double b = (theta / (double) beta);
double angle = 2 * Math.PI * (b);
double c = Math.cos(angle);
double s = (b - c);
return s;
}
}
}
Now in this program I want to have a variable called graphHeight that helps to increase the height of the graph. If I give the value of the variable as 1 then I can see the output like this:
Now if I try to increase the height to 5 then I get the graph but it is not shown smoothly or continuous curve, I get the output like this:
Can someone please help me how to get the output as smooth continuous curve?
You are drawing a curve using points. You are placing one point at each location on the x axis -- this makes sense to do.
When the graph is small, it looks fine, because the y separation of these points is relatively small. However, as you increase the graph size, this flaw becomes more noticeable.
The solution here is to fill in the vertical space with lines. You have a few options for the exact implementation of this:
Draw a line from [x(i), y(i)] to [x(i+1),y(i+1)] -- this is easy, but may not look the way you want.
Draw a line from [x(i), y(i)] to [x(i),y(i+1)] -- this is still pretty easy, but it won't be quite correct: you're continuing up so that you could be an entire pixel off.
Draw a line from [x(i), y(i)] to [x(i),(y(i)+y(i+1))/2], and then from [x(i+1), (y(i)+y(i+1))/2] to [x(i+1),y(i+1)] -- this is what 1 should do (neglecting anti-aliasing), and will be the most correct of your possible options.
I would suggest number 3. Note that you can implement this with a loop of the form:
int lastY = yBase - (int) (getValue(0)*graphHeight / maxY * yScale);
for (int i = 1; i < 360; i++) {
x = xBase + i;
y = yBase - (int) (getValue(i)*graphHeight / maxY * yScale);
g.drawLine(x-1, lastY, x-1, (y+lastY)/2);
g.drawLine(x, (y+lastY)/2, x, y);
}
If the one pixel overlap bothers you, you can make it a bit more complex such that the second line starts at +/- 1 pixel (depending on if the function is increasing or decreasing).
Alternatively, you can implement number 3 by manually drawing the line, using a for loop, and basically write a special-case version of Bresenham's line algorithm.
You use graphHeight to define the y of the next point to be painted with g.drawLine(x, y, x, y);. The distance between drawn points will be related to the graphHeight variable

Drawing fully transparent "white" in Java BufferedImage

This might sound like a bit of strange title, but bear with me, there is a reason:
I am trying to generate a white glow around a text on a gray background.
To generate the glow, I created a new BufferedImage that's bigger than the text, then I drew the text in white onto the canvas of the image and ran a Gaussian Blur over the image via a ConvolveOp, hoping for something like this:
At first I was a bit surprised when the glow turned out darker than the gray background of the text:
But after a bit of thinking, I understood the problem:
The convolution operates on each color channel (R, G, B, and A) independently to calculate the blurred image. The transparent background of the picture has color value 0x00000000, i.e. a fully transparent black! So, when the convolution filter runs over the image, it not only blends the alpha value, but also mixes the black into the RGB values of the white pixels. This is why the glow comes out dark.
To fix this, I need to initialize the image to 0x00FFFFFF, i.e. a fully transparent white instead, but if I just set that color and fill a rectangle with it, it simply does nothing as Java says "well, it's a fully transparent rectangle that you're drawing! That's not going to change the image... Let me optimize that away for you... Done... You're welcome.".
If I instead set the color to 0x01FFFFFF, i.e. an almost fully transparent white, it does draw the rectangle and the glow looks beautiful, except I end up with a very faint white box around it...
Is there a way I can initialize the image to 0x00FFFFFF everywhere?
UPDATE:
I found one way, but it's probably as non-optimal as you can get:
I draw an opaque white rectangle onto the image and then I run a RescaleOp over the image that sets all alpha values to 0. This works, but it's probably a terrible approach as far as performance goes.
Can I do better somehow?
PS: I'm also open to entirely different suggestions for creating such a glow effect
The main reason why the glow appeared darker with your initial approach is most likely that you did not use an image with a premultiplied alpha component. The JavaDoc of ConvolveOp contains some information about how the alpha component is treated during a convolution.
You could work around this with an "almost fully transparent white". But alternatively, you may simply use an image with premultiplied alpha, i.e. one with the type TYPE_INT_ARGB_PRE.
Here is a MCVE that draws a panel with some text, and some pulsing glow around the text (remove the timer and set a fixed radius to remove the pulse - I couldn't resist playing around a little here ...).
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class TextGlowTest
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
createAndShowGUI();
}
});
}
private static void createAndShowGUI()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(new TextGlowPanel());
f.setSize(300,200);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
class TextGlowPanel extends JPanel
{
private BufferedImage image;
private int radius = 1;
TextGlowPanel()
{
Timer t = new Timer(50, new ActionListener()
{
long startMillis = -1;
#Override
public void actionPerformed(ActionEvent e)
{
if (startMillis == -1)
{
startMillis = System.currentTimeMillis();
}
long d = System.currentTimeMillis() - startMillis;
double s = d / 1000.0;
radius = (int)(1 + 15 * (Math.sin(s * 3) * 0.5 + 0.5));
repaint();
}
});
t.start();
}
#Override
protected void paintComponent(Graphics gr)
{
super.paintComponent(gr);
gr.setColor(Color.GRAY);
int w = getWidth();
int h = getHeight();
gr.fillRect(0, 0, w, h);
if (image == null || image.getWidth() != w || image.getHeight() != h)
{
// Must be prmultiplied!
image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE);
}
Graphics2D g = image.createGraphics();
Font font = g.getFont().deriveFont(70.0f).deriveFont(Font.BOLD);
g.setFont(font);
g.setComposite(AlphaComposite.Src);
g.setColor(new Color(255,255,255,0));
g.fillRect(0,0,w,h);
g.setComposite(AlphaComposite.SrcOver);
g.setColor(new Color(255,255,255,0));
g.fillRect(0,0,w,h);
g.setColor(Color.WHITE);
g.drawString("Glow!", 50, 100);
image = getGaussianBlurFilter(radius, true).filter(image, null);
image = getGaussianBlurFilter(radius, false).filter(image, null);
g.dispose();
g = image.createGraphics();
g.setFont(font);
g.setColor(Color.BLUE);
g.drawString("Glow!", 50, 100);
g.dispose();
gr.drawImage(image, 0, 0, null);
}
// From
// http://www.java2s.com/Code/Java/Advanced-Graphics/GaussianBlurDemo.htm
public static ConvolveOp getGaussianBlurFilter(
int radius, boolean horizontal)
{
if (radius < 1)
{
throw new IllegalArgumentException("Radius must be >= 1");
}
int size = radius * 2 + 1;
float[] data = new float[size];
float sigma = radius / 3.0f;
float twoSigmaSquare = 2.0f * sigma * sigma;
float sigmaRoot = (float) Math.sqrt(twoSigmaSquare * Math.PI);
float total = 0.0f;
for (int i = -radius; i <= radius; i++)
{
float distance = i * i;
int index = i + radius;
data[index] =
(float) Math.exp(-distance / twoSigmaSquare) / sigmaRoot;
total += data[index];
}
for (int i = 0; i < data.length; i++)
{
data[i] /= total;
}
Kernel kernel = null;
if (horizontal)
{
kernel = new Kernel(size, 1, data);
}
else
{
kernel = new Kernel(1, size, data);
}
return new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
}
}
I've found that clearRect should paint a transparent color.
g.setBackground(new Color(0x00FFFFFF, true));
g.clearRect(0, 0, img.getWidth(), img.getHeight());
You should also be able to force the BufferedImage to fill with a transparent color by setting the pixel data directly.
public static void forceFill(BufferedImage img, int rgb) {
for(int x = 0; x < img.getWidth(); x++) {
for(int y = 0; y < img.getHeight(); y++) {
img.setRGB(x, y, rgb);
}
}
}
It is not clearly documented but I tested it and setRGB appears to accept an ARGB value.

Categories