EzDev.org

ImageProcessor

ImageProcessor - :camera: A fluent wrapper around System.Drawing for the processing of image files. An open-source solution for on-the-fly processing of images using .NET :: ImageProcessor a .net library for on-the-fly processing of images.


WPF ImageProcessor slow first time use

In my WPF application i need to make thumbs from photo the user add to the program. To do this i use the ImageProcessor package which works perfect for me. Bu i have one small problem the first use in an application session always takes 5 a 10 seconds to complete every next thumb making in the same session only takes milliseconds.

It looks like the DLL is only loaded on first use. Is there a way to make this faster?

I've tried replacing ImageProcessor with ImageResizer and also tried loading ImageProccesor on application startup both didn't work.


Source: (StackOverflow)

Split resize algorithm into two passes

I have written the following resizing algorithm which can correctly scale an image up or down. It's far too slow though due to the inner iteration through the array of weights on each loop.

I'm fairly certain I should be able to split out the algorithm into two passes much like you would with a two pass Gaussian blur which would vastly reduce the operational complexity and speed up performance. Unfortunately I can't get it to work. Would anyone be able to help?

Parallel.For(
    startY,
    endY,
    y =>
    {
        if (y >= targetY && y < targetBottom)
        {
            Weight[] verticalValues = this.verticalWeights[y].Values;

            for (int x = startX; x < endX; x++)
            {
                Weight[] horizontalValues = this.horizontalWeights[x].Values;

                // Destination color components
                Color destination = new Color();

                // This is where there is too much operation complexity.
                foreach (Weight yw in verticalValues)
                {
                    int originY = yw.Index;

                    foreach (Weight xw in horizontalValues)
                    {
                        int originX = xw.Index;
                        Color sourceColor = Color.Expand(source[originX, originY]);
                        float weight = yw.Value * xw.Value;
                        destination += sourceColor * weight;
                    }
                }

                destination = Color.Compress(destination);
                target[x, y] = destination;
            }
        }
    });

Weights and indices are calculated as follows. One for each dimension:

/// <summary>
/// Computes the weights to apply at each pixel when resizing.
/// </summary>
/// <param name="destinationSize">The destination section size.</param>
/// <param name="sourceSize">The source section size.</param>
/// <returns>
/// The <see cref="T:Weights[]"/>.
/// </returns>
private Weights[] PrecomputeWeights(int destinationSize, int sourceSize)
{
    IResampler sampler = this.Sampler;
    float ratio = sourceSize / (float)destinationSize;
    float scale = ratio;

    // When shrinking, broaden the effective kernel support so that we still
    // visit every source pixel.
    if (scale < 1)
    {
        scale = 1;
    }

    float scaledRadius = (float)Math.Ceiling(scale * sampler.Radius);
    Weights[] result = new Weights[destinationSize];

    // Make the weights slices, one source for each column or row.
    Parallel.For(
        0,
        destinationSize,
        i =>
            {
                float center = ((i + .5f) * ratio) - 0.5f;
                int start = (int)Math.Ceiling(center - scaledRadius);

                if (start < 0)
                {
                    start = 0;
                }

                int end = (int)Math.Floor(center + scaledRadius);

                if (end > sourceSize)
                {
                    end = sourceSize;

                    if (end < start)
                    {
                        end = start;
                    }
                }

                float sum = 0;
                result[i] = new Weights();

                List<Weight> builder = new List<Weight>();
                for (int a = start; a < end; a++)
                {
                    float w = sampler.GetValue((a - center) / scale);

                    if (w < 0 || w > 0)
                    {
                        sum += w;
                        builder.Add(new Weight(a, w));
                    }
                }

                // Normalise the values
                if (sum > 0 || sum < 0)
                {
                    builder.ForEach(w => w.Value /= sum);
                }

                result[i].Values = builder.ToArray();
                result[i].Sum = sum;
            });

    return result;
}

/// <summary>
/// Represents the weight to be added to a scaled pixel.
/// </summary>
protected class Weight
{
    /// <summary>
    /// The pixel index.
    /// </summary>
    public readonly int Index;

    /// <summary>
    /// Initializes a new instance of the <see cref="Weight"/> class.
    /// </summary>
    /// <param name="index">The index.</param>
    /// <param name="value">The value.</param>
    public Weight(int index, float value)
    {
        this.Index = index;
        this.Value = value;
    }

    /// <summary>
    /// Gets or sets the result of the interpolation algorithm.
    /// </summary>
    public float Value { get; set; }
}

/// <summary>
/// Represents a collection of weights and their sum.
/// </summary>
protected class Weights
{
    /// <summary>
    /// Gets or sets the values.
    /// </summary>
    public Weight[] Values { get; set; }

    /// <summary>
    /// Gets or sets the sum.
    /// </summary>
    public float Sum { get; set; }
}

Each IResampler provides the appropriate series of weights based on the given index. the bicubic resampler works as follows.

/// <summary>
/// The function implements the bicubic kernel algorithm W(x) as described on
/// <see rel='nofollow' href="https://en.wikipedia.org/wiki/Bicubic_interpolation#Bicubic_convolution_algorithm">Wikipedia</see>
/// A commonly used algorithm within imageprocessing that preserves sharpness better than triangle interpolation.
/// </summary>
public class BicubicResampler : IResampler
{
    /// <inheritdoc/>
    public float Radius => 2;

    /// <inheritdoc/>
    public float GetValue(float x)
    {
        // The coefficient.
        float a = -0.5f;

        if (x < 0)
        {
            x = -x;
        }

        float result = 0;

        if (x <= 1)
        {
            result = (((1.5f * x) - 2.5f) * x * x) + 1;
        }
        else if (x < 2)
        {
            result = (((((a * x) + 2.5f) * x) - 4) * x) + 2;
        }

        return result;
    }
}

Here's an example of an image resized by the existing algorithm. The output is correct (note the silvery sheen is preserved).

Original image

Original unscaled image

Image halved in size using the bicubic resampler.

Image halved in size

The code is part of a much larger library that I am writing to add image processing to corefx.


Source: (StackOverflow)

Mimicking this imaging effect

I am asking this question as the other one is two years old and not answered accurately.

I'm looking to replicate the PhotoShop effect mentioned in this article in C#. Adobe call it a Color halftone, I think it looks like some sort of rotated CMYK halftone thingy. Either way I don't know how I would do it.

Current code sample is below.

Any ideas?

Color halftone effect

P.S.

This isn't homework. I'm looking to upgrade the comic book effect I have in my OSS project ImageProcessor.

ImageProcessor comic effect

Progress Update.

So here's some code to show what I have done so far...

I can convert to and from CMYK to RGB fairly easily and accurately enough for my needs and also print out a patterned series of ellipses based on the the intensity of each colour component at a series of points.

What I am stuck at just now is rotating the graphics object for each colour so that the points are laid at the angles specified in the code. Can anyone give me some pointers as how to go about that?

public Image ProcessImage(ImageFactory factory)
{
    Bitmap newImage = null;
    Image image = factory.Image;

    try
    {
        int width = image.Width;
        int height = image.Height;

        // These need to be used.
        float cyanAngle = 105f;
        float magentaAngle = 75f;
        float yellowAngle = 90f;
        float keylineAngle = 15f;

        newImage = new Bitmap(width, height);
        newImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);

        using (Graphics graphics = Graphics.FromImage(newImage))
        {
            // Reduce the jagged edges.
            graphics.SmoothingMode = SmoothingMode.AntiAlias;
            graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
            graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
            graphics.CompositingQuality = CompositingQuality.HighQuality;

            graphics.Clear(Color.White);

            using (FastBitmap sourceBitmap = new FastBitmap(image))
            {
                for (int y = 0; y < height; y += 4)
                {
                    for (int x = 0; x < width; x += 4)
                    {
                        Color color = sourceBitmap.GetPixel(x, y);

                        if (color != Color.White)
                        {
                            CmykColor cmykColor = color;
                            float cyanBrushRadius = (cmykColor.C / 100) * 3;
                            graphics.FillEllipse(Brushes.Cyan, x, y, cyanBrushRadius, cyanBrushRadius);

                            float magentaBrushRadius = (cmykColor.M / 100) * 3;
                            graphics.FillEllipse(Brushes.Magenta, x, y, magentaBrushRadius, magentaBrushRadius);

                            float yellowBrushRadius = (cmykColor.Y / 100) * 3;
                            graphics.FillEllipse(Brushes.Yellow, x, y, yellowBrushRadius, yellowBrushRadius);

                            float blackBrushRadius = (cmykColor.K / 100) * 3;
                            graphics.FillEllipse(Brushes.Black, x, y, blackBrushRadius, blackBrushRadius);
                        }
                    }
                }
            }
        }

        image.Dispose();
        image = newImage;
    }
    catch (Exception ex)
    {
        if (newImage != null)
        {
            newImage.Dispose();
        }

        throw new ImageProcessingException("Error processing image with " + this.GetType().Name, ex);
    }

    return image;
}
Input Image

input image

Current Output

As you can see since the drawn ellipses are not angled colour output is incorrect.

current output


Source: (StackOverflow)

How can i read EXIF data in AspNet.Core

What's the best way to read EXIF info of a picture in Asp.Net Core. I am using ImageProcessorCore alpha from myget to rotate pictures but i haven't found a way to read exif data is there a in library way of doing this?


Source: (StackOverflow)

Running out of memory resizing images in dot net

I'm having a lot of issues running out of memory resizing images. I was at first convinced that I was simply leaking, so I switched my custom code for something based around https://github.com/JimBobSquarePants/ImageProcessor and the same issues occur.

So a source image causing problems might be 7137x10096 Uncompressed that should be 7137x10096x4 = 288220608 bytes or 274Mb. OK, thats "big" but why is it troublingly big? Running it IISExpress (32bit) its throws out-of-memory. Running on Azure in a 64bit server with 3.5GB it simply unreliable.

Error is "An exception of type 'System.OutOfMemoryException' occurred in System.Drawing.dll but was not handled in user code"

Code based on ImageProcessor throws on the imageFactory.Load statement

   public bool ProcessStream(Size size, Func<MemoryStream, bool> resultCallback, string gravity, Stream inStream, int quality=80)
    {
        inStream.Position = 0;
        bool res = false;
        using (var outStream = new MemoryStream())
        {
            using (var imageFactory = new ImageFactory())
            {
                var anchor = AnchorPosition.Center;
                if (gravity == "top") anchor = AnchorPosition.Top;
                if (gravity == "bottom") anchor = AnchorPosition.Bottom;
                var layer = new ResizeLayer(size, ResizeMode.Pad, anchor);

                imageFactory.Load(inStream)
                    .Resize(layer)
                    .BackgroundColor(System.Drawing.ColorTranslator.FromHtml("#FFFFFF"))
                    .Quality(quality)
                    .Save(outStream);
                res = resultCallback(outStream);
            }
        }
        return res;
    }

In its simplest test case I'm calling the above with

     public bool nop(MemoryStream s)
     {
         return true;
     }

     public string TestResize()
     {
         var resizer = new ResizeImage();
         var size = new System.Drawing.Size(300, 400);
         using (
             var filestream =
                 new FileStream(
                     @"C:\Users\Andrew\problem issues\NastyLargeImageThatBreaksThings.jpg",
                     FileMode.Open, FileAccess.Read))
         {
             var res = resizer.ProcessStream(size, nop, "top", filestream, 75);
             return res.ToString();
         }
     }

I can:

1) Try a different technique

2) Upgrade my Azure servers to have more memory (not sure if that will help)

3) Try resizing via a 3rd party service such as http://www.blitline.com/ which has some Azure specific integration.

Any understanding of why images this size can't be handled in Systen.Drawing would be much appreciated.


Source: (StackOverflow)

Asynchronous locking based on a key

I'm attempting to figure out an issue that has been raised with my ImageProcessor library here where I am getting intermittent file access errors when adding items to the cache.

System.IO.IOException: The process cannot access the file 'D:\home\site\wwwroot\app_data\cache\0\6\5\f\2\7\065f27fc2c8e843443d210a1e84d1ea28bbab6c4.webp' because it is being used by another process.

I wrote a class designed to perform an asynchronous lock based upon a key generated by a hashed url but it seems I have missed something in the implementation.

My locking class

public sealed class AsyncDuplicateLock
{
    /// <summary>
    /// The collection of semaphore slims.
    /// </summary>
    private static readonly ConcurrentDictionary<object, SemaphoreSlim> SemaphoreSlims
                            = new ConcurrentDictionary<object, SemaphoreSlim>();

    /// <summary>
    /// Locks against the given key.
    /// </summary>
    /// <param name="key">
    /// The key that identifies the current object.
    /// </param>
    /// <returns>
    /// The disposable <see cref="Task"/>.
    /// </returns>
    public IDisposable Lock(object key)
    {
        DisposableScope releaser = new DisposableScope(
        key,
        s =>
        {
            SemaphoreSlim locker;
            if (SemaphoreSlims.TryRemove(s, out locker))
            {
                locker.Release();
                locker.Dispose();
            }
        });

        SemaphoreSlim semaphore = SemaphoreSlims.GetOrAdd(key, new SemaphoreSlim(1, 1));
        semaphore.Wait();
        return releaser;
    }

    /// <summary>
    /// Asynchronously locks against the given key.
    /// </summary>
    /// <param name="key">
    /// The key that identifies the current object.
    /// </param>
    /// <returns>
    /// The disposable <see cref="Task"/>.
    /// </returns>
    public Task<IDisposable> LockAsync(object key)
    {
        DisposableScope releaser = new DisposableScope(
        key,
        s =>
        {
            SemaphoreSlim locker;
            if (SemaphoreSlims.TryRemove(s, out locker))
            {
                locker.Release();
                locker.Dispose();
            }
        });

        Task<IDisposable> releaserTask = Task.FromResult(releaser as IDisposable);
        SemaphoreSlim semaphore = SemaphoreSlims.GetOrAdd(key, new SemaphoreSlim(1, 1));

        Task waitTask = semaphore.WaitAsync();

        return waitTask.IsCompleted
                   ? releaserTask
                   : waitTask.ContinueWith(
                       (_, r) => (IDisposable)r,
                       releaser,
                       CancellationToken.None,
                       TaskContinuationOptions.ExecuteSynchronously,
                       TaskScheduler.Default);
    }

    /// <summary>
    /// The disposable scope.
    /// </summary>
    private sealed class DisposableScope : IDisposable
    {
        /// <summary>
        /// The key
        /// </summary>
        private readonly object key;

        /// <summary>
        /// The close scope action.
        /// </summary>
        private readonly Action<object> closeScopeAction;

        /// <summary>
        /// Initializes a new instance of the <see cref="DisposableScope"/> class.
        /// </summary>
        /// <param name="key">
        /// The key.
        /// </param>
        /// <param name="closeScopeAction">
        /// The close scope action.
        /// </param>
        public DisposableScope(object key, Action<object> closeScopeAction)
        {
            this.key = key;
            this.closeScopeAction = closeScopeAction;
        }

        /// <summary>
        /// Disposes the scope.
        /// </summary>
        public void Dispose()
        {
            this.closeScopeAction(this.key);
        }
    }
}

Usage - within a HttpModule

private readonly AsyncDuplicateLock locker = new AsyncDuplicateLock();

using (await this.locker.LockAsync(cachedPath))
{
    // Process and save a cached image.
}

Can anyone spot where I have gone wrong? I'm worried that I am misunderstanding something fundamental.

The full source for the library is stored on Github here


Source: (StackOverflow)

ImageProcessor request makes future List Bindings Fail

I am struggling with an issue with my site, where if I make a request to an image using ImageProcessor.Web, that it prevents some future List<> binding requests from working.

I'm not sure whether it's a bug, or whether it's a configuration problem, but I've been struggling to get to the bottom of it.

I have stripped my entire website back to a solution just to demonstrate this binding problem.

I have located the test application at the following address in my S3: https://s3.amazonaws.com/bindingissue/BindingIssue.zip

If you open the application, run the website project and navigate to https://localhost:44300/ it displays the form:

The initial form

If you submit the form, you will see that the page indicates that the value within the text box has been bound and the submitted value appears in the form.

Binding happened successfully

The name of the form element is FilledInValues[0] and it binds the value to a variable in the controller action called FilledInValues which is of type List<string>.

[HttpPost]
public ActionResult Index(TestViewModel requestResponseModel)
{
    if (requestResponseModel.FilledInValues != null && !string.IsNullOrWhiteSpace(requestResponseModel.FilledInValues[0]))
    {
        ViewBag.Success = true;
    }
    else
    {
        ViewBag.Success = false;
    }

    return View(requestResponseModel);
}

Here's the model that is being bound to:

public class TestViewModel
{
    public string UrlId { get; set; }
    public string QuizName { get; set; }
    public int QuestionId { get; set; }
    public List<int?> SelectedAnswers { get; set; }

    // This is the value that fails to bind
    public List<string> FilledInValues { get; set; }

    public bool? IsEmbed { get; set; }
}

Now, when you click the link, it takes you to the following URL in a new tab:

https://localhost:44300/content/images/smileyface.png?width=260&height=100&mode=stretch&bgcolor=FFFFFF

This loads an image from an S3 Bucket, Image Processor resizes the image according to the values specified in the query string. The image should be displayed, it is a smiley face :).

Now, when you return back to the form, refresh the page and submit the form again. It will indicate that the value you submitted did not bind correctly. Even though it did before!

Failed binding

If you put a breakpoint on the Home controller on the Index action, you can observe the value failing to bind.

Now, it will continue to fail to bind this value until you restart the app pool (if the app is hosted on IIS) or if you restart the app within Visual Studio.

The form hasn't changed and the values are still being posted, because I can see then within the Chrome developer tools Network tab and you can see the query string value that has been formatted in the controller's this.Request.Form value once you've submitted the form.

Please can you help me identify why the binding works before and then fails after loading the image that loads through Image Processor?


Source: (StackOverflow)

HTTP Module intercept requests and breaks custom errors configuration

I have an ASP.NET MVC 5 web application which runs locally on IIS 8.5 and after deployment, on Azure Websites - on both cases, the behavior that will be later described is the same.

I configured in the web.config the following custom errors page management (it covers all my cases of custom errors and it has been tested and it's working great):

<system.webServer>
  <httpErrors errorMode="Custom" existingResponse="Replace">
    <clear />
    <error statusCode="400" responseMode="ExecuteURL" path="/App/Error"/>
    <error statusCode="403" responseMode="ExecuteURL" path="/App/Error/Forbidden" />
    <error statusCode="404" responseMode="ExecuteURL" path="/App/Error/NotFound" />
    <error statusCode="500" responseMode="ExecuteURL" path="/App/Error" />
  </httpErrors>
</system.webServer>

Also, I have an HTTP Module configured in the same web.config like this:

<system.webServer>
<modules>
  <add name="ImageProcessorModule" type="ImageProcessor.Web.HttpModules.ImageProcessingModule, ImageProcessor.Web" />
 </modules>
</system.webServer>

The issue that I have is like this: if I'm making a request to a strange URL like .../c<, the application executes the 500 custom error path as instructed in the web.config file. But, if I'm making a request to a stranger URL (to simulate an html tag) like .../<c, though the resulted error is 500, the custom error is not executed anymore, because accordingly to the detailed error, the HTTP Module intercept the call and "decides" to just show a YSOD...

The message that I get is:

A potentially dangerous Request.RawUrl value was detected from the client (="/App/

And is easy to see that this is caused by the webmodule because of the stacktrace:

[HttpRequestValidationException (0x80004005): A potentially dangerous Request.RawUrl value was detected from the client (="/App/d__10.MoveNext() +201 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +144 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +84 System.Web.TaskAsyncHelper.EndTask(IAsyncResult ar) +98 System.Web.AsyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +434 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +288

If I'm commenting out the Image Processor Module from the web.config, everything runs as expected.

Why in this case, the custom error path doesn't get executed?

Thank you for your time and answers.


Source: (StackOverflow)

ImageProcessorCore: Opening image takes >11seconds, what am I missing?

I'm currently examining ImageProcessorCore and I ran into an issue that makes me feel like I'm missing something: On his website the dev shows some benchmarks with a performance that is completely different to the times I measure in my sample program. I have a 2.3 MB (3853x2569) jpg image from which I only want to get the width and height (for now), so I created this little .NET core console test application:

using ImageProcessorCore;
using System;
using System.IO;

namespace ImageProcessorCoreTest
{
    public class Program
    {
        public static void Main(string[] args)
        {
            using (FileStream input = File.OpenRead(@"c:\test\a.jpg"))
            {
                DateTime start = DateTime.Now;
                Image image = new Image(input);

                int w = image.Width;
                int h = image.Height;

                double duration = (DateTime.Now.Subtract(start)).TotalMilliseconds;

                Console.WriteLine("Image size is " + w.ToString() + "x" + h.ToString() + " Pixels (" + duration.ToString() + "ms)");
                Console.ReadLine();
            }
        }
    }
}

This operation takes more than 11 seconds (factor 100 compared the benchmarks mentioned above) for just reading in the image and getting the size. What am I doing wrong?

I'm using version 1.0.0 on Windows 10 Pro 64.

(BTW: My dev machine is an i7-5820K with 16G RAM and a Samsung Pro 950 NVMe drive, so the hardware most probably can't be a bottleneck, I think.)

Update 1: Recompiling ImageProcessorCore and creating a release nuget package that I then use in my (release) sample program unfortunately only brings the duration down to a little over 10 seconds.

Update 2: I just resized the test image (externally) to 2000x1334 pixels. This significantly brought down the time to 849 milliseconds, which is still strange considering the given 56 ms for reading, resizing and writing out again in the dev's benchmark.

Update 3: I now use a test image that I can share with you for testing. The new image is 11416x6380 pixels (11.5 MB) and it takes >17 seconds with above code. You can download it here: http://orig01.deviantart.net/92d3/f/2010/110/7/2/pla_sf_3_by_recon071.jpg

Update 4: When I use the package from the MyGet repository, the time for the latest test image (see Update 3) goes down to 2.4 seconds.


Source: (StackOverflow)

ImageProcessor / Windows Azure Storage issue, returns 403 Forbidden

These images can be loaded in local ENV, and also in production ENV. However, for no reason at all, the staging environment cannot load these.

<package id="ImageProcessor" version="2.2.0.0" targetFramework="net45" />
  <package id="ImageProcessor.Web" version="4.2.1.0" targetFramework="net45" />
  <package id="ImageProcessor.Web.Config" version="2.2.0.0" targetFramework="net45" />
  <package id="ImageProcessor.Web.Plugins.AzureBlobCache" version="1.0.0.0" targetFramework="net45" />
  <package id="ImageProcessor.Web.PostProcessor" version="1.0.2.0" targetFramework="net45" />
  <package id="UmbracoAzureBlobStorageProvider" version="1.0.10.5" targetFramework="net45" />
  <package id="WindowsAzure.Storage" version="4.3.0" targetFramework="net45" />

I'm using ImageProcessor and domains are whitelisted as required:

<whitelist>
        <add url="http://conceptjp.blob.core.windows.net/"/>
        <add url="https://az739977.vo.msecnd.net/"/>
</whitelist>

https://staging.conceptjp.com/remote.axd?https://az739977.vo.msecnd.net/media/6883/logo-sparitual.png?quality=70 (do not works)

https://conceptjp.com/remote.axd?https://az739977.vo.msecnd.net/media/6883/logo-sparitual.png?quality=70 (works)

https://cjp.local/remote.axd?https://az739977.vo.msecnd.net/media/6883/logo-sparitual.png?quality=70 (works, local environment)

2016-10-04 13:31:11.2393 Logging.TheLogger The remote server returned an error: (403) Forbidden. The remote server returned an error: (403) Forbidden.    at Microsoft.WindowsAzure.Storage.Core.Executor.Executor.EndExecuteAsync[T](IAsyncResult result)
   at Microsoft.WindowsAzure.Storage.Core.Util.AsyncExtensions.<>c__DisplayClass1`1.<CreateCallback>b__0(IAsyncResult ar)
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at ImageProcessor.Web.Plugins.AzureBlobCache.AzureBlobCache.<IsNewOrUpdatedAsync>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at ImageProcessor.Web.HttpModules.ImageProcessingModule.<ProcessImageAsync>d__10.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.TaskAsyncHelper.EndTask(IAsyncResult ar)
   at System.Web.HttpApplication.AsyncEventExecutionStep.OnAsyncEventCompletion(IAsyncResult ar)

Source: (StackOverflow)

ImageProcessor with EPiServer not working

I am trying to configure an EPiServer 9 site with ImageProcessor but can't get it to work.

I have installed the following nuget packages:

ImageProcessor
ImageProcessor.Web
ImageProcessor.Web.Config

With the default configuration nothing happens. With the following custom configuration in config/imageprocessor/security.config ...

<security>
  <services>
    <service name="CloudImageService" type="ImageProcessor.Web.Services.CloudImageService, ImageProcessor.Web">
      <settings>
        <setting key="MaxBytes" value="8194304" />
        <setting key="Timeout" value="30000" />
        <setting key="Host" value="http://site.local/globalassets/"/>
      </settings>
    </service>
    <service prefix="remote.axd" name="RemoteImageService" type="ImageProcessor.Web.Services.RemoteImageService, ImageProcessor.Web">
      <settings>
        <setting key="MaxBytes" value="4194304" />
        <setting key="Timeout" value="3000" />
        <setting key="Protocol" value="http" />
      </settings>
      <whitelist>
      </whitelist>
    </service>
  </services>
</security>

... it seems like ImageProcessor is trying to resize my image but I get below error ...

[ImageFormatException: Input stream is not a supported format.]
   ImageProcessor.ImageFactory.Load(Stream stream) +523
   ImageProcessor.Web.HttpModules.<ProcessImageAsync>d__34.MoveNext() +3308
   System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +31
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62
   System.Web.TaskAsyncHelper.EndTask(IAsyncResult ar) +64
   System.Web.AsyncEventExecutionStep.OnAsyncEventCompletion(IAsyncResult ar) +162

... when trying to resize an image to 200px width like this:

http://site.local/globalassets/sample_image.jpg?width=200

Anyone have any suggestions on how I can get this to work? The image is showing as normal without the width parameter:

http://site.local/globalassets/sample_image.jpg


Source: (StackOverflow)

ImageProcessorCore: Attempt to resample image results in zero-length response

I am trying to resample a JPG image from 300dpi to 150dpi and am getting back a zero-length file.

Controller's ActionResult:

public ActionResult ViewImage(string file, int dpi = 300, bool log = true)
{
    FileExtensions fileExtensions = new FileExtensions();
    ImageExtensions imageExtensions = new ImageExtensions();

    FileModel fileModel = fileExtensions.GetFileModel(file);
    string contentType = fileModel.FileType;
    byte[] fileData = fileModel.FileData;
    string fileName = Path.GetFileNameWithoutExtension(fileModel.FileName) + "_" + dpi + "DPI" + Path.GetExtension(fileModel.FileName);
    FileStreamResult resampledImage = imageExtensions.ResampleImage(fileData, contentType, dpi);
    resampledImage.FileDownloadName = fileName;
    return resampledImage;
}

ResampleImage method:

public FileStreamResult ResampleImage(byte[] fileData, string contentType, int targetDPI)
{
    MemoryStream outputStream = new MemoryStream();
    using (Stream sourceStream = new MemoryStream(fileData))
    { 
        Image image = new Image(sourceStream);
        image.HorizontalResolution = targetDPI;
        image.VerticalResolution = targetDPI;
        JpegEncoder jpegEncoder = new JpegEncoder();
        jpegEncoder.Quality = 100;
        image.Save(outputStream, jpegEncoder);
    }           
    FileStreamResult file = new FileStreamResult(outputStream, contentType);
    return file;
}

Source: (StackOverflow)

Adjusting the spread of a vignette effect

I'm using the following code to produce a vignette effect on an image. As you can see below it works quite well. I'd like to be able to adjust the inner spread of the vignette (i.e make the middle brighter and shorten the gradient) however the maths have got the better of me. Could anyone please give me some pointers with an explanation?

    protected override void Apply(ImageBase target, 
        ImageBase source, 
        Rectangle targetRectangle, 
        Rectangle sourceRectangle, 
        int startY, int endY)
    {
        int startX = sourceRectangle.X;
        int endX = sourceRectangle.Right;
        Color color = this.Color;
        Vector2 centre = Rectangle.Center(targetRectangle);
        float rX = this.RadiusX > 0 ? this.RadiusX : targetRectangle.Width / 2f;
        float rY = this.RadiusY > 0 ? this.RadiusY : targetRectangle.Height / 2f;
        float maxDistance = (float)Math.Sqrt(rX * rX + rY * rY);

        Parallel.For(
            startY,
            endY,
            y =>
                {
                    for (int x = startX; x < endX; x++)
                    {
                        float distance = Vector2.Distance(centre, new Vector2(x, y));
                        Color sourceColor = target[x, y];
                        target[x, y] = Color.Lerp(sourceColor, 
                            color, .9f * distance / maxDistance);
                    }
                });
    }

Original Image Original image

Vignette Effect enter image description here


Source: (StackOverflow)

Optimal settings for serving images with ImageProcessor AzureBlobCache

I've been trying to understand the issues https://github.com/JimBobSquarePants/ImageProcessor/issues/161 and https://github.com/JimBobSquarePants/ImageProcessor/issues/178 discusses here.

I have an environment where i have my regular site on http://example.com and i have a separate site for imageprocessor served from http://d.example.com.

Then i have the Azure blob cache setup like this.

    <setting key="CachedStorageAccount" value="DefaultEndpointsProtocol=https;AccountName=***********;AccountKey=************" />
    <setting key="CachedBlobContainer" value="imgcache" />
    <setting key="UseCachedContainerInUrl" value="false" />
    <setting key="CachedCDNRoot" value="https://imgcdn.azureedge.net/" />
    <setting key="SourceStorageAccount" value="DefaultEndpointsProtocol=https;AccountName=**********;AccountKey=***************" />
    <setting key="SourceBlobContainer" value="dist" />
    <setting key="StreamCachedImage" value="false" />

It seems to work fine but i'm not sure about what is my optimal setting for the "StreamCachedImage" option.

I did some tests locally and with StreamCachedImage set to false it do a redirect to the CDN and i get a 302 and then a 200 from the CDN, and chrome says it cached so just a few bytes is transferred.

First: enter image description here

Second: enter image description here

When i switch to StreamCachedImage true i do not get a redirect and only get a 200 but it seems like it always returns the full image to the client.

enter image description here

I should also add that on top of this we also run Cloudflare against both example.com and d.example.com

But well, i basically would like to get some advice on how to set this up and to understand it fully.


Source: (StackOverflow)

Any way to restrict the full resolution image from being served up with Imageprocessor in Umbraco?

I'm working on a photography website in which full resolution photos can be uploaded but full-res should not be able to be displayed/accessed (download of the full res will take place through a token.)

I've tried the "restrictTo" setting but resolutions need to not be reliant on specified dimensions.

Is there a way to have myphoto.jpg by default without a querystring display at for example 700x700 yet still have the full resolution file available through a token download? Pretty much, an image without a querystring is still processed by Imageprocessor but with a default resize rule.


Source: (StackOverflow)