Иконка ресурса

Воспроизведение gif. 0.1

Нет прав для скачивания
194
12
29
Zloy_GreGan добавил(а) новый ресурс:

Воспроизведение gif. - Воспроизведение gif анимации в пару строк кода.

Иногда бывают ситуации когда нужно воспроизвести gif анимацию, и тогда в голову приходит мысля разбить её на кадры и воспроизводить их по очереди, но это не удобно. После разбития её на кадры получится много картинок которые будут весить в разы больше самой гифки. Я предлагаю вам не делать так, ведь это можно сделать проще! Вам нужно будет скачать 1 класс, впихнуть его к себе в проект и написать пару строк кода в одной из которых нужно будет указать путь до вашей гифки, ну и воспроизвести...

Узнать больше об этом ресурсе...
 

tox1cozZ

aka Agravaine
Модератор
7,536
486
2,348
Полезно.
Единственный момент: ImageIO очень медленный. На гитхабе есть декодеры, который работают довольно шустро. При желании можно адаптировать под один из них.
 
1,020
48
201
Дергал когда-то из модов xMod серии.
От (int), (float) и тд не чистил.
Работает на 1.12.2.

Raw Code:
public class GuiGif {
    public int frames;
    public BufferedImage[] images;
    public int[] imagesGLIDs;
    public boolean errored;
    private int currentFrame = 0;
    protected int x;
    protected int y;
    private int x2;
    private int y2;
    public static final int PIXEL_FORMAT_RGBA = 4;
   
    public GuiGif(String path, int x, int y, int x2, int y2) {
        this.x = x;
        this.y = y;
        this.x2 = x2;
        this.y2 = y2;
        InputStream is = null;
        try {
            int i;
            is = this.getClass().getResourceAsStream("/assets/MODID/textures/gui/" + path +".gif");
            ImageInputStream stream = ImageIO.createImageInputStream(is);
            Iterator<ImageReader> readers = ImageIO.getImageReaders(stream);
            if (!readers.hasNext()) {
                throw new IOException("No suitable reader found for image");
            }
            ImageReader reader = readers.next();
            reader.setInput(stream);
            this.frames = reader.getNumImages(true);
            BufferedImage[] images = new BufferedImage[this.frames];
            this.imagesGLIDs = new int[this.frames];
            for (i = 0; i < this.frames; ++i) {
                images[i] = reader.read(i);
            }
            reader.dispose();
            for (i = 0; i < this.frames; ++i) {
                this.imagesGLIDs[i] = this.loadTexture(images[i]);
            }
        }
        catch (IOException e) {
            try {
                e.printStackTrace();
            }
            catch (Throwable throwable) {
                IOUtils.closeQuietly(is);
                throw throwable;
            }
            IOUtils.closeQuietly((InputStream)is);
        }
        IOUtils.closeQuietly((InputStream)is);
    }
   
    public void increaseFrame() {
        this.currentFrame = this.currentFrame != this.frames - 1 ? ++this.currentFrame : 0;
    }
   
    private int loadTexture(BufferedImage image) {
        int[] pixels = new int[image.getWidth() * image.getHeight()];
        image.getRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth());
        ByteBuffer buffer = BufferUtils.createByteBuffer((int)(image.getWidth() * image.getHeight() * 4));
        for (int y = 0; y < image.getHeight(); ++y) {
            for (int x = 0; x < image.getWidth(); ++x) {
                int pixel = pixels[y * image.getWidth() + x];
                buffer.put((byte)(pixel >> 16 & 255));
                buffer.put((byte)(pixel >> 8 & 255));
                buffer.put((byte)(pixel & 255));
                buffer.put((byte)(pixel >> 24 & 255));
            }
        }
        buffer.flip();
        int textureID = GL11.glGenTextures();
        GL11.glBindTexture((int)3553, (int)textureID);
        GL11.glTexParameteri((int)3553, (int)10242, (int)33071);
        GL11.glTexParameteri((int)3553, (int)10243, (int)33071);
        GL11.glTexParameteri((int)3553, (int)10241, (int)9729);
        GL11.glTexParameteri((int)3553, (int)10240, (int)9729);
        GL11.glTexImage2D((int)3553, (int)0, (int)32856, (int)image.getWidth(), (int)image.getHeight(), (int)0, (int)6408, (int)5121, (ByteBuffer)buffer);
        return textureID;
    }
   
    public void draw() {
        GL11.glPushMatrix();
        GL11.glEnable(GL11.GL_TEXTURE_2D);
        GL11.glBindTexture((int)3553, (int)this.imagesGLIDs[this.currentFrame]);
        GL11.glColor4f((float)1.0f, (float)1.0f, (float)1.0f, (float)1.0f);
        GL11.glEnable((int)3042);
        GL11.glBlendFunc((int)770, (int)771);
        GL11.glEnable((int)3008);
        GL11.glAlphaFunc((int)516, (float)0.0f);
        GL11.glBegin((int)7);
        GL11.glTexCoord2d((double)0.0, (double)0.0);
        GL11.glVertex2f((float)this.x, (float)this.y);
        GL11.glTexCoord2d((double)1.0, (double)0.0);
        GL11.glVertex2f((float)this.x2, (float)this.y);
        GL11.glTexCoord2d((double)1.0, (double)1.0);
        GL11.glVertex2f((float)this.x2, (float)this.y2);
        GL11.glTexCoord2d((double)0.0, (double)1.0);
        GL11.glVertex2f((float)this.x, (float)this.y2);
        GL11.glEnd();
        GL11.glPopMatrix();
    }
}

Юз:
private GuiGif gif = new GuiGif(0, 0, 250, 250);

в тик методе:
gif.increaseFrame();
gif.draw();

(можете объеденить методы.)
 
2,502
78
380
А всех устраивает, что кадры gif переключаются каждый кадр игры? А если у меня 500фпс? В gif для каждого кадра есть свой frametime, если не ошибаюсь.

Никого не смущает, что у вас утечка видеопамяти? Причем и в сливе, и у @BlesseNtumble.

Выгружать всю gif в видеопамять тоже такое себе, конечно.
 

tox1cozZ

aka Agravaine
Модератор
7,536
486
2,348
А всех устраивает, что кадры gif переключаются каждый кадр игры? А если у меня 500фпс? В gif для каждого кадра есть свой frametime, если не ошибаюсь.
Не обратил внимания, но да.

Никого не смущает, что у вас утечка видеопамяти? Причем и в сливе, и у @BlesseNtumble.
Где?

Выгружать всю gif в видеопамять тоже такое себе, конечно.
А что, постоянно с диска читать? Ну фиг знает, медленно как-то. Тут же не огромные гифки по 100мб грузим, а обычно для аватарок или подобного, которые несколько сотен кб весят.
 
395
7
117
Это надо делать в отдельном потоке.

Да ещё и сохранить вершины стоило бы в vao, чтобы не вызывать их постоянно.

И вообще, какой 1.12.2 без GlStateManager?
 
Последнее редактирование:
2,502
78
380
Текстуры никогда не удаляются.

А что, постоянно с диска читать? Ну фиг знает, медленно как-то. Тут же не огромные гифки по 100мб грузим, а обычно для аватарок или подобного, которые несколько сотен кб весят.
Не. Один раз считать в оперативу, а затем стримить на gpu через double-buffered PBO.
Я так делал абстрактную систему для стриминга вообще любого анимационного или видео формата.
 

tox1cozZ

aka Agravaine
Модератор
7,536
486
2,348
Ну видос, наверное, надо как раз читать из файла параллельно и уже данные прокидывать в опенгл. Майн так с длинной музыкой делает, чтобы не грузить 3-4 минуты трек весь сразу.
 
2,502
78
380
Это уже другой вопрос. Я говорю только о стриминге на gpu.
 
Сверху