content: package me.earth.earthhack.impl.util.render.image;
  
  import org.w3c.dom.NamedNodeMap;
  import org.w3c.dom.Node;
  import org.w3c.dom.NodeList;
  
  import javax.imageio.ImageIO;
  import javax.imageio.ImageReader;
  import javax.imageio.metadata.IIOMetadata;
  import javax.imageio.metadata.IIOMetadataNode;
  import java.awt.*;
  import java.awt.image.BufferedImage;
  import java.awt.image.ColorModel;
  import java.awt.image.WritableRaster;
  import java.io.IOException;
  import java.io.InputStream;
  import java.util.ArrayList;
  import java.util.List;
  
  public class GifConverter
  {
      public static GifImage readGifImage(InputStream stream, String name) throws IOException
      {
          ArrayList<ImageFrame> frames = new ArrayList<>(2);
  
          ImageReader reader = ImageIO.getImageReadersByFormatName("gif").next();
          reader.setInput(ImageIO.createImageInputStream(stream));
  
          int lastx = 0;
          int lasty = 0;
  
          int width = -1;
          int height = -1;
  
          IIOMetadata metadata = reader.getStreamMetadata();
  
          Color backgroundColor = null;
  
          if (metadata != null) {
              IIOMetadataNode globalRoot = (IIOMetadataNode) metadata.getAsTree(metadata.getNativeMetadataFormatName());
  
              NodeList globalColorTable = globalRoot.getElementsByTagName("GlobalColorTable");
              NodeList globalScreeDescriptor = globalRoot.getElementsByTagName("LogicalScreenDescriptor");
  
              if (globalScreeDescriptor.getLength() > 0){
                  IIOMetadataNode screenDescriptor = (IIOMetadataNode) globalScreeDescriptor.item(0);
  
                  if (screenDescriptor != null){
                      width = Integer.parseInt(screenDescriptor.getAttribute("logicalScreenWidth"));
                      height = Integer.parseInt(screenDescriptor.getAttribute("logicalScreenHeight"));
                  }
              }
  
              if (globalColorTable.getLength() > 0){
                  IIOMetadataNode colorTable = (IIOMetadataNode) globalColorTable.item(0);
  
                  if (colorTable != null) {
                      String bgIndex = colorTable.getAttribute("backgroundColorIndex");
  
                      IIOMetadataNode colorEntry = (IIOMetadataNode) colorTable.getFirstChild();
                      while (colorEntry != null) {
                          if (colorEntry.getAttribute("index").equals(bgIndex)) {
                              int red = Integer.parseInt(colorEntry.getAttribute("red"));
                              int green = Integer.parseInt(colorEntry.getAttribute("green"));
                              int blue = Integer.parseInt(colorEntry.getAttribute("blue"));
  
                              backgroundColor = new Color(red, green, blue);
                              break;
                          }
  
                          colorEntry = (IIOMetadataNode) colorEntry.getNextSibling();
                      }
                  }
              }
          }
  
          BufferedImage master = null;
          boolean hasBackround = false;
  
          for (int frameIndex = 0;; frameIndex++) {
              BufferedImage image;
              try {
                  image = reader.read(frameIndex);
              } catch (IndexOutOfBoundsException io){
                  break;
              }
  
              if (width == -1 || height == -1){
                  width = image.getWidth();
                  height = image.getHeight();
              }
  
              IIOMetadataNode root = (IIOMetadataNode) reader.getImageMetadata(frameIndex).getAsTree("javax_imageio_gif_image_1.0");
              IIOMetadataNode gce = (IIOMetadataNode) root.getElementsByTagName("GraphicControlExtension").item(0);
              NodeList children = root.getChildNodes();
  
              int delay = Integer.parseInt(gce.getAttribute("delayTime"));
  
              String disposal = gce.getAttribute("disposalMethod");
  
              if (master == null){
                  master = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
                  master.createGraphics().setColor(backgroundColor);
                  master.createGraphics().fillRect(0, 0, master.getWidth(), master.getHeight());
  
                  hasBackround = image.getWidth() == width && image.getHeight() == height;
  
                  master.createGraphics().drawImage(image, 0, 0, null);
              } else {
                  int x = 0;
                  int y = 0;
  
                  for (int nodeIndex = 0; nodeIndex < children.getLength(); nodeIndex++){
                      Node nodeItem = children.item(nodeIndex);
  
                      if (nodeItem.getNodeName().equals("ImageDescriptor")){
                          NamedNodeMap map = nodeItem.getAttributes();
  
                          x = Integer.parseInt(map.getNamedItem("imageLeftPosition").getNodeValue());
                          y = Integer.parseInt(map.getNamedItem("imageTopPosition").getNodeValue());
                      }
                  }
  
                  if (disposal.equals("restoreToPrevious")){
                      BufferedImage from = null;
                      for (int i = frameIndex - 1; i >= 0; i--){
                          if (!frames.get(i).getDisposal().equals("restoreToPrevious") || frameIndex == 0){
                              from = frames.get(i).getImage();
                              break;
                          }
                      }
  
                      {
                          ColorModel model = from.getColorModel();
                          boolean alpha = from.isAlphaPremultiplied();
                          WritableRaster raster = from.copyData(null);
                          master = new BufferedImage(model, raster, alpha, null);
                      }
                  } else if (disposal.equals("restoreToBackgroundColor") && backgroundColor != null){
                      if (!hasBackround || frameIndex > 1){
                          master.createGraphics().fillRect(lastx, lasty, frames.get(frameIndex - 1).getWidth(), frames.get(frameIndex - 1).getHeight());
                      }
                  }
                  master.createGraphics().drawImage(image, x, y, null);
  
                  lastx = x;
                  lasty = y;
              }
  
              {
                  BufferedImage copy;
  
                  {
                      ColorModel model = master.getColorModel();
                      boolean alpha = master.isAlphaPremultiplied();
                      WritableRaster raster = master.copyData(null);
                      copy = new BufferedImage(model, raster, alpha, null);
                  }
                  frames.add(new ImageFrame(copy, delay, disposal, image.getWidth(), image.getHeight()));
              }
  
              master.flush();
          }
          reader.dispose();
  
          ImageFrame[] framesArray = frames.toArray(new ImageFrame[0]);
          int totalWidth = 0;
          int maxHeight = framesArray[0].getHeight();
          for (ImageFrame frame : framesArray) {
              totalWidth += frame.getWidth();
              if (frame.getHeight() > maxHeight) {
                  maxHeight = frame.getHeight();
              }
          }
          BufferedImage finalImage = new BufferedImage(totalWidth, maxHeight, BufferedImage.TYPE_INT_RGB);
          Graphics graphics = finalImage.getGraphics();
          int offset = 0;
          int delay = 0;
          List<BufferedImage> images = new ArrayList<>();
          for (ImageFrame frame : framesArray) {
              /*graphics.drawImage(frame.getImage(), offset, 0, null);
              offset += frame.getWidth();*/
              delay += frame.getDelay() * 10;
              images.add(frame.getImage());
          }
          delay /= framesArray.length;
          graphics.dispose();
  
          // ByteArrayOutputStream baos = new ByteArrayOutputStream();
          // ImageIO.write(finalImage, "gif", baos);
          // InputStream is = new ByteArrayInputStream(baos.toByteArray());
          // Image image1 = new Image(TextureLoader.getTexture("GIF", is));
  
          /*List<DynamicTexture> textures = new ArrayList<>();
          for (BufferedImage image : images)
          {
              textures.add(new DynamicTexture(ImageUtil.createFlipped(image)));
          }
          return new GifImage(name, delay, textures);*/
          return new GifImage(images, delay, name);
  
          // return new Animation(new SpriteSheet(image1, width, height), delay);
      }
  
  
  
      /*public static GifImage readGifImageEfficient(InputStream stream, String name) throws IOException
      {
          ArrayList<ImageFrame> frames = new ArrayList<ImageFrame>(2);
  
          ImageReader reader = ImageIO.getImageReadersByFormatName("gif").next();
          reader.setInput(ImageIO.createImageInputStream(stream));
  
          int lastx = 0;
          int lasty = 0;
  
          int width = -1;
          int height = -1;
  
          IIOMetadata metadata = reader.getStreamMetadata();
  
          Color backgroundColor = null;
  
          if (metadata != null) {
              IIOMetadataNode globalRoot = (IIOMetadataNode) metadata.getAsTree(metadata.getNativeMetadataFormatName());
  
              NodeList globalColorTable = globalRoot.getElementsByTagName("GlobalColorTable");
              NodeList globalScreeDescriptor = globalRoot.getElementsByTagName("LogicalScreenDescriptor");
  
              if (globalScreeDescriptor != null && globalScreeDescriptor.getLength() > 0){
                  IIOMetadataNode screenDescriptor = (IIOMetadataNode) globalScreeDescriptor.item(0);
  
                  if (screenDescriptor != null){
                      width = Integer.parseInt(screenDescriptor.getAttribute("logicalScreenWidth"));
                      height = Integer.parseInt(screenDescriptor.getAttribute("logicalScreenHeight"));
                  }
              }
  
              if (globalColorTable != null && globalColorTable.getLength() > 0){
                  IIOMetadataNode colorTable = (IIOMetadataNode) globalColorTable.item(0);
  
                  if (colorTable != null) {
                      String bgIndex = colorTable.getAttribute("backgroundColorIndex");
  
                      IIOMetadataNode colorEntry = (IIOMetadataNode) colorTable.getFirstChild();
                      while (colorEntry != null) {
                          if (colorEntry.getAttribute("index").equals(bgIndex)) {
                              int red = Integer.parseInt(colorEntry.getAttribute("red"));
                              int green = Integer.parseInt(colorEntry.getAttribute("green"));
                              int blue = Integer.parseInt(colorEntry.getAttribute("blue"));
  
                              backgroundColor = new Color(red, green, blue);
                              break;
                          }
  
                          colorEntry = (IIOMetadataNode) colorEntry.getNextSibling();
                      }
                  }
              }
          }
  
          BufferedImage master = null;
          boolean hasBackround = false;
  
          for (int frameIndex = 0;; frameIndex++) {
              BufferedImage image;
              try{
                  image = reader.read(frameIndex);
              }catch (IndexOutOfBoundsException io){
                  break;
              }
  
              if (width == -1 || height == -1){
                  width = image.getWidth();
                  height = image.getHeight();
              }
  
              IIOMetadataNode root = (IIOMetadataNode) reader.getImageMetadata(frameIndex).getAsTree("javax_imageio_gif_image_1.0");
              IIOMetadataNode gce = (IIOMetadataNode) root.getElementsByTagName("GraphicControlExtension").item(0);
              NodeList children = root.getChildNodes();
  
              int delay = Integer.valueOf(gce.getAttribute("delayTime"));
  
              String disposal = gce.getAttribute("disposalMethod");
  
              if (master == null){
                  master = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
                  master.createGraphics().setColor(backgroundColor);
                  master.createGraphics().fillRect(0, 0, master.getWidth(), master.getHeight());
  
                  hasBackround = image.getWidth() == width && image.getHeight() == height;
  
                  master.createGraphics().drawImage(image, 0, 0, null);
              }else{
                  int x = 0;
                  int y = 0;
  
                  for (int nodeIndex = 0; nodeIndex < children.getLength(); nodeIndex++){
                      Node nodeItem = children.item(nodeIndex);
  
                      if (nodeItem.getNodeName().equals("ImageDescriptor")){
                          NamedNodeMap map = nodeItem.getAttributes();
  
                          x = Integer.valueOf(map.getNamedItem("imageLeftPosition").getNodeValue());
                          y = Integer.valueOf(map.getNamedItem("imageTopPosition").getNodeValue());
                      }
                  }
  
                  if (disposal.equals("restoreToPrevious")){
                      BufferedImage from = null;
                      for (int i = frameIndex - 1; i >= 0; i--){
                          if (!frames.get(i).getDisposal().equals("restoreToPrevious") || frameIndex == 0){
                              from = frames.get(i).getImage();
                              break;
                          }
                      }
  
                      {
                          ColorModel model = from.getColorModel();
                          boolean alpha = from.isAlphaPremultiplied();
                          WritableRaster raster = from.copyData(null);
                          master = new BufferedImage(model, raster, alpha, null);
                      }
                  }else if (disposal.equals("restoreToBackgroundColor") && backgroundColor != null){
                      if (!hasBackround || frameIndex > 1){
                          master.createGraphics().fillRect(lastx, lasty, frames.get(frameIndex - 1).getWidth(), frames.get(frameIndex - 1).getHeight());
                      }
                  }
                  master.createGraphics().drawImage(image, x, y, null);
  
                  lastx = x;
                  lasty = y;
              }
  
              {
                  BufferedImage copy;
  
                  {
                      ColorModel model = master.getColorModel();
                      boolean alpha = master.isAlphaPremultiplied();
                      WritableRaster raster = master.copyData(null);
                      copy = new BufferedImage(model, raster, alpha, null);
                  }
                  frames.add(new ImageFrame(copy, delay, disposal, image.getWidth(), image.getHeight()));
              }
  
              master.flush();
          }
          reader.dispose();
  
          ImageFrame[] framez = frames.toArray(new ImageFrame[frames.size()]);
          int totalWidth = 0;
          int maxHeight = framez[0].getHeight();
          for (ImageFrame frame : framez) {
              totalWidth += frame.getWidth();
              if (frame.getHeight() > maxHeight) {
                  maxHeight = frame.getHeight();
              }
          }
          BufferedImage finalImage = new BufferedImage(totalWidth, maxHeight, BufferedImage.TYPE_INT_RGB);
          Graphics graphics = finalImage.getGraphics();
          int offset = 0;
          int delay = 0;
          for (ImageFrame frame : framez) {
              graphics.drawImage(frame.getImage(), offset, 0, null);
              offset += frame.getWidth();
              delay += frame.getDelay() * 10;
          }
          delay /= framez.length;
          graphics.dispose();
  
          ByteArrayOutputStream baos = new ByteArrayOutputStream();
          ImageIO.write(finalImage, "gif", baos);
          InputStream is = new ByteArrayInputStream(baos.toByteArray());
          byte[] bytez = baos.toByteArray();
  
  
          Image image1 = new Image(TextureLoader.getTexture("GIF", is));
          return new Animation(new SpriteSheet(image1, width, height), delay);
      }*/
  
  
  }
  