Downscale images in url2epub
Since I added support to my new Kobo eink reader to url2epub, I’ve been reading a lot of long web articles on it, and one thing start to bother me: Kobo is the only epub reader, hardware or software, that do not auto downscale bigger images.
For example, when I read a Washington Post article about a captive orca, this is quite annoying:
So I started to fix it, by implementing a downscaling feature when grayscaling the images to be packed in to epub files.
It turns out that scaling an image is not a simple thing, as there are a lot of different ways to decide “how” (Image Magick project has a page describe in details of different filters). The general consensus is that for downscaling Lanczos is usually the best, but it’s also complicated to implement.
Since here in reality I’m only dealing with grayscaled images, that every color is only represented by a single number (a 16-bit unsigned int for the grayness), I decided to do something much simpler: Just calculated a weighted average of the color of the original pixels of the new pixel is representing.
For example, when you downscale an originally 720x540 image to 480x405, you can map the new
(0, 0) pixel to a range of 0-1.5 for both x and y, so it’s the combination of the original
(0, 0) (full),
(0, 1) (half),
(1, 0) (half), and
(1, 1) (1⁄4). So just calculated the weighted average of the 4 colors from the original image to get the new color for the
(0, 0) pixel on the new image.
With that implemented, I also need to decide how the API should work for downscaling. I could pass in both desired width and height to do the downscaling, but considering that Kobo eink readers can be used in both vertical or horizontal orientation, if you just downscale for the width, it could still be too high when you switch to horizontal and now the width limitation becomes the height limitation. For that reason, and also for the reason of for the sake of simplicity, I chose to only set one number being the limitation of both width and height. In the Telegram bot, this is the new
/fit N command, and in the REST API this can be set via the new
fit=N url query.
Then the next problem is to decide what’s the number I need to set for my own Kobo Sage. The official tech spec says the screen resolution is 1440x1920, I tried both 1280 and 1024 and it seems 1280 works best:
And looks like my downscaling implementation is rendered pretty sharp on Kobo’s eink display!