private void writePackFile(File outputDir, Array<Page> pages, String packFileName)
      throws IOException {
    if (!packFileName.endsWith(".pack")) packFileName = packFileName + ".pack";

    File packFile = new File(outputDir, packFileName);

    if (packFile.exists() && false) {
      // Make sure there aren't duplicate names.
      TextureAtlasData textureAtlasData =
          new TextureAtlasData(new FileHandle(packFile), new FileHandle(packFile), false);
      for (Page page : pages) {
        for (Rect rect : page.outputRects) {
          String rectName = Rect.getAtlasName(rect.name, settings.flattenPaths);
          for (Region region : textureAtlasData.getRegions()) {
            if (region.name.equals(rectName)) {
              throw new GdxRuntimeException(
                  "A region with the name \""
                      + rectName
                      + "\" has already been packed: "
                      + rect.name);
            }
          }
        }
      }
    }

    FileWriter writer = new FileWriter(packFile, true);
    for (Page page : pages) {
      writer.write("\n" + page.imageName + "\n");
      writer.write("format: " + settings.format + "\n");
      writer.write("filter: " + settings.filterMin + "," + settings.filterMag + "\n");
      writer.write("repeat: " + getRepeatValue() + "\n");

      for (Rect rect : page.outputRects) {
        //				System.out.println("rect.name = " + rect.name);
        writeRect(writer, page, rect, rect.name);
        for (Alias alias : rect.aliases) {
          Rect aliasRect = new Rect();
          aliasRect.set(rect);
          alias.apply(aliasRect);
          writeRect(writer, page, aliasRect, alias.name);
        }
      }
    }
    writer.close();
  }
 public void apply(Rect rect) {
   rect.name = name;
   rect.index = index;
   rect.splits = splits;
   rect.pads = pads;
   rect.offsetX = offsetX;
   rect.offsetY = offsetY;
   rect.originalWidth = originalWidth;
   rect.originalHeight = originalHeight;
 }
  private void writeRect(FileWriter writer, Page page, Rect rect, String name) throws IOException {
    writer.write(Rect.getAtlasName(name, settings.flattenPaths) + "\n");
    writer.write("  rotate: " + rect.rotated + "\n");
    writer.write(
        "  xy: " + (page.x + rect.x) + ", " + (page.y + page.height - rect.height - rect.y) + "\n");

    writer.write("  size: " + rect.regionWidth + ", " + rect.regionHeight + "\n");
    if (rect.splits != null) {
      writer.write(
          "  split: " //
              + rect.splits[0]
              + ", "
              + rect.splits[1]
              + ", "
              + rect.splits[2]
              + ", "
              + rect.splits[3]
              + "\n");
    }
    if (rect.pads != null) {
      if (rect.splits == null) writer.write("  split: 0, 0, 0, 0\n");
      writer.write(
          "  pad: "
              + rect.pads[0]
              + ", "
              + rect.pads[1]
              + ", "
              + rect.pads[2]
              + ", "
              + rect.pads[3]
              + "\n");
    }
    writer.write("  orig: " + rect.originalWidth + ", " + rect.originalHeight + "\n");
    writer.write(
        "  offset: "
            + rect.offsetX
            + ", "
            + (rect.originalHeight - rect.regionHeight - rect.offsetY)
            + "\n");
    writer.write("  index: " + rect.index + "\n");
  }
  private void writeImages(File outputDir, Array<Page> pages, String packFileName) {
    String imageName = packFileName;
    // int dotIndex = imageName.lastIndexOf('.');
    // if (dotIndex != -1) imageName = imageName.substring(0, dotIndex);

    int fileIndex = 0;
    for (Page page : pages) {
      int width = page.width, height = page.height;
      int paddingX = settings.paddingX;
      int paddingY = settings.paddingY;
      if (settings.duplicatePadding) {
        paddingX /= 2;
        paddingY /= 2;
      }
      width -= settings.paddingX;
      height -= settings.paddingY;
      if (settings.edgePadding) {
        page.x = paddingX;
        page.y = paddingY;
        width += paddingX * 2;
        height += paddingY * 2;
      }
      if (settings.pot) {
        width = MathUtils.nextPowerOfTwo(width);
        height = MathUtils.nextPowerOfTwo(height);
      }
      width = Math.max(settings.minWidth, width);
      height = Math.max(settings.minHeight, height);

      File outputFile;
      outputFile = new File(outputDir, imageName + "." + settings.outputFormat);
      if (outputFile.exists()) {
        while (true) {

          fileIndex++;
          outputFile =
              new File(outputDir, imageName + "-" + fileIndex + "." + settings.outputFormat);
          if (!outputFile.exists()) break;
        }
      }
      page.imageName = outputFile.getName();

      BufferedImage canvas =
          new BufferedImage(width, height, getBufferedImageType(settings.format));
      Graphics2D g = (Graphics2D) canvas.getGraphics();

      System.out.println(
          "Writing " + canvas.getWidth() + "x" + canvas.getHeight() + ": " + outputFile);

      for (Rect rect : page.outputRects) {
        BufferedImage image = rect.getImage(imageProcessor);
        int iw = image.getWidth();
        int ih = image.getHeight();
        int rectX = page.x + rect.x, rectY = page.y + page.height - rect.y - rect.height;
        if (settings.duplicatePadding) {
          int amountX = settings.paddingX / 2;
          int amountY = settings.paddingY / 2;
          if (rect.rotated) {
            // Copy corner pixels to fill corners of the padding.
            for (int i = 1; i <= amountX; i++) {
              for (int j = 1; j <= amountY; j++) {
                plot(canvas, rectX - j, rectY + iw - 1 + i, image.getRGB(0, 0));
                plot(canvas, rectX + ih - 1 + j, rectY + iw - 1 + i, image.getRGB(0, ih - 1));
                plot(canvas, rectX - j, rectY - i, image.getRGB(iw - 1, 0));
                plot(canvas, rectX + ih - 1 + j, rectY - i, image.getRGB(iw - 1, ih - 1));
              }
            }
            // Copy edge pixels into padding.
            for (int i = 1; i <= amountY; i++) {
              for (int j = 0; j < iw; j++) {
                plot(canvas, rectX - i, rectY + iw - 1 - j, image.getRGB(j, 0));
                plot(canvas, rectX + ih - 1 + i, rectY + iw - 1 - j, image.getRGB(j, ih - 1));
              }
            }
            for (int i = 1; i <= amountX; i++) {
              for (int j = 0; j < ih; j++) {
                plot(canvas, rectX + j, rectY - i, image.getRGB(iw - 1, j));
                plot(canvas, rectX + j, rectY + iw - 1 + i, image.getRGB(0, j));
              }
            }
          } else {
            // Copy corner pixels to fill corners of the padding.
            for (int i = 1; i <= amountX; i++) {
              for (int j = 1; j <= amountY; j++) {
                canvas.setRGB(rectX - i, rectY - j, image.getRGB(0, 0));
                canvas.setRGB(rectX - i, rectY + ih - 1 + j, image.getRGB(0, ih - 1));
                canvas.setRGB(rectX + iw - 1 + i, rectY - j, image.getRGB(iw - 1, 0));
                canvas.setRGB(rectX + iw - 1 + i, rectY + ih - 1 + j, image.getRGB(iw - 1, ih - 1));
              }
            }
            // Copy edge pixels into padding.
            for (int i = 1; i <= amountY; i++) {
              copy(image, 0, 0, iw, 1, canvas, rectX, rectY - i, rect.rotated);
              copy(image, 0, ih - 1, iw, 1, canvas, rectX, rectY + ih - 1 + i, rect.rotated);
            }
            for (int i = 1; i <= amountX; i++) {
              copy(image, 0, 0, 1, ih, canvas, rectX - i, rectY, rect.rotated);
              copy(image, iw - 1, 0, 1, ih, canvas, rectX + iw - 1 + i, rectY, rect.rotated);
            }
          }
        }
        copy(image, 0, 0, iw, ih, canvas, rectX, rectY, rect.rotated);
        if (settings.debug) {
          g.setColor(Color.magenta);
          g.drawRect(
              rectX,
              rectY,
              rect.width - settings.paddingX - 1,
              rect.height - settings.paddingY - 1);
        }
      }

      if (settings.bleed
          && !settings.premultiplyAlpha
          && !settings.outputFormat.equalsIgnoreCase("jpg")) {
        canvas = new ColorBleedEffect().processImage(canvas, 2);
        g = (Graphics2D) canvas.getGraphics();
      }

      if (settings.debug) {
        g.setColor(Color.magenta);
        g.drawRect(0, 0, width - 1, height - 1);
      }

      ImageOutputStream ios = null;
      try {
        if (settings.outputFormat.equalsIgnoreCase("jpg")) {
          BufferedImage newImage =
              new BufferedImage(
                  canvas.getWidth(), canvas.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
          newImage.getGraphics().drawImage(canvas, 0, 0, null);
          canvas = newImage;

          Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpg");
          ImageWriter writer = writers.next();
          ImageWriteParam param = writer.getDefaultWriteParam();
          param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
          param.setCompressionQuality(settings.jpegQuality);
          ios = ImageIO.createImageOutputStream(outputFile);
          writer.setOutput(ios);
          writer.write(null, new IIOImage(canvas, null, null), param);
        } else {
          if (settings.premultiplyAlpha)
            canvas.getColorModel().coerceData(canvas.getRaster(), true);
          ImageIO.write(canvas, "png", outputFile);
        }
      } catch (IOException ex) {
        throw new RuntimeException("Error writing file: " + outputFile, ex);
      } finally {
        if (ios != null) {
          try {
            ios.close();
          } catch (Exception ignored) {
          }
        }
      }
    }
  }