<commit_before>package com.faforever.api.utils;

import com.google.common.io.LittleEndianDataInputStream;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.image.WritableImage;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;

import javax.imageio.ImageIO;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.awt.image.Raster;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;
import java.util.stream.Stream;

import static com.github.nocatch.NoCatch.noCatch;
import static java.awt.Image.SCALE_SMOOTH;
import static java.awt.image.BufferedImage.TYPE_INT_ARGB;
import static java.nio.file.Files.isRegularFile;
import static java.nio.file.Files.list;

// TODO: move to shared faf code
public final class PreviewGenerator {

  private static final double RESOURCE_ICON_RATIO = 20 / 1024d;
  private static final String MASS_IMAGE = "/images/map_markers/mass.png";
  private static final String HYDRO_IMAGE = "/images/map_markers/hydro.png";
  private static final String ARMY_IMAGE = "/images/map_markers/army.png";
  private static final String ARMY_PREFIX = "ARMY_";

  private PreviewGenerator() {
    throw new AssertionError("Not instantiatable");
  }

  public static javafx.scene.image.Image generatePreview(Path mapFolder, int width, int height) throws IOException {
    try (Stream<Path> mapFolderStream = list(mapFolder)) {
      Optional<Path> mapPath = mapFolderStream
          .filter(file -> file.getFileName().toString().endsWith(".scmap"))
          .findFirst();
      if (!mapPath.isPresent()) {
        throw new RuntimeException("No map file was found in: " + mapFolder.toAbsolutePath());
      }

      return noCatch(() -> {
        MapData mapData = parseMap(mapPath.get());

        BufferedImage previewImage = getDdsImage(mapData);
        previewImage = scale(previewImage, width, height);

        addMarkers(previewImage, mapData);

        return SwingFXUtils.toFXImage(previewImage, new WritableImage(width, height));
      });

    }
  }

  private static MapData parseMap(Path mapPath) throws IOException {
    MapData mapData = new MapData();
    try (LittleEndianDataInputStream mapInput = new LittleEndianDataInputStream(Files.newInputStream(mapPath))) {
      mapInput.skip(16);
      mapData.setWidth((int) mapInput.readFloat());
      mapData.setHeight((int) mapInput.readFloat());
      mapInput.skip(6);

      int ddsSize = mapInput.readInt();
      // Skip DDS header
      mapInput.skipBytes(128);

      byte[] buffer = new byte[ddsSize - 128];
      mapInput.readFully(buffer);

      mapData.setDdsData(buffer);

      Path lua = Paths.get(mapPath.toAbsolutePath().toString().replace(".scmap", "_save.lua"));
      if (isRegularFile(lua)) {
        LuaTable markers = LuaUtil.loadFile(lua).get("Scenario").get("MasterChain").get("_MASTERCHAIN_").get("Markers").checktable();
        mapData.setMarkers(markers);
      }
    }
    return mapData;
  }

  private static BufferedImage getDdsImage(MapData mapData) throws IOException {
    byte[] ddsData = mapData.getDdsData();
    int ddsDimension = (int) (Math.sqrt(ddsData.length) / 2);

    bgraToAbgr(ddsData);
    BufferedImage previewImage = new BufferedImage(ddsDimension, ddsDimension, BufferedImage.TYPE_4BYTE_ABGR);
    previewImage.setData(Raster.createRaster(previewImage.getSampleModel(), new DataBufferByte(ddsData, ddsData.length), new Point()));
    return previewImage;
  }

  private static BufferedImage scale(BufferedImage previewImage, double width, double height) {
    int targetWidth = width < 1 ? 1 : (int) width;
    int targetHeight = height < 1 ? 1 : (int) height;

    Image image = previewImage.getScaledInstance(targetWidth, targetHeight, SCALE_SMOOTH);<commit_msg>Test Travis<commit_after>package com.faforever.api.utils;

import com.google.common.io.LittleEndianDataInputStream;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.image.WritableImage;
import lombok.SneakyThrows;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;

import javax.imageio.ImageIO;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.awt.image.Raster;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;
import java.util.stream.Stream;

import static com.github.nocatch.NoCatch.noCatch;
import static java.awt.Image.SCALE_SMOOTH;
import static java.awt.image.BufferedImage.TYPE_INT_ARGB;
import static java.nio.file.Files.list;

// TODO: move to shared faf code
public final class PreviewGenerator {

  private static final double RESOURCE_ICON_RATIO = 20 / 1024d;
  private static final String MASS_IMAGE = "/images/map_markers/mass.png";
  private static final String HYDRO_IMAGE = "/images/map_markers/hydro.png";
  private static final String ARMY_IMAGE = "/images/map_markers/army.png";
  private static final String ARMY_PREFIX = "ARMY_";

  private PreviewGenerator() {
    throw new AssertionError("Not instantiatable");
  }

  public static javafx.scene.image.Image generatePreview(Path mapFolder, int width, int height) throws IOException {
    try (Stream<Path> mapFolderStream = list(mapFolder)) {
      Optional<Path> mapPath = mapFolderStream
          .filter(file -> file.getFileName().toString().endsWith(".scmap"))
          .findFirst();
      if (!mapPath.isPresent()) {
        throw new RuntimeException("No map file was found in: " + mapFolder.toAbsolutePath());
      }

      return noCatch(() -> {
        MapData mapData = parseMap(mapPath.get());
        if (mapData == null) {
          throw new RuntimeException("mapdata is null after parseMap from: " + mapPath.get());
        }

        BufferedImage previewImage = getDdsImage(mapData);
        previewImage = scale(previewImage, width, height);

        addMarkers(previewImage, mapData);

        return SwingFXUtils.toFXImage(previewImage, new WritableImage(width, height));
      });

    }
  }

  @SneakyThrows
  private static MapData parseMap(Path mapPath) {
    MapData mapData = new MapData();
    try (LittleEndianDataInputStream mapInput = new LittleEndianDataInputStream(Files.newInputStream(mapPath))) {
      mapInput.skip(16);
      mapData.setWidth((int) mapInput.readFloat());
      mapData.setHeight((int) mapInput.readFloat());
      mapInput.skip(6);

      int ddsSize = mapInput.readInt();
      // Skip DDS header
      mapInput.skipBytes(128);

      byte[] buffer = new byte[ddsSize - 128];
      mapInput.readFully(buffer);

      mapData.setDdsData(buffer);

      Path lua = Paths.get(mapPath.toAbsolutePath().toString().replace(".scmap", "_save.lua"));
      // java.nio.file.Files.isRegularFile does not work on Linux
      if (!Files.exists(lua)) {
        throw new RuntimeException("Path does not exists: " + lua);
      }
      LuaTable markers = LuaUtil.loadFile(lua).get("Scenario").get("MasterChain").get("_MASTERCHAIN_").get("Markers").checktable();
      mapData.setMarkers(markers);
    }
    return mapData;
  }

  private static BufferedImage getDdsImage(MapData mapData) throws IOException {
    byte[] ddsData = mapData.getDdsData();
    int ddsDimension = (int) (Math.sqrt(ddsData.length) / 2);

    bgraToAbgr(ddsData);
    BufferedImage previewImage = new BufferedImage(ddsDimension, ddsDimension, BufferedImage.TYPE_4BYTE_ABGR);
    previewImage.setData(Raster.createRaster(previewImage.getSampleModel(), new DataBufferByte(ddsData, ddsData.length), new Point()));
    return previewImage;
  }

  private static BufferedImage scale(BufferedImage previewImage, double width, double height) {
    int targetWidth = width < 1 ? 1 : (int) width;
    int targetHeight = height < 1 ? 1 : (int) height;

    Image image = previewImage.getScaledInstance(targetWidth, targetHeight, SCALE_SMOOTH);
{'fraction_non_alphanumeric': 0.11457819437592501, 'fraction_numerical': 0.005673408978786384, 'mean_word_length': 4.080827067669173, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '529789', 'n_tokens_mistral': 2563, 'n_tokens_neox': 2479, 'n_words': 541}