Skip to content

Instantly share code, notes, and snippets.

@raydac
Last active November 2, 2019 18:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save raydac/faa697e44a27c9b59690c69aed7cb7c4 to your computer and use it in GitHub Desktop.
Save raydac/faa697e44a27c9b59690c69aed7cb7c4 to your computer and use it in GitHub Desktop.
Java class to generate ICNS from image under MacOS
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import javax.imageio.ImageIO;
public class IcnsGen {
public static void main(final String... args) throws Exception {
if (args.length < 1) {
System.err.println("IcnsGen <image.file>");
System.exit(1);
}
final int[][] SIZES = new int[][]{
{16, 1},
{32, 1},
{32, 2},
{64, 1},
{64, 2},
{256, 1},
{256, 2},
{512, 1},
{512, 2},
{1024, 1},
{1024, 2},};
final File srcFile = new File(args[0]);
if (!srcFile.isFile()) {
System.err.println("Can't find image file: " + srcFile);
}
final BufferedImage sourceImage = ImageIO.read(srcFile);
String rawImageName = srcFile.getName();
if (rawImageName.contains(".")) {
int index = rawImageName.lastIndexOf(".");
rawImageName = rawImageName.substring(0, index);
}
final Path currentFolder = FileSystems.getDefault().getPath(".").toAbsolutePath();
final File targetFolder = new File(currentFolder.toFile(), rawImageName + ".iconset");
if (!targetFolder.isDirectory() && !targetFolder.mkdirs()) {
throw new Error("Can't create folder: " + targetFolder);
}
for (final int[] arg : SIZES) {
System.out.print(String.format("Generated icon %d.%d.....", arg[0], arg[1]));
scaleAndSave(sourceImage, targetFolder, arg[0], arg[1]);
System.out.println("OK");
}
final File targetIcnsFile = new File(currentFolder.toFile(), rawImageName + ".icns");
final ProcessBuilder processBuilder = new ProcessBuilder("iconutil", "-c", "icns", targetFolder.getAbsolutePath(), "-o", targetIcnsFile.getAbsolutePath());
processBuilder.inheritIO();
processBuilder.redirectErrorStream(true);
final int exit = processBuilder.start().waitFor();
if (exit == 0) {
System.out.println("Generated icns file: " + targetIcnsFile.getAbsolutePath());
} else {
System.err.println("Error exit status: " + exit);
}
System.exit(exit);
}
private static void scaleAndSave(final BufferedImage src, final File folder, int width, int scale) throws Exception {
final String name;
if (scale == 1) {
name = String.format("icon_%dx%d.png", width, width);
} else {
name = String.format("icon_%dx%d@2x.png", width / 2, width / 2);
}
final BufferedImage target = new BufferedImage(width, width, BufferedImage.TYPE_INT_ARGB);
final AffineTransform transform = AffineTransform.getScaleInstance((double) width / (double) src.getWidth(), (double) width / (double) src.getHeight());
final Graphics2D gfx = target.createGraphics();
gfx.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
gfx.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
gfx.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
gfx.drawImage(src, transform, null);
gfx.dispose();
final ByteArrayOutputStream buffer = new ByteArrayOutputStream(100000);
if (!ImageIO.write(target, "png", buffer)) {
throw new Error("Can't find ONG encoder");
}
final byte[] fileBody = buffer.toByteArray();
try (FileOutputStream fos = new FileOutputStream(new File(folder, name), false)) {
fos.write(fileBody);
fos.flush();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment