matt-way / gifuct-js

Fastest javascript .GIF decoder/parser
MIT License
430 stars 64 forks source link

Help with some minorly corrupted gifs #65

Open konsumer opened 1 month ago

konsumer commented 1 month ago

Hi, first thanks for making this very useful library.

I am working on a tool to turn a gif into code for display on an OLED. You can see the tool here. For the most part it works pretty well. Basically I use gifuct to load the gif, split it into canvases for each frame, then apply a dither, then from there output different kinds of code.

I noticed that some gifs have issues, like this:

input

voltron

output

voltron (2)

The issue is what looks kinda like lightning when the Voltrons are dancing.

At first I thought it was the gif output lib I am using gifenc, because I didn't see the problem on the preview-canvas, but I tested the outputted code on a real OLED, too, and it showed up. I figured it was a problem with transparency, so I tried filling the canvas before drawing, and it made the problem show up on the preview-canvas as well. I also tried adding {alpha: false} to the context, which did not seem to help.

Here is how I load it:

// get all frames in the original image as an array of canvas 
export function process(buffer) { 
  const gif = parseGIF(buffer)
  const frames = decompressFrames(gif, true)

  const out = []
  if (frames?.length) {
    const { dims: {width, height}, delay } = frames[0]
    for (const frame of frames) {
      const otx = (new OffscreenCanvas(width, height)).getContext("2d")
      const imgData = otx.createImageData(width, height)

      for (let i = 0; i < imgData.data.length; i += 4) {
        imgData.data[i+0] = frame.patch[i + 0]
        imgData.data[i+1] = frame.patch[i + 1]
        imgData.data[i+2] = frame.patch[i + 2]
        imgData.data[i+3] = frame.patch[i + 3]
      }

      otx.putImageData(imgData, 0, 0)
      out.push(otx)
    }
    return { width, height, delay, frames: out }
  }

  return {frames: []}
}

Do I need to do something else to make sure it's a complete no-transparency frame?

konsumer commented 1 month ago

As another test, I tried not dithering at all, and just running the same frames through the input, resize & output pipelines, and it seems to have the same issue.

voltron (8)

konsumer commented 1 month ago

Also, some (most) images are fine, it's just this Voltron image, in my testing. For example, this turns out exactly as expected:

siouxsie (3)

matt-way commented 1 month ago

Testing your gif above, it does seem to render fine for me. Have a look in https://github.com/matt-way/gifuct-js/blob/master/demo/demo.js to see how some basic rendering is done. I suspect the problem has something to do with treating each frame individually, and not as patches over the gif itself.

konsumer commented 1 month ago

I suspect the problem has something to do with treating each frame individually, and not as patches over the gif itself.

I think so too. The display works fine on a canvas (since it patches to the same canvas.) Maybe on each frame, I should grab a copy of previous frame first.