imazen / imageflow-dotnet

The official .NET API for Imageflow, the Rust image processing and optimization engine for web servers
GNU Affero General Public License v3.0
143 stars 25 forks source link

Error when resizing one image to multiple sizes #7

Closed bjornsallarp closed 4 years ago

bjornsallarp commented 5 years ago

I'm testing this library and my use case is that I have one image that I want to output to multiple sizes and jpg quality. I figured it would probably be best to decode the image once and that the Branch-method would allow me to do this? Here's my test code:

`public async Task Get([FromQuery]uint width = 1000) { var encoder = new LibJpegTurboEncoder {Progressive = true, Quality = 90};

        using (var b = new FluentBuildJob())
        {
            var bytes = await System.IO.File.ReadAllBytesAsync(@"C:\\Users\\bjorn.sallarp\\Pictures\\arkaden-takterrass.jpg");
            await b.Decode(new ArraySegment<byte>(bytes))
                .Branch(x => HighRes(x, width))
                .Branch(x => LowRes(x, width))
                .EncodeToStream(Response.Body, false, encoder)
                .FinishAsync();
        }
    }

    private BuildEndpoint HighRes(BuildNode arg, uint width)
    {
        var outfile = $@"C:\\Users\\bjorn.sallarp\\Pictures\\arkaden-takterrass-hires.jpg";
        var encoder = new LibJpegTurboEncoder { Progressive = true, Quality = 90 };
        return arg.ConstrainWithin(width, null, null,
                downFilter: InterpolationFilter.Lanczos,
                upFilter: InterpolationFilter.Mitchell,
                interpolationColorspace: ScalingFloatspace.Linear,
                resampleWhen: ResampleWhen.Always)
            .Encode(new StreamDestination(System.IO.File.OpenWrite(outfile), true), encoder);
    }

    private BuildEndpoint LowRes(BuildNode arg, uint width)
    {
        var outfile = @"C:\\Users\\bjorn.sallarp\\Pictures\\arkaden-takterrass-lowres.jpg";
        var encoder = new LibJpegTurboEncoder { Progressive = true, Quality = 60 };
        return arg.ConstrainWithin(width, null)
            .Encode(new StreamDestination(System.IO.File.OpenWrite(outfile), true), encoder);
    }

This is the error I get: ImageflowException: GraphInvalid: InvalidNodeConnections: Node type primitive_encoder prohibits child nodes, but had 1 outbound edges. atimageflow_core\src\flow\execution_engine.rs:77:21https://github.com/imazen/imageflow/blob/6f7f054d868c9726a42eaaae7277900a5cb4e3a1/imageflow_core\src\flow\execution_engine.rs#L77imageflow_core\src\context.rs:244:59https://github.com/imazen/imageflow/blob/6f7f054d868c9726a42eaaae7277900a5cb4e3a1/imageflow_core\src\context.rs#L244imageflow_core\src\context_methods.rs:32:68https://github.com/imazen/imageflow/blob/6f7f054d868c9726a42eaaae7277900a5cb4e3a1/imageflow_core\src\context_methods.rs#L32Active node:NodeDebugInfo { stable_id: -1, params: Json( Encode { io_id: 2, preset: LibjpegTurbo { quality: Some( 60 ), progressive: Some( true ), optimize_huffman_coding: None } } ), index: NodeIndex(1)}989`

By accident i found that this works: b.Decode(new ArraySegment<byte>(bytes)); await b.Decode(new ArraySegment<byte>(bytes)) .Branch(x => HighRes(x, width-1)) .Branch(x => HighRes(x, width-2)) .Branch(x => HighRes(x, width-3)) .Branch(x => HighRes(x, width-4)) .Branch(x => LowRes(x, width)) .EncodeToStream(Response.Body, false, encoder) .FinishAsync();

I guess it has something to do with how the command is built? Perhaps it would have worked if FinishAsync could be called directly from Branch, without adding the last output outside of the branch with EncodeToStream?

lilith commented 4 years ago

Thank you for reporting this! It has been fixed in 8aa89b22 (will be released as v0.4.2).