Images

Fanray resizes your uploaded images and uses Responsive Images to serve the best image to the client.

Image Resizing

Images uploaded to Fanray get resized before they are stored away. Currently only .png, .jpg, .jpeg and .gif are supported. Here is the flow.

Upload Image Use Case

Sizes

The number of copies and their sizes are application specific. For example, the blog app, based on the image dimension, can save up to 5 different copies including the original. You can find the specifics in blog app’s ImageService class.

  • Small: 600px
  • Medium: 1200px
  • Medium Large: 1800px
  • Large: 2400px
  • Original

For example, if you drag and drop a landscape image with a width over 2400px to your blog post, you will end up with all 5 resizes, whereas a 1700px image will end up with 4 resizes. The height of the image is adjusted in proportion to its width.

ImageSharp

Image resizing is a common requirement but .NET Core currently does not have System.Drawing or something equivalent, a third party lib is needed. I’ve chosen ImageSharp based its speed, library size, output file size and output file quality. I’ve created a separate repo to compare it with Magick.NET, another choice I was using prior to ImageSharp.

Strategies

Fanray resizes the images as user uploads them. Here I want to briefly mention another approach when it comes to image resizing. The approach is to resize through the image URL by attaching parameters needed to the URL, for example, https://mysite.com/images/my-pic.jpg?w=200

The resizing doesn’t happen till a request is made to the URL. There are pros and cons with each approach, it all depends on your situation.

With this approach, you only resize when you need to and you can defer a lot of the resizing to a background job to handle. But on the other hand you may need to have extra logic in place for caching and preventing DOS attacks. For instance someone could potentially play around with the image URL parameters to generate more image copies. Andrew Lock has a nice post on this topic.

Responsive Images

Fanray uses Responsive Images to serve the best image to the client based on the client’s viewport size and screen density, it saves bandwidth and boosts client response time. Responsive Images is part of responsive web design, it’s done through the img tag’s srcset and sizes attributes.

Suppose you upload pic.jpg (2200 x 1650), Fanray will first resize image and store them, then it will output the following code to serve a particular version of your image based on client’s viewport size and screen density.

<img src="https://localhost:44381/media/blog/2020/01/md/pic.jpg"
     srcset="https://localhost:44381/media/blog/2020/01/sm/pic.jpg 600w,
             https://localhost:44381/media/blog/2020/01/md/pic.jpg 1200w,
             https://localhost:44381/media/blog/2020/01/ml/pic.jpg 2x,
             https://localhost:44381/media/blog/2020/01/pic.jpg 3x"
     sizes="(max-width: 1800px) 100vw, 1800px"
     alt="pic">

The above will render an medium sized image of 1200px by default, but depending on the client’s viewport size and screen density, it actually may serve the 600px, 1200px, 1800px or original version 2200px of the image.

The sizes="(max-width: 1800px) 100vw, 1800px" attribute says if client viewport size is <= 1800px then let the viewport decide 100%, otherwise use 1800px. In other words, it’s saying when client screen density is 1x and when client’s viewport size is <= 600px, use the 600px image; if viewport size is <= 1200px, use the 1200px image; in all other cases use 1800px image. It is equivalent to sizes="(max-width: 600px) 600px, (max-width: 1200px) 1200px, 1800px".

However, regardless of client’s viewport size, when the client density is between 1x and 2x, i.e. > 1x && <=2x, the 1800px image will be served; when it is greater than 2x, the original image of 2200px is served.

To see this happen in action, I prepared a separate repo for demoing purpose.

Storage
Caching