001/**
002 * Copyright (C) 2006-2025 Talend Inc. - www.talend.com
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.talend.sdk.component.tools;
017
018import java.awt.Color;
019import java.awt.image.BufferedImage;
020import java.io.IOException;
021import java.io.InputStream;
022import java.io.OutputStream;
023import java.nio.file.FileVisitResult;
024import java.nio.file.Files;
025import java.nio.file.Path;
026import java.nio.file.SimpleFileVisitor;
027import java.nio.file.attribute.BasicFileAttributes;
028
029import org.apache.batik.transcoder.TranscoderException;
030import org.apache.batik.transcoder.TranscoderInput;
031import org.apache.batik.transcoder.TranscoderOutput;
032import org.apache.batik.transcoder.image.ImageTranscoder;
033import org.apache.batik.transcoder.image.PNGTranscoder;
034
035public class SVG2Png implements Runnable {
036
037    private final Path iconsFolder;
038
039    private final Log log;
040
041    private final boolean activeWorkarounds;
042
043    public SVG2Png(final Path iconsFolder, final boolean activeWorkarounds, final Object log) {
044        this.iconsFolder = iconsFolder;
045        this.activeWorkarounds = activeWorkarounds;
046        try {
047            this.log = Log.class.isInstance(log) ? Log.class.cast(log) : new ReflectiveLog(log);
048        } catch (final NoSuchMethodException e) {
049            throw new IllegalArgumentException(e);
050        }
051    }
052
053    @Override
054    public void run() {
055        try {
056            Files.walkFileTree(iconsFolder, new SimpleFileVisitor<Path>() {
057
058                @Override
059                public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException {
060                    final String fileName = file.getFileName().toString();
061                    if (fileName.endsWith(".svg")) {
062                        final Path svg = file
063                                .getParent()
064                                .resolve(fileName.substring(0, fileName.length() - ".svg".length()) + "_icon32.png");
065                        if (!Files.exists(svg)) {
066                            createPng(file, svg);
067                            log.info("Created " + svg);
068                        }
069                    }
070                    return super.visitFile(file, attrs);
071                }
072            });
073        } catch (final IOException e) {
074            throw new IllegalStateException(e);
075        }
076    }
077
078    private void createPng(final Path svg, final Path png) {
079        final PNGTranscoder transcoder = new PNGTranscoder() {
080
081            @Override
082            public void writeImage(final BufferedImage img, final TranscoderOutput output) throws TranscoderException {
083                if (activeWorkarounds) {
084                    ensureAlphaDiff(img);
085                }
086                super.writeImage(img, output);
087            }
088
089            private void ensureAlphaDiff(final BufferedImage img) {
090                // otherwise all web icon are just plain black and studio ignores the alpha in its
091                // md5 cache key so we just get only one icon
092                for (int x = 1; x < img.getWidth() - 1; x++) {
093                    for (int y = 1; y < img.getHeight() - 1; y++) {
094                        final Color color = new Color(img.getRGB(x, y), true);
095                        if (color.getAlpha() == 0) { // enforce some differences for all black images
096                            img.setRGB(x, y, new Color(255, 255, 255, color.getAlpha()).getRGB());
097                        }
098                    }
099                }
100            }
101        };
102        transcoder.addTranscodingHint(ImageTranscoder.KEY_HEIGHT, 32f);
103        transcoder.addTranscodingHint(ImageTranscoder.KEY_WIDTH, 32f);
104        try (final InputStream in = Files.newInputStream(svg); final OutputStream out = Files.newOutputStream(png)) {
105            transcoder.transcode(new TranscoderInput(in), new TranscoderOutput(out));
106        } catch (final IOException | TranscoderException ioe) {
107            throw new IllegalStateException(ioe);
108        }
109    }
110}