imazen / imageflow

High-performance image manipulation for web servers. Includes imageflow_server, imageflow_tool, and libimageflow
https://docs.imageflow.io/
GNU Affero General Public License v3.0
4.14k stars 140 forks source link

Repeated Gif convertation fails with "unexpected EOF" #643

Open FlipSs opened 3 years ago

FlipSs commented 3 years ago

Hello!

Steps to reproduce: 1) Resize some gif image 2) Resize output from first step

Example gif: https://media2.giphy.com/media/BLjVY7KIN1fYLLvkLh/giphy.gif?cid=ecf05e472d5ea09f14d415d582fe28c7665c258b75644605&rid=giphy.gif&ct=g

Example code:

public class Test 
{
                public async Task<byte[]> ConvertAsync(byte[] image)
        {
            using var imageSource = new BytesSource(image);

            using var job = new ImageJob();

            var node = job.Decode(
                imageSource,
                new DecodeCommands().SetIgnoreColorProfileErrors(true)
            );

            await using var resultStream = new MemoryStream();

            await node.Constrain(new Constraint(200, 100))
            .EncodeToStream(resultStream, false, new GifEncoder())
            .Finish()
            .InProcessAsync()
            .ConfigureAwait(false);

            return resultStream.ToArray();
        }

        public async Task Test(byte[] gif)
        {
            var converted = await ConvertAsync(gif);
            await ConvertAsync(converted); // throws error
        }
}

Error: Exception: Imageflow.Bindings.ImageflowException Error: ImageMalformed: "unexpected EOF" at imageflow_core/src/codecs/gif/mod.rs:57:91 https://github.com/imazen/imageflow/blob/1f6dc67eef41132d5d3300676daa5d42ae7f8941/imageflow_core/src/codecs/gif/mod.rs#L57 imageflow_core/src/codecs/gif/mod.rs:162:54 https://github.com/imazen/imageflow/blob/1f6dc67eef41132d5d3300676daa5d42ae7f8941/imageflow_core/src/codecs/gif/mod.rs#L162 imageflow_core/src/flow/nodes/codecs_and_pointer.rs:222:65 https://github.com/imazen/imageflow/blob/1f6dc67eef41132d5d3300676daa5d42ae7f8941/imageflow_core/src/flow/nodes/codecs_and_pointer.rs#L222 imageflow_core/src/flow/execution_engine.rs:477:114 https://github.com/imazen/imageflow/blob/1f6dc67eef41132d5d3300676daa5d42ae7f8941/imageflow_core/src/flow/execution_engine.rs#L477 imageflow_core/src/context.rs:419:59 https://github.com/imazen/imageflow/blob/1f6dc67eef41132d5d3300676daa5d42ae7f8941/imageflow_core/src/context.rs#L419 imageflow_core/src/context_methods.rs:50:68 https://github.com/imazen/imageflow/blob/1f6dc67eef41132d5d3300676daa5d42ae7f8941/imageflow_core/src/context_methods.rs#L50

lilith commented 3 years ago

Sorry for the super late reply. I was on vacation, then came back and immediately had to move to a new house & office.

I only see a single resize step here. Is there more code?

On Tue, Jun 8, 2021, 8:53 AM Pavel Eroshkin @.***> wrote:

Hello!

Steps to reproduce:

  1. Resize some gif image
  2. Resize output from first step

Example gif:

https://media2.giphy.com/media/BLjVY7KIN1fYLLvkLh/giphy.gif?cid=ecf05e472d5ea09f14d415d582fe28c7665c258b75644605&rid=giphy.gif&ct=g

Example code:

public class Test { public async Task<byte[]> ConvertAsync(byte[] image) { using var imageSource = new BytesSource(image);

      using var job = new ImageJob();

      var node = job.Decode(
          imageSource,
          new DecodeCommands().SetIgnoreColorProfileErrors(true)
      );

      await using var resultStream = new MemoryStream();

      await node.Constrain(new Constraint(200, 100))
      .EncodeToStream(resultStream, false, new GifEncoder())
      .Finish()
      .InProcessAsync()
      .ConfigureAwait(false);

      return resultStream.ToArray();
  }

  public async Task Test(byte[] gif)
  {
      var converted = await ConvertAsync(gif);
      await ConvertAsync(converted); // throws error
  }

}

Error: Exception: Imageflow.Bindings.ImageflowException Error: ImageMalformed: "unexpected EOF" at imageflow_core/src/codecs/gif/mod.rs:57:91

https://github.com/imazen/imageflow/blob/1f6dc67eef41132d5d3300676daa5d42ae7f8941/imageflow_core/src/codecs/gif/mod.rs#L57 imageflow_core/src/codecs/gif/mod.rs:162:54 https://github.com/imazen/imageflow/blob/1f6dc67eef41132d5d3300676daa5d42ae7f8941/imageflow_core/src/codecs/gif/mod.rs#L162 imageflow_core/src/flow/nodes/codecs_and_pointer.rs:222:65 https://github.com/imazen/imageflow/blob/1f6dc67eef41132d5d3300676daa5d42ae7f8941/imageflow_core/src/flow/nodes/codecs_and_pointer.rs#L222 imageflow_core/src/flow/execution_engine.rs:477:114 https://github.com/imazen/imageflow/blob/1f6dc67eef41132d5d3300676daa5d42ae7f8941/imageflow_core/src/flow/execution_engine.rs#L477 imageflow_core/src/context.rs:419:59 https://github.com/imazen/imageflow/blob/1f6dc67eef41132d5d3300676daa5d42ae7f8941/imageflow_core/src/context.rs#L419 imageflow_core/src/context_methods.rs:50:68 https://github.com/imazen/imageflow/blob/1f6dc67eef41132d5d3300676daa5d42ae7f8941/imageflow_core/src/context_methods.rs#L50

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/imazen/imageflow/issues/643, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAA2LH63VDEMIRR4TI24YB3TRYVIFANCNFSM46KEHMAA .

FlipSs commented 3 years ago

Hi, here are 2 resize steps, they are the same because this is an example, but the second is executed on the result of the first.

public async Task Test(byte[] gif)
{
        // first resize 
    var converted = await ConvertAsync(gif);
    // second resize
    await ConvertAsync(converted); // throws error
}
lilith commented 3 years ago

Try dropping .ConfigureAwait(false)

On Fri, Jun 25, 2021, 7:57 AM Pavel Eroshkin @.***> wrote:

Hi, here are 2 resize steps, they are the same because this is an example, but the second is executed on the result of the first.

public async Task Test(byte[] gif) { // first resize var converted = await ConvertAsync(gif); // second resize await ConvertAsync(converted); // throws error }

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/imazen/imageflow/issues/643, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAA2LHZLTACDBYVP6RZSKYLTUSDLTANCNFSM46KEHMAA .

FlipSs commented 3 years ago

doesn't work either

ajbeaven commented 2 years ago

I think I may be hitting something related to this with imageflow-dotnet-server too.

Here's an example GIF I got off Google Images that when stored in Azure Storage (don't think this is relevant) and referenced by imageflow-dotnet-server, fails to render correctly:

4016070_24725e92-1b64-4c96-b927-2b2ed2e2452b

Stack trace for this error:

Imageflow.Bindings.ImageflowException: ImageMalformed: "unexpected EOF" at
imageflow_core\src\codecs\gif\mod.rs:57:91
https://github.com/imazen/imageflow/blob/1f6dc67eef41132d5d3300676daa5d42ae7f8941/imageflow_core\src\codecs\gif\mod.rs#L57
imageflow_core\src\codecs\gif\mod.rs:162:54
https://github.com/imazen/imageflow/blob/1f6dc67eef41132d5d3300676daa5d42ae7f8941/imageflow_core\src\codecs\gif\mod.rs#L162
imageflow_core\src\flow\nodes\codecs_and_pointer.rs:222:65
https://github.com/imazen/imageflow/blob/1f6dc67eef41132d5d3300676daa5d42ae7f8941/imageflow_core\src\flow\nodes\codecs_and_pointer.rs#L222
imageflow_core\src\flow\execution_engine.rs:477:114
https://github.com/imazen/imageflow/blob/1f6dc67eef41132d5d3300676daa5d42ae7f8941/imageflow_core\src\flow\execution_engine.rs#L477
imageflow_core\src\context.rs:419:59
https://github.com/imazen/imageflow/blob/1f6dc67eef41132d5d3300676daa5d42ae7f8941/imageflow_core\src\context.rs#L419
imageflow_core\src\context_methods.rs:50:68
https://github.com/imazen/imageflow/blob/1f6dc67eef41132d5d3300676daa5d42ae7f8941/imageflow_core\src\context_methods.rs#L50
Active node:
NodeDebugInfo {
    stable_id: 464,
    params: Json(
        Decode {
            io_id: 0,
            commands: None,
        },
    ),
    index: NodeIndex(1),
}

   at Imageflow.Bindings.JobContext.AssertReady()
   at Imageflow.Bindings.JobContext.SendJsonBytes(String method, Byte[] utf8Json)
   at Imageflow.Bindings.JobContext.Execute[T](T message)
   at Imageflow.Fluent.ImageJob.FinishAsync(JobExecutionOptions executionOptions, SecurityOptions securityOptions, CancellationToken cancellationToken)
   at Imageflow.Server.ImageJobInfo.ProcessUncached()
   at Imageflow.Server.ImageflowMiddleware.<>c__DisplayClass15_0.<<ProcessWithStreamCache>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at Imazen.HybridCache.AsyncCache.<>c__DisplayClass35_0.<<GetOrCreateBytes>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at Imazen.Common.Concurrency.AsyncLockProvider.TryExecuteAsync(String key, Int32 timeoutMs, CancellationToken cancellationToken, Func`1 success)
   at Imazen.HybridCache.AsyncCache.GetOrCreateBytes(Byte[] key, AsyncBytesResult dataProviderCallback, CancellationToken cancellationToken, Boolean retrieveContentType)
   at Imazen.HybridCache.HybridCache.GetOrCreateBytes(Byte[] key, AsyncBytesResult dataProviderCallback, CancellationToken cancellationToken, Boolean retrieveContentType)
   at Imageflow.Server.ImageflowMiddleware.ProcessWithStreamCache(HttpContext context, String cacheKey, ImageJobInfo info)
   at Imageflow.Server.ImageflowMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
lilith commented 1 year ago

I think this is a codec problem: https://github.com/image-rs/image-gif/issues/138

lilith commented 1 year ago

The "big hug" image is malformed, and the codec I use doesn't support recovering from that (yet).

$ # /usr/bin/giftopnm is owned by netpbm 10.73.37-2
$ giftopnm /tmp/139770827-18e25c4e-eb0a-4058-ba48-ddc3849090ee.gif > /dev/null 
giftopnm: Error accessing Image 67 of stream.  File read error where start of image descriptor or end of GIF expected.  End of file encountered