Add some documentation.
This commit is contained in:
parent
384ed98f12
commit
f0e037fb36
3 changed files with 147 additions and 0 deletions
59
docs/bilinear_interpolation.md
Normal file
59
docs/bilinear_interpolation.md
Normal file
|
@ -0,0 +1,59 @@
|
|||
## Coding Bilinear Interpolation ##
|
||||
|
||||
Source: [The Supercomputing Blog](http://supercomputingblog.com/graphics/coding-bilinear-interpolation/)
|
||||
|
||||
When performing image transformation and manipulation techniques, it is often
|
||||
necessary to employ some sort of interpolation or filtering in order to obtain
|
||||
a good image quality. For example, if you scale an image, you can determine
|
||||
the final color of each pixel by either some basic nearest neighbor method, or
|
||||
a more advanced interpolation method. However, an interpolation method will
|
||||
invariably offer better final image quality. In this tutorial, we’ll be
|
||||
writing a function to rotate an image, using bilinear interpolation. This
|
||||
tutorial also demonstrates how to perform a high quality image rotate
|
||||
transformation, however, that is not the focus of this tutorial, but rather
|
||||
the example transform being performed.
|
||||
|
||||
|
||||
### Why interpolation is used after image transforms ###
|
||||
|
||||
Image transforms like scaling, rotating, twisting or otherwise warping,
|
||||
effectively move pixels around in the image. The result is that the pixels in
|
||||
the final image do not directly map to a single original pixel in the original
|
||||
image. Suppose after rotation, a pixel should have the same color as pixel
|
||||
(3.4, 5.6) in the original image. The only problem is that there is no such
|
||||
thing as fractional pixels! Instead of simply choosing the color of the
|
||||
nearest available pixel, (3,6), we can get better results by intelligently
|
||||
averaging the colors of the four closest pixels. In this case, the values of
|
||||
pixels (3,5) (3,6) (4,5) and (4,6) would be intelligently averaged together to
|
||||
estimate the color of an imaginary pixel at (3.4, 5.6). This is called
|
||||
interpolation, and it is used after image transforms to provide a smooth,
|
||||
accurate and visually appealing images.
|
||||
|
||||
|
||||
### Understanding bilinear interpolation ###
|
||||
|
||||
We can best understand bilinear interpolation by looking at the graphic here.
|
||||
The green P dot represents the point where we want to estimate the color. The
|
||||
four red Q dots represent the nearest pixels from the original image. The
|
||||
color of these four Q pixels is known. In this example, P lies closest to Q12,
|
||||
so it is only appropriate that the color of Q12 contributes more to the final
|
||||
color of P than the 3 other Q pixels.
|
||||
|
||||
|
||||
### Calculating bilinear interpolation ###
|
||||
|
||||
There are several ways equivalent ways to calculate the value of P. An easy
|
||||
way to calculate the value of P would be to first calculate the value of the
|
||||
two blue dots, R2, and R1. R2 is effectively a weighted average of Q12 and
|
||||
Q22, while R1 is a weighted average of Q11 and Q21.
|
||||
|
||||
``` R1 = ((x2 – x)/(x2 – x1))*Q11 + ((x – x1)/(x2 – x1))*Q21 R2 = ((x2 –
|
||||
x)/(x2 – x1))*Q12 + ((x – x1)/(x2 – x1))*Q22 ```
|
||||
|
||||
After the two R values are calculated, the value of P can finally be
|
||||
calculated by a weighted average of R1 and R2.
|
||||
|
||||
``` P = ((y2 – y)/(y2 – y1))*R1 + ((y – y1)/(y2 – y1))*R2 ```
|
||||
|
||||
The calculation will have to be repeated for the red, green, blue, and
|
||||
optionally the alpha component of.
|
16
docs/padding.txt
Normal file
16
docs/padding.txt
Normal file
|
@ -0,0 +1,16 @@
|
|||
https://stackoverflow.com/questions/11642210/computing-padding-required-for-n-byte-alignment
|
||||
|
||||
There is a faster way to compute the padding, if the alignment is a power of two
|
||||
(2,4,8,...). The following runs because binary & is similar to % for powers of
|
||||
two: %(2^x) and &(2^x-1) do the same for positive numbers. Attention: & will
|
||||
delete the sign bit and therefore always returns the positive modulo result.
|
||||
|
||||
So (4 - (string_length & 3)) & 3 will do the same as
|
||||
(4 - (string_length % 4)) % 4. Using the positive modulo property this can be
|
||||
simplified to (-string_length) & 3!
|
||||
|
||||
|
||||
If you wanna add that result to the size you can even do more optimizations:
|
||||
|
||||
padded_length = (string_length + 3) & ~3 Semantically this 'rounds up' the
|
||||
number to the padding size of 4.
|
72
docs/srgb_linear.md
Normal file
72
docs/srgb_linear.md
Normal file
|
@ -0,0 +1,72 @@
|
|||
## A close look at the sRGB formula ##
|
||||
|
||||
[Source](https://blog.demofox.org/2018/03/10/dont-convert-srgb-u8-to-linear-u8/)
|
||||
[Specific page](http://entropymine.com/imageworsener/srgbformula/)
|
||||
|
||||
The formulas for converting sRGB colors to linear, and the reverse, are usually
|
||||
given as follows:
|
||||
|
||||
```
|
||||
sRGB to Linear
|
||||
|
||||
Condition Value
|
||||
0 ≤ S ≤ 0.04045 L = S/12.92
|
||||
0.04045 < S ≤ 1 L = ((S+0.055)/1.055)^2.4
|
||||
```
|
||||
|
||||
```
|
||||
Linear to sRGB
|
||||
|
||||
Condition Value
|
||||
0 ≤ L ≤ 0.0031308 S = L×12.92
|
||||
0.0031308 < L ≤ 1 S = 1.055×L^(1/2.4) − 0.055
|
||||
```
|
||||
|
||||
The definition uses two different functions – a straight line and an
|
||||
exponential curve – glued together at a certain “cutoff point”. The implication
|
||||
is that these functions (the ones in the sRGB to Linear definition) intersect
|
||||
at the point:
|
||||
|
||||
**(0.0404500000000000, 0.00313080000000000)**
|
||||
|
||||
If we take a close look at the function, though, we can see this intersection
|
||||
point is not exact, so the formula has a slight discontinuity:
|
||||
|
||||
* sRGB: 0.0404500000000000
|
||||
* sRGB: 0.0404500000000001
|
||||
* Linear: 0.00313080495356037
|
||||
* Linera: 0.00313080728306769
|
||||
|
||||
If we extend the functions, we see that they actually intersect at two points:
|
||||
|
||||
1. (0.0381547987133173, 0.00295315779514840)
|
||||
2. (0.0404482362771082, 0.00313066844250063)
|
||||
|
||||
If we use either of these two points as the cutoff point, there will be no
|
||||
discontinuity at all. It’s apparent that the sRGB inventors selected the second
|
||||
of these points, and rounded its value to 4 significant digits to get 0.04045.
|
||||
They then used that rounded sRGB value to recalculate the Linear value, and got
|
||||
0.00313080. I don’t know why their Linear value has more significant digits (5
|
||||
or 6) than their sRGB value (4).
|
||||
|
||||
I guess that if you’re a perfectionist, and want no discontinuity at all, you
|
||||
can tweak the formulas like this:
|
||||
|
||||
```
|
||||
sRGB to Linear
|
||||
|
||||
Condition Value
|
||||
0 ≤ S ≤ 0.0404482362771082 L = S/12.92
|
||||
0.0404482362771082 < S ≤ 1 L = ((S+0.055)/1.055)^2.4
|
||||
```
|
||||
|
||||
```
|
||||
Linear to sRGB
|
||||
|
||||
Condition Value
|
||||
0 ≤ L ≤ 0.00313066844250063 S = L×12.92
|
||||
0.00313066844250063 < L ≤ 1 S = 1.055×L^(1/2.4) − 0.055
|
||||
```
|
||||
|
||||
It doesn’t make any practical difference. The two functions are extremely close
|
||||
together in this region, so the precise cutoff point is almost irrelevant.
|
Loading…
Add table
Reference in a new issue