parent
bcefca10f7
commit
63cce5c70a
1 changed files with 62 additions and 0 deletions
@ -0,0 +1,62 @@ |
|||||||
|
Consider three cases just to suggest the spectrum |
||||||
|
of possiblities: |
||||||
|
|
||||||
|
a) linear upsample: each output pixel is a weighted sum |
||||||
|
of 4 input pixels |
||||||
|
|
||||||
|
b) cubic upsample: each output pixel is a weighted sum |
||||||
|
of 16 input pixels |
||||||
|
|
||||||
|
c) downsample by N with box filter: each output pixel |
||||||
|
is a weighted sum of NxN input pixels, N can be very large |
||||||
|
|
||||||
|
Now, suppose you want to handle 8-bit input, 16-bit |
||||||
|
input, and float input, and you want to do sRGB correction |
||||||
|
or not. |
||||||
|
|
||||||
|
Suppose you create a temporary buffer of float pixels, say |
||||||
|
one scanline tall. Actually two temp buffers, one for the |
||||||
|
input and one for the output. You decode a scanline of the |
||||||
|
input into the temp buffer which is always linear floats. This |
||||||
|
isolates the handling of 8/16/float and sRGB to one place |
||||||
|
(and still allows you to make optimized 8-bit-sRGB-to-float |
||||||
|
lookup tables). This also allows you to put wrap logic here, |
||||||
|
explicitly wrapping, reflecting, or replicating-from-edge |
||||||
|
pixels that would come from off-edge. |
||||||
|
|
||||||
|
You then do whatever the appropriate weighted sums are |
||||||
|
into the output buffer, and you move on to the next |
||||||
|
scanline of the input. |
||||||
|
|
||||||
|
The algorithm just described works directly for case (c). |
||||||
|
Suppose you're downsampling by 2.5; then output scanline 0 |
||||||
|
sums from input scanlines 0, 1, and 2; output scanline 1 |
||||||
|
sums from 2,3,4; output 2 from 5,6,7; output 3 from 7,8,9. |
||||||
|
Note how 2 & 7 get reused, but we don't have to recompute |
||||||
|
them because we can do things in a single linear pass |
||||||
|
through the input and output at the same time. |
||||||
|
|
||||||
|
Now, consider case (a). When upsampling, the same two input |
||||||
|
scanlines will get sampled-from for multiple output scanlines. |
||||||
|
So, to avoid recomputing the input scanlines, we need either |
||||||
|
multiple input or multiple output temp buffer lines. Since |
||||||
|
the number of output lines a given pair of input scanlines |
||||||
|
might touch scales with the upsample amount, it makes more |
||||||
|
sense to use two input scanline buffers. For cubic, you'll |
||||||
|
need four scanline buffers, and in general the number of |
||||||
|
buffers will be limited by the max filter width, which is |
||||||
|
presumably hardcoded. |
||||||
|
|
||||||
|
You want to avoid memory allocations (since you're passing |
||||||
|
in the target buffer already), so instead of using a scanline-width |
||||||
|
temp buffer, use some fixed-width temp buffer that's W pixels, |
||||||
|
and scale the image in vertical stripes that are that wide. |
||||||
|
Suppose you make the temp buffers 256 wide; then an upsample |
||||||
|
by 8 computes 256-pixel-width strips (from ~32-pixel-wide input |
||||||
|
strips), but a downsample by 8 computes ~32-pixel-width |
||||||
|
strips (from a 256-pixel width strip). Note this limits |
||||||
|
the max down/upsampling to be ballpark 256x along the |
||||||
|
horizontal axis. |
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue