Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Basically, you can create a "mask" of the original image, which can be generated from the non-opaque portions of the image.</p> <p>So I created two potion images (sure you could use a sprite sheet). One which has an opaque center and one that is transparent (just the outline).</p> <p><img src="https://i.stack.imgur.com/o8zIg.png" alt="Base"><img src="https://i.stack.imgur.com/3vpOn.png" alt="Outline"></p> <p>From this, I'm able to generate a mask of first image (in the color I want), use subimage to reduce the amount of the image I want to use then render it and the outline</p> <p><img src="https://i.stack.imgur.com/n9qeN.gif" alt="enter image description here"></p> <pre><code>import java.awt.AlphaComposite; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GraphicsConfiguration; import java.awt.GraphicsEnvironment; import java.awt.RenderingHints; import java.awt.Transparency; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.Timer; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; public class TestOverlay { public static void main(String[] args) { new TestOverlay(); } public TestOverlay() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { } JFrame frame = new JFrame("Testing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout()); frame.add(new TestPane()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public class TestPane extends JPanel { private BufferedImage potionBase; private BufferedImage potionOutline; private float value = 1f; public TestPane() { try { potionBase = ImageIO.read(new File("Potion.png")); potionOutline = ImageIO.read(new File("PotionOutline.png")); } catch (IOException ex) { ex.printStackTrace(); } Timer timer = new Timer(40, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { value = value - 0.01f; if (value &lt; 0) { value = 1f; } repaint(); } }); timer.start(); } @Override public Dimension getPreferredSize() { return potionBase == null ? super.getPreferredSize() : new Dimension(potionBase.getWidth(), potionBase.getHeight()); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g.create(); BufferedImage mask = generateMask(potionBase, Color.RED, 1f); int y = (int) (mask.getHeight() * (1f - value)); if (y &lt; mask.getHeight()) { mask = mask.getSubimage(0, y, mask.getWidth(), mask.getHeight() - y); } int x = (getWidth() - mask.getWidth()) / 2; y = y + ((getHeight() - potionOutline.getHeight()) / 2); g2d.drawImage(mask, x, y, this); y = ((getHeight() - potionOutline.getHeight()) / 2); g2d.drawImage(potionOutline, x, y, this); g2d.dispose(); } } public static BufferedImage generateMask(BufferedImage imgSource, Color color, float alpha) { int imgWidth = imgSource.getWidth(); int imgHeight = imgSource.getHeight(); BufferedImage imgMask = createCompatibleImage(imgWidth, imgHeight, Transparency.TRANSLUCENT); Graphics2D g2 = imgMask.createGraphics(); g2.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); g2.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE); g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); g2.drawImage(imgSource, 0, 0, null); g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_IN, alpha)); g2.setColor(color); g2.fillRect(0, 0, imgSource.getWidth(), imgSource.getHeight()); g2.dispose(); return imgMask; } public static BufferedImage createCompatibleImage(int width, int height, int transparency) { BufferedImage image = getGraphicsConfiguration().createCompatibleImage(width, height, transparency); image.coerceData(true); return image; } public static GraphicsConfiguration getGraphicsConfiguration() { return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration(); } } </code></pre> <p>Now, having gone through the problem, what I should have done was simply create a "filled" potion and a "empty" potion (whose inner container is empty) and simply used the same process of generating a sub image (of the filled jar) instead of generating the mask...but it was fun working up to it ;)</p> <p>Basically, what this means, is the "empty" jar can be completely transparent (except for the outline) and you can paint "within" it...</p> <p>This is based on the concept of tinting an image as demonstrated <a href="https://stackoverflow.com/questions/14225518/tinting-image-in-java-improvement/14225857#14225857">here</a></p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload