/******************************************************************************* * Breakout Cave Survey Visualizer * * Copyright (C) 2014 James Edwards * * jedwards8 at fastmail dot fm * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) any later * version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *******************************************************************************/ package org.andork.awt; import java.awt.Color; import java.awt.image.BufferedImage; import java.io.File; import javax.imageio.ImageIO; import javax.swing.ImageIcon; import org.andork.util.Reparam; public class SexyWaitIconGenerator { public static ImageIcon generateIcon(int size, int lobeCount, float innerRadius, float outerRadius, float blobRadius, Color color, int frame, int totalFrames) { float blobRadius2 = blobRadius * blobRadius; float lobeRadius = (outerRadius - innerRadius) / 2f; float lobeRadius2 = lobeRadius * lobeRadius; float centerRadius = (innerRadius + outerRadius) / 2f; float blobAngle = (float) Math.PI * 2f * frame / totalFrames; float blobx = size / 2f + centerRadius * (float) Math.sin(blobAngle); float bloby = size / 2f + centerRadius * (float) Math.cos(blobAngle); BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB); float[] lobex = new float[lobeCount]; float[] lobey = new float[lobeCount]; for (int lobe = 0; lobe < lobeCount; lobe++) { float lobeAngle = (float) Math.PI * 2f * lobe / lobeCount; lobex[lobe] = size / 2f + centerRadius * (float) Math.sin(lobeAngle); lobey[lobe] = size / 2f + centerRadius * (float) Math.cos(lobeAngle); } for (int x = 0; x < size; x++) { for (int y = 0; y < size; y++) { float value = 0f; float dx = x - blobx; float dy = y - bloby; float dxy2 = dx * dx + dy * dy; // if( dxy2 < blobRadius2 ) // { value += blobRadius2 / dxy2; // } for (int lobe = 0; lobe < lobeCount; lobe++) { dx = x - lobex[lobe]; dy = y - lobey[lobe]; dxy2 = dx * dx + dy * dy; // if( dxy2 < lobeRadius2 ) // { value += lobeRadius2 / dxy2; // } } value = Math.max(0f, Math.min(1f, Reparam.linear(value, 4f, 5f, 0f, 1f))); // value = Math.max( 0f , Math.min( 1f , value ) ); int rgb = (int) (255 * value) << 24 | color.getRGB() & 0xffffff; image.setRGB(x, y, rgb); } } return new ImageIcon(image); } public static ImageIcon generateIcon2(int size, int lobeCount, float innerRadius, float outerRadius, float expansion, Color color, int frame, int totalFrames) { float lobeRadius = (outerRadius - innerRadius) / 2f; float lobeRadius2 = lobeRadius * lobeRadius; float centerRadius = (innerRadius + outerRadius) / 2f; float spinAngle = (float) Math.PI * 2f * frame / totalFrames; BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB); float[] lobex = new float[lobeCount]; float[] lobey = new float[lobeCount]; for (int lobe = 0; lobe < lobeCount; lobe++) { float lobeAngle = (float) Math.PI * 2f * lobe / lobeCount; lobex[lobe] = size / 2f + centerRadius * (float) Math.sin(lobeAngle); lobey[lobe] = size / 2f + centerRadius * (float) Math.cos(lobeAngle); } for (int x = 0; x < size; x++) { for (int y = 0; y < size; y++) { float value = 0f; for (int lobe = 0; lobe < lobeCount; lobe++) { float lobeAngle = (float) Math.PI * 2f * lobe / lobeCount; float dangle = (float) Math.min(Math.abs(spinAngle - lobeAngle), Math.PI * 2f - Math.abs(spinAngle - lobeAngle)); float fexp = expansion * dangle / (float) Math.PI; float rad = lobeRadius + fexp; float rad2 = rad * rad; float nlobex = lobex[lobe] + fexp * (float) Math.sin(lobeAngle); float nlobey = lobey[lobe] + fexp * (float) Math.cos(lobeAngle); float dx = x - nlobex; float dy = y - nlobey; float dxy2 = dx * dx + dy * dy; if (dxy2 < rad2) { value += 1 - dxy2 / rad2; } } float angle = (float) Math.atan2(x - size / 2, y - size / 2); if (angle < 0) { angle += Math.PI * 2; } float dangle = (float) Math.min(Math.abs(angle - spinAngle), Math.PI * 2f - Math.abs(angle - spinAngle)); int colorScale = (int) Reparam.linear(dangle, 0, (float) Math.PI, 127, 255); int rgb = (int) (255 * value) << 24 | color.getRed() * colorScale / 255 << 16 | color.getGreen() * colorScale / 255 << 8 | color.getBlue() * colorScale / 255; image.setRGB(x, y, rgb); } } return new ImageIcon(image); } public static ImageIcon generateIcon2Neutral(int size, int lobeCount, float innerRadius, float outerRadius, float expansion, Color color, int frame, int totalFrames) { float lobeRadius = (outerRadius - innerRadius) / 2f; float lobeRadius2 = lobeRadius * lobeRadius; float centerRadius = (innerRadius + outerRadius) / 2f; BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB); float[] lobex = new float[lobeCount]; float[] lobey = new float[lobeCount]; for (int lobe = 0; lobe < lobeCount; lobe++) { float lobeAngle = (float) Math.PI * 2f * lobe / lobeCount; lobex[lobe] = size / 2f + centerRadius * (float) Math.sin(lobeAngle); lobey[lobe] = size / 2f + centerRadius * (float) Math.cos(lobeAngle); } for (int x = 0; x < size; x++) { for (int y = 0; y < size; y++) { float value = 0f; for (int lobe = 0; lobe < lobeCount; lobe++) { float dx = x - lobex[lobe]; float dy = y - lobey[lobe]; float dxy2 = dx * dx + dy * dy; if (dxy2 < lobeRadius2) { value += 1 - dxy2 / lobeRadius2; } } int colorScale = 127; int rgb = (int) (255 * value) << 24 | color.getRed() * colorScale / 255 << 16 | color.getGreen() * colorScale / 255 << 8 | color.getBlue() * colorScale / 255; image.setRGB(x, y, rgb); } } return new ImageIcon(image); } public static void main(String[] args) throws Exception { int totalFrames = 30; int scale = 1; for (int frame = 0; frame < totalFrames; frame++) { ImageIcon icon = generateIcon2(28 * scale, 8, 5f * scale, 10f * scale, 2f * scale, Color.RED, frame, totalFrames); BufferedImage image = (BufferedImage) icon.getImage(); ImageIO.write(image, "png", new File("spinner-" + frame + ".png")); } ImageIcon icon = generateIcon2Neutral(28 * scale, 8, 5f * scale, 10f * scale, 2f * scale, Color.RED, 0, totalFrames); ImageIO.write((BufferedImage) icon.getImage(), "png", new File("spinner-off.png")); } }