lehins / hip

Haskell Image Processing Library
116 stars 17 forks source link

Lanczos resampling #38

Open kirisaki opened 4 years ago

kirisaki commented 4 years ago

Description

I thought "Bicubic" which is used in raster graphic editors like Photoshop, GIMP and so on used "Bicubic interpolation", but, I hear that they really use Lanczos filter or Mitchell-Netravali filter (This so confused me!:confused:).

I want to downsize images so need Lanczos filter and plan to implement it. Lanczos filter takes a positive integer value as the size of the kernel. I have three suggestions about implementation.

Implementation

A. Let ADT have the kernel size

Define such that:

data Lanczos = Lanczos Natural

This way is simple but needs to allocate memory by dynamic way, so it maybe causes slow.

B. Let the name of ADT have kernel size

data Lanczos3 = Lanczos3

This way is simple too, but not cool. To take into account that it can use several kernel sizes only, this selection may be good. And it require implementation each data type, so not need dynamic memory allocation.

C. Use type level number

Black magic:

data Lanczos (n :: Nat) = Lanczos

instance Interpolation (Lanczos 3) where
...

The way of implementation is same as B, but looks cooler. It requires type annotation to use:

writeImage "sample.jpg" $ resize (Lanczos :: Lanczos 3) Edge (300, 400) img

D. Implement only Lanczos-3

It's a possibly.

lehins commented 4 years ago

I think the suggested approach C. is the best one. Making it even slightly more general would be even better:

data Lanczos (n :: Nat) = Lanczos

instance (KnownNat n, 1 <= n) => Interpolation (Lanczos n) where

Later it would be possible to simplify it for users a bit with PatternSynonyms, which can be defined for common case of 2 through 4

type Lanczos2 = Lanczos 2
pattern Lanczos2 :: Lanczos2
pattern Lanczos2 = Lanczos

type Lanczos3 = Lanczos 3
pattern Lanczos3 :: Lanczos3
pattern Lanczos3 = Lanczos

type Lanczos4 = Lanczos 4
pattern Lanczos4 :: Lanczos4
pattern Lanczos4 = Lanczos
lehins commented 4 years ago

Regardless of the approach if at least one of those is implemented (eg. Lanczos3 ) then we can refactor to make it more general later

kirisaki commented 4 years ago

Great idea! PatternSynonyms is used like this, isn't it!

Does it require a collection like Array in implementation? Or divide into cases by the kernel size? The former generalize code against the kernel size but slow, the latter requires implementation each kernel sizes and throw an error when a kernel size isn't supported.

lehins commented 4 years ago

I guess it all depends on the implementation. Try getting the one you suggested first

instance Interpolation (Lanczos 3) where

and then I can recommend a proper way going forward from there.

kirisaki commented 4 years ago

OK, I challenge it.

YellowOnion commented 6 months ago

If you're thinking of adding any other algorithms, there's a selection of filters here, with some key details about their implementation. : https://avisynthplus.readthedocs.io/en/latest/avisynthdoc/corefilters/resize.html

It might also help or hinder the the understanding of what a bicubic filter really is :P