/******************************************************************************* * Copyright 2014 Rafael Garcia Moreno. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package com.bladecoder.engineeditor.common; import java.awt.Graphics2D; import java.awt.Image; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import java.io.File; import java.io.FilenameFilter; import java.io.IOException; import java.net.URL; import java.nio.file.Files; import javax.imageio.ImageIO; import javax.swing.ImageIcon; import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.graphics.Pixmap.Format; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.Texture.TextureFilter; import com.badlogic.gdx.graphics.g2d.TextureAtlas.TextureAtlasData; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.tools.texturepacker.TexturePacker; import com.badlogic.gdx.tools.texturepacker.TexturePacker.Settings; import com.bladecoder.engine.model.World; public class ImageUtils { public static ImageIcon getImageIcon(URL u, int w) throws IOException { BufferedImage img = null; BufferedImage tmp = ImageIO.read(u); ImageIcon icon = null; if (tmp != null) { float h = (float) tmp.getHeight() * (float) w / (float) tmp.getWidth(); img = scaleImage(w, (int) h, tmp, RenderingHints.VALUE_INTERPOLATION_BICUBIC); icon = new ImageIcon((Image) img); } return icon; } public static BufferedImage scaleImage(int w, int h, BufferedImage img, Object interpolation) { BufferedImage bi; bi = new BufferedImage(w, h, img.getType()); Graphics2D g2d = (Graphics2D) bi.createGraphics(); // g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, // RenderingHints.VALUE_ANTIALIAS_ON); // g2d.addRenderingHints(new // RenderingHints(RenderingHints.KEY_RENDERING, // RenderingHints.VALUE_RENDER_QUALITY)); g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, interpolation); g2d.drawImage(img, 0, 0, w, h, null); g2d.dispose(); return bi; } public static void scaleImageFile(File org, File dest, float scale) throws IOException { BufferedImage destImg = null; BufferedImage orgImg = ImageIO.read(org); if (orgImg != null) { Object interpolation; if (orgImg.getWidth() < 20) { interpolation = RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR; } else { interpolation = RenderingHints.VALUE_INTERPOLATION_BICUBIC; } destImg = scaleImage(Math.max(1, (int) (orgImg.getWidth() * scale)), Math.max(1, (int) (orgImg.getHeight() * scale)), orgImg, interpolation); ImageIO.write(destImg, org.getName().substring(org.getName().lastIndexOf('.') + 1), dest); } } /** * Scale all images in a folder. * * WARNING: .etc1 file format is not supported. * * @param orgDir * @param destDir * @param scale * @throws IOException */ public static void scaleDirFiles(File orgDir, File destDir, float scale) throws IOException { File[] files = orgDir.listFiles(new FilenameFilter() { @Override public boolean accept(File dir, String name) { if (name.toLowerCase().endsWith(".png") || name.toLowerCase().endsWith(".jpg")) return true; return false; } }); if (files != null) { for (File f : files) { if (f.getName().endsWith(".9.png")) { // 9 patches doesn't scale Files.copy(f.toPath(), new File(destDir, f.getName()).toPath()); } else { ImageUtils.scaleImageFile(f, new File(destDir, f.getName()), scale); } } } } public static void scaleAtlas(File orgAtlas, File destDir, float scale) throws IOException { File tmpDir = DesktopUtils.createTempDirectory(); EditorLogger.debug("SCALING: " + orgAtlas.getName()); unpackAtlas(orgAtlas, tmpDir); createAtlas(tmpDir.getAbsolutePath(), destDir.getAbsolutePath(), orgAtlas.getName(), scale, TextureFilter.Linear, TextureFilter.Linear); DesktopUtils.removeDir(tmpDir.getAbsolutePath()); } public static void unpackAtlas(File orgAtlas, File destDir) { CustomTextureUnpacker unpacker = new CustomTextureUnpacker(); String atlasParentPath = orgAtlas.getParentFile().getAbsolutePath(); TextureAtlasData atlas = new TextureAtlasData(new FileHandle(orgAtlas), new FileHandle(atlasParentPath), false); unpacker.splitAtlas(atlas, destDir.getAbsolutePath()); } public static void scaleDirAtlases(File orgDir, File destDir, float scale) throws IOException { File[] files = orgDir.listFiles(new FilenameFilter() { @Override public boolean accept(File dir, String name) { if (name.toLowerCase().endsWith(".atlas")) return true; return false; } }); for (File f : files) { ImageUtils.scaleAtlas(f, destDir, scale); } } public static void createAtlas(String inDir, String outdir, String name, float scale, TextureFilter filterMin, TextureFilter filterMag) throws IOException { Settings settings = new Settings(); settings.pot = false; settings.paddingX = 2; settings.paddingY = 2; settings.duplicatePadding = true; settings.edgePadding = true; settings.rotation = false; settings.minWidth = 16; settings.minWidth = 16; settings.stripWhitespaceX = true; settings.stripWhitespaceY = true; settings.alphaThreshold = 0; settings.filterMin = filterMin; settings.filterMag = filterMag; settings.wrapX = Texture.TextureWrap.ClampToEdge; settings.wrapY = Texture.TextureWrap.ClampToEdge; settings.format = Format.RGBA8888; settings.alias = true; settings.outputFormat = "png"; settings.jpegQuality = 0.9f; settings.ignoreBlankImages = true; settings.fast = false; settings.debug = false; int wWidth = World.getInstance().getWidth(); settings.maxWidth = MathUtils.nextPowerOfTwo((int) (wWidth * scale * 2f)); settings.maxHeight = MathUtils.nextPowerOfTwo((int) (wWidth * scale * 2f)); EditorLogger.debug("ATLAS MAXWIDTH: " + settings.maxWidth); File inTmpDir = new File(inDir); // Resize images to create atlas for diferent resolutions if (scale != 1.0f) { inTmpDir = DesktopUtils.createTempDirectory(); ImageUtils.scaleDirFiles(new File(inDir), inTmpDir, scale); } TexturePacker.process(settings, inTmpDir.getAbsolutePath(), outdir, name.endsWith(".atlas") ? name : name + ".atlas"); if (scale != 1.0f) { DesktopUtils.removeDir(inTmpDir.getAbsolutePath()); } } }