/**
* Copyright 2004-2016 Riccardo Solmi. All rights reserved.
* This file is part of the Whole Platform.
*
* The Whole Platform is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The Whole Platform 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the Whole Platform. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whole.lang.ui.image;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.stream.FileCacheImageOutputStream;
import javax.imageio.stream.ImageOutputStream;
public class ICNSGenerator extends AbstractImageGenerator {
private static final String ICNS_MAGIC = "icns";
private static final int HEADER_LENGTH = 8;
public void write(OutputStream os) throws IOException {
List<ICNSData> icons = new ArrayList<>();
for (ICNSType iconType : ICNSType.values()) {
RenderedImage image = images.get(iconType.getSize());
if (image == null)
throw new IllegalArgumentException("incomplete image dimesions");
icons.add(new ICNSData(iconType, image));
}
try (FileCacheImageOutputStream ios = new FileCacheImageOutputStream(os, null)) {
ios.setByteOrder(ByteOrder.BIG_ENDIAN);
writeHeader(ios, ICNS_MAGIC, calculateTotalLength(icons));
for (ICNSData icon : icons)
writeSegments(ios, icon);
}
}
protected void writeHeader(ImageOutputStream ios, String magic, int length) throws IOException {
ios.writeBytes(magic);
ios.writeInt(length);
}
protected void writeSegments(ImageOutputStream ios, ICNSData iconData) throws IOException {
ICNSType iconType = iconData.getIconType();
// write icon data
writeHeader(ios, iconType.getMagic(), iconData.getImage().length + HEADER_LENGTH);
ios.write(iconData.getImage());
// conditional write icon alpha
if (iconType.hasAlpha()) {
writeHeader(ios, iconType.getAlphaMagic(), iconData.getAlpha().length + HEADER_LENGTH);
ios.write(iconData.getAlpha());
}
}
protected int calculateTotalLength(List<ICNSData> icons) {
int length = HEADER_LENGTH; // main header size
for (ICNSData iconData : icons) {
length += HEADER_LENGTH; // icon header size
length += iconData.getImage().length; // icon data size
if (iconData.getIconType().hasAlpha()) {
length += HEADER_LENGTH; // icon header size
length += iconData.getAlpha().length; // icon data size
}
}
return length;
}
protected BufferedImage halfScale(BufferedImage image) {
int w = image.getWidth() / 2;
int h = image.getHeight() / 2;
BufferedImage scaled = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
AffineTransform affineTransform = new AffineTransform();
affineTransform.scale(.5, .5);
AffineTransformOp operation = new AffineTransformOp(affineTransform, AffineTransformOp.TYPE_BICUBIC);
return operation.filter(image, scaled);
}
}