View Full Version : overlapped dct, proof of concept frequency lowpass and interpolator function
*.mp4 guy
7th February 2007, 01:59
I made a dct based frequency limiter/expander. The function has variable precision, using 4, 8, 32, or 64 overlapped dct's specified by the "useXdct=true/false" parameters, the highest specified accuracy will be used, if no accuracy is specified 8X accuracy will be used, if all are set to false the lowest accuracy will be used. frequency weighting is by default a sinc function, different frequency weighting can be specified with the dct2-8 parameters, dct2 being the lowest frequncies, dct4 and dct5 being the middle, and dct8 being the highest.
Also included is a simple 4x enlargement function with variable sharpness, and a non-functioning downsizing function.
frequency limiter usage:
dctlimit(dc=1, dct2=1, dct3=1, dct4=1.2, dct5=-0.2, dct6=0, dct7=0, dct8=0, use8dct=true)
dctlimit does not process chroma
upsizer usage:
dctus(sharpness=2)
upsizer2 usage:
wdresize(sharpness=1.95, warp=4, u64dct=false)
The second upsizer function is just a wrapper for the first with some usefull additions, its separated so the other function can be used as a regular interpolater.
Required plugins are dctfilter and average
The upsizer performs about aswell as lanczos, but with less aliasing.
see later post for the function, it almost exceeds the char limit
708145
8th February 2007, 13:05
Do I get it right: Is this like a DCTfilter on steroids?
If so then it's very nice. I was looking for that for a long time.
bis besser,
T0B1A5
*.mp4 guy
8th February 2007, 15:08
Yep thats exactly what it is, high precision modes are S L O W.
foxyshadis
8th February 2007, 15:11
Needs to come with a warning, "Requires 4 gigs of memory", though. :p Creating a simplified plugin out of it is probably necessary to work with HD resolutions.
Possible idea - what about creating a massively overlapped 8x8 DCT this way, and then doing a 16x16 IDCT on the coefficients, in order to perform the upsizing, instead of all of these machinations with pointresize? It probably wouldn't be too hard to create a filter to do that, along with an offset parameter to get overlapped versions. (Without actually performing the averaging in the filter.)
*.mp4 guy
9th February 2007, 04:18
Possible idea - what about creating a massively overlapped 8x8 DCT this way, and then doing a 16x16 IDCT on the coefficients, in order to perform the upsizing, instead of all of these machinations with pointresize?
All of the pointresize calls in the dctlimit function are just used to shift the image without interpolating data, but you were probably refering to the pointresize calls used in the interpolation function?
Needs to come with a warning, "Requires 4 gigs of memory", though. :p Creating a simplified plugin out of it is probably necessary to work with HD resolutions.
Possible idea - what about creating a massively overlapped 8x8 DCT this way, and then doing a 16x16 IDCT on the coefficients, in order to perform the upsizing, instead of all of these machinations with pointresize? It probably wouldn't be too hard to create a filter to do that, along with an offset parameter to get overlapped versions. (Without actually performing the averaging in the filter.)
That would be the "non-half-assed" way to go about this type of resizing :sly:. It would be much more memory efficient if each independant instance of dct filter ulnoaded its memory after it processed its data aswell. Another possible speedup would be using the hct instead of the dct, but I don't know how that would impact quality.
Overlapped 8x8dct to overlapped 16*16 IDCT processing would have less overlapping during idct then during the dct, which might cause artifacts. The way things are now it is either a 2-tap function overlapped to 4 taps (all the benefits of a 4tap function, but no ringing) or a 4 tap function averlapped to 8 taps, using a 16X16 idct would turn it into an 8tap function overlapped to 16taps, which could introduce an unpleasant amount of ringing, but would have amaizing high frequency accuracy.
I can't program myself or I would have started on a plugin already, this method definately looks like it will need some real code to work properly.
[edit] function code has been updated, quality of upsizing improved.
*.mp4 guy
9th February 2007, 04:23
see later posts for new versions
Fizick
9th February 2007, 06:00
I do not know any fast (MMX) DCT 16x16 code.
But I develop dct3dfilter (not finished).
*.mp4 guy
9th February 2007, 08:44
More info please.
Does dct3dfilter do an 8x8x8 3d dct across the horizontal vertical and temporal axis?
Is it a non standard size like 8x8x4?
Hows the speed?
How accurate are the dct and idct algorithms you are using?
How does it deal with improperly temporally lowpassed content?
Fizick
9th February 2007, 17:29
1. Now I partially implement mode bt=0, bt=1, bt=3, for size 8x8,
overlap=0, 2, 4.
2.Speed is about twice fft3d.
3.Not very accurate dct,
4.I do not know.
It is under development. Please wait.
IMO Soulhunter and tritical have similar filters :)
foxyshadis
9th February 2007, 19:25
It would be much more memory efficient if each independant instance of dct filter ulnoaded its memory after it processed its data aswell.
That makes an enormous difference. Enjoy (https://dl.dropboxusercontent.com/u/54412753/doom9/DctFilter_015.zip).
I also added a chroma=-1 parameter so that it won't bother doing all that, since it's grey-only currently. 0 also works, but I'm reserving that for "copy" eventually (current behavior is "trash it"). Also enabled the dormant SSE2 fdct; it hasn't crashed on me so far, though the idct was buggy.
btw, you could put the mergechroma immediately before the return, instead of multiple times after each average; not much of a speedup but something. And I think you mixed up the rep logic.
Prettied up version:
# DCTlimit, by *.mp4 guy
#
function dctlimit(clip c, float "dct2", float "dct3", float "dct4", float "dct5", float "dct6", float "dct7", float "dct8", \
float "dc", bool "use8dct", bool "use32dct", bool "use64dct", bool "use4dct"){
dc = default(dc, 1)
dct2 = default(dct2, 1)
dct3 = default(dct3, 1)
dct4 = default(dct4, 1)
dct5 = default(dct5, 0)
dct6 = default(dct6, 0)
dct7 = default(dct7, 0)
dct8 = default(dct8, 0)
use4dct = default(use4dct, false)
use8dct = default(use8dct, true)
use32dct = default(use32dct, false)
use64dct = default(use64dct, false)
w = c.width
h = c.height
sourcey = c
source = sourcey
cropc = sourcey
#crop0 = sourcey.dctfilter(dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8,chroma=-1)
##################################################################-dct16-1
crop1 = source.dfilter(-1, 0, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop2 = source.dfilter(-1, -1, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop3 = source.dfilter(-1, -2, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop4 = source.dfilter(-1, -3, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop5 = source.dfilter(-1, -4, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop6 = source.dfilter(-1, -5, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop7 = source.dfilter(-1, -6, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop8 = source.dfilter(-1, -7, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop9 = source.dfilter(-2, -0, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop10 = source.dfilter(-2, -1, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop11 = source.dfilter(-2, -2, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop12 = source.dfilter(-2, -3, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop13 = source.dfilter(-2, -4, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop14 = source.dfilter(-2, -5, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop15 = source.dfilter(-2, -6, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop16 = source.dfilter(-2, -7, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
##################################################################-dct32-2
crop17 = source.dfilter(-3, 0, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop18 = source.dfilter(-3, -1, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop19 = source.dfilter(-3, -2, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop20 = source.dfilter(-3, -3, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop21 = source.dfilter(-3, -4, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop22 = source.dfilter(-3, -5, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop23 = source.dfilter(-3, -6, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop24 = source.dfilter(-3, -7, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop25 = source.dfilter(-4, -0, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop26 = source.dfilter(-4, -1, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop27 = source.dfilter(-4, -2, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop28 = source.dfilter(-4, -3, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop29 = source.dfilter(-4, -4, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop30 = source.dfilter(-4, -5, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop31 = source.dfilter(-4, -6, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop32 = source.dfilter(-4, -7, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
##################################################################-dct48-3
crop33 = source.dfilter(-5, 0, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop34 = source.dfilter(-5, -1, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop35 = source.dfilter(-5, -2, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop36 = source.dfilter(-5, -3, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop37 = source.dfilter(-5, -4, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop38 = source.dfilter(-5, -5, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop39 = source.dfilter(-5, -6, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop40 = source.dfilter(-5, -7, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop41 = source.dfilter(-4, -0, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop42 = source.dfilter(-6, -1, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop43 = source.dfilter(-6, -2, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop44 = source.dfilter(-6, -3, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop45 = source.dfilter(-6, -4, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop46 = source.dfilter(-6, -5, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop47 = source.dfilter(-6, -6, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop48 = source.dfilter(-6, -7, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
##################################################################-dct64-4
crop49 = source.dfilter(-7, 0, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop50 = source.dfilter(-7, -1, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop51 = source.dfilter(-7, -2, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop52 = source.dfilter(-7, -3, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop53 = source.dfilter(-7, -4, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop54 = source.dfilter(-7, -5, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop55 = source.dfilter(-7, -6, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop56 = source.dfilter(-7, -7, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop57 = source.dfilter(-0, 0, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop58 = source.dfilter(-0, -1, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop59 = source.dfilter(-0, -2, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop60 = source.dfilter(-0, -3, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop61 = source.dfilter(-0, -4, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop62 = source.dfilter(-0, -5, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop63 = source.dfilter(-0, -6, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
crop64 = source.dfilter(-0, -7, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
###################################
alignc = cropc
###################################
##################################################################-align16-1
align1 = crop1 .pointResize(W, H, 1, 0, W, H)
align2 = crop2 .pointResize(W, H, 1, 1, W, H)
align3 = crop3 .pointResize(W, H, 1, 2, W, H)
align4 = crop4 .pointResize(W, H, 1, 3, W, H)
align5 = crop5 .pointResize(W, H, 1, 4, W, H)
align6 = crop6 .pointResize(W, H, 1, 5, W, H)
align7 = crop7 .pointResize(W, H, 1, 6, W, H)
align8 = crop8 .pointResize(W, H, 1, 7, W, H)
align9 = crop9 .pointResize(W, H, 2, 0, W, H)
align10 = crop10.pointResize(W, H, 2, 1, W, H)
align11 = crop11.pointResize(W, H, 2, 2, W, H)
align12 = crop12.pointResize(W, H, 2, 3, W, H)
align13 = crop13.pointResize(W, H, 2, 4, W, H)
align14 = crop14.pointResize(W, H, 2, 5, W, H)
align15 = crop15.pointResize(W, H, 2, 6, W, H)
align16 = crop16.pointResize(W, H, 2, 7, W, H)
##################################################################-align32-2
align17 = crop17.pointResize(W, H, 3, 0, W, H)
align18 = crop18.pointResize(W, H, 3, 1, W, H)
align19 = crop19.pointResize(W, H, 3, 2, W, H)
align20 = crop20.pointResize(W, H, 3, 3, W, H)
align21 = crop21.pointResize(W, H, 3, 4, W, H)
align22 = crop22.pointResize(W, H, 3, 5, W, H)
align23 = crop23.pointResize(W, H, 3, 6, W, H)
align24 = crop24.pointResize(W, H, 3, 7, W, H)
align25 = crop25.pointResize(W, H, 4, 0, W, H)
align26 = crop26.pointResize(W, H, 4, 1, W, H)
align27 = crop27.pointResize(W, H, 4, 2, W, H)
align28 = crop28.pointResize(W, H, 4, 3, W, H)
align29 = crop29.pointResize(W, H, 4, 4, W, H)
align30 = crop30.pointResize(W, H, 4, 5, W, H)
align31 = crop31.pointResize(W, H, 4, 6, W, H)
align32 = crop32.pointResize(W, H, 4, 7, W, H)
##################################################################-align48-3
align33 = crop33.pointResize(W, H, 5, 0, W, H)
align34 = crop34.pointResize(W, H, 5, 1, W, H)
align35 = crop35.pointResize(W, H, 5, 2, W, H)
align36 = crop36.pointResize(W, H, 5, 3, W, H)
align37 = crop37.pointResize(W, H, 5, 4, W, H)
align38 = crop38.pointResize(W, H, 5, 5, W, H)
align39 = crop39.pointResize(W, H, 5, 6, W, H)
align40 = crop40.pointResize(W, H, 5, 7, W, H)
align41 = crop41.pointResize(W, H, 6, 0, W, H)
align42 = crop42.pointResize(W, H, 6, 1, W, H)
align43 = crop43.pointResize(W, H, 6, 2, W, H)
align44 = crop44.pointResize(W, H, 6, 3, W, H)
align45 = crop45.pointResize(W, H, 6, 4, W, H)
align46 = crop46.pointResize(W, H, 6, 5, W, H)
align47 = crop47.pointResize(W, H, 6, 6, W, H)
align48 = crop48.pointResize(W, H, 6, 7, W, H)
##################################################################-align64-4
align49 = crop49.pointResize(W, H, 7, 0, W, H)
align50 = crop50.pointResize(W, H, 7, 1, W, H)
align51 = crop51.pointResize(W, H, 7, 2, W, H)
align52 = crop52.pointResize(W, H, 7, 3, W, H)
align53 = crop53.pointResize(W, H, 7, 4, W, H)
align54 = crop54.pointResize(W, H, 7, 5, W, H)
align55 = crop55.pointResize(W, H, 7, 6, W, H)
align56 = crop56.pointResize(W, H, 7, 7, W, H)
align57 = crop57#.pointResize(W, H, 0, 0, W, H)
align58 = crop58.pointResize(W, H, 0, 1, W, H)
align59 = crop59.pointResize(W, H, 0, 2, W, H)
align60 = crop60.pointResize(W, H, 0, 3, W, H)
align61 = crop61.pointResize(W, H, 0, 4, W, H)
align62 = crop62.pointResize(W, H, 0, 5, W, H)
align63 = crop63.pointResize(W, H, 0, 6, W, H)
align64 = crop64.pointResize(W, H, 0, 7, W, H)
dct4_1 = average(align56, 0.25, align38, 0.25, align20, 0.25, align2, 0.25)
dct8_1 = average(align57, 0.125, align56, 0.125, align38, 0.125, align47, 0.125, align20, 0.125, align29, 0.125, align2, 0.125, align11, 0.125)
dct16_1 = average(align1, 0.0625, align2, 0.0625, align3, 0.0625, align4, 0.0625, align5, 0.0625, align6, 0.0625, align7, 0.0625, align8, 0.0625, \
align9, 0.0625, align10, 0.0625, align11, 0.0625, align12, 0.0625, align13, 0.0625, align14, 0.0625, align15, 0.0625, align16, 0.0625)
dct32_2 = average(align17, 0.0625, align18, 0.0625, align19, 0.0625, align20, 0.0625, align21, 0.0625, align22, 0.0625, align23, 0.0625, align24, 0.0625, \
align25, 0.0625, align26, 0.0625, align27, 0.0625, align28, 0.0625, align29, 0.0625, align30, 0.0625, align31, 0.0625, align32, 0.0625)
dct48_3 = average(align33, 0.0625, align34, 0.0625, align35, 0.0625, align36, 0.0625, align37, 0.0625, align38, 0.0625, align39, 0.0625, align40, 0.0625, \
align41, 0.0625, align42, 0.0625, align43, 0.0625, align44, 0.0625, align45, 0.0625, align46, 0.0625, align47, 0.0625, align48, 0.0625)
dct64_4 = average(align49, 0.0625, align50, 0.0625, align51, 0.0625, align52, 0.0625, align53, 0.0625, align54, 0.0625, align55, 0.0625, align56, 0.0625, \
align57, 0.0625, align58, 0.0625, align59, 0.0625, align60, 0.0625, align61, 0.0625, align62, 0.0625, align63, 0.0625, align64, 0.0625)
align57
use4dct ? dct4_1 : last
use8dct ? dct8_1 : last
use32dct ? average(dct16_1, 0.5, dct32_2, 0.5) : last
use64dct ? average(dct16_1, 0.25, dct48_3, 0.25, dct32_2, 0.25, dct64_4, 0.25) : last
mergechroma(alignc, 1)
return(last)
}
function m(int r, float x) {return(x<16?16:int(round(x/float(r))*r))}
Function DCTus(clip clp, float "sharpness", bool "u64dct"){
OX = m(16,Clp.Width)
OY = m(16,Clp.Height)
dx = ox - clp.width
dy = oy - clp.height
sharpness = default(sharpness, 2)
u64dct = default(u64dct, false)
luma = clp.pointresize(Clp.Width*4,Clp.Height*4).addborders(dx*4, dy*4, 0, 0).dctlimit(dct2=sharpness, dct3=0, dct4=0, dct5=0, \
use64dct=u64dct, use8dct=true).crop(dx*4, dy*4, 0, 0)
luma.mergechroma(lanczosresize(clp,Clp.Width*4 ,Clp.Height*4), 1)
return(last)
}
Function DCTds(clip clp,int destx, int desty, float "sharpness"){
sharpness = default(sharpness,1)
OX = m(16,Clp.Width)
OY = m(16,Clp.Height)
dx = ox - clp.width
dy = oy - clp.height
(clp.width < destx*2) ? dx*2 : dx
(clp.width < destx*2) ? dy*2 : dy
clp
(width < destx*2) ? dctus(sharpness) : last
(width < destx*2) ? dctds(destx=destx, desty=desty, sharpness=sharpness) : \
bilinearresize(destx,desty).addborders(dx, dy, 0, 0).dctlimit(dct3=0.75+(sharpness/4),dct4=sharpness, dct5=0).crop(dx, dy, 0, 0).pointresize(destx,desty)
return last
}
function wdresize(clip clp, float "sharpness", bool "u64dct", int "warp", int "thresh", int "rep"){
sharpness = default(sharpness, 2)
u64dct = default(u64dct, false)
warp = default(warp, 4)
thresh = default(thresh, 50)
rep = default(rep, 1)
clp.dctus(sharpness=sharpness, u64dct=u64dct).DeHalo_alpha(ss=1, lowsens=30, highsens=30, rx=2, ry=2)
w = last.width
h = last.height
pointresize(w/2, h/2)
(rep>= 2) ? last.dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=sharpness, dct5=0) : last
(rep>= 2) ? last.DeHalo_alpha(ss=1, lowsens=15, highsens=15, rx=2, ry=2) : last
(rep>= 3) ? last.dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=0.5, dct5=sharpness).dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=sharpness, dct5=0) : last
(rep>= 3) ? last.DeHalo_alpha(ss=1, lowsens=20, highsens=20, rx=2, ry=2) : last
awarpsharp(depth=warp, cm=0, blurlevel=1)
awarpsharp(depth=warp, cm=0, blurlevel=1)
awarpsharp(depth=warp, cm=0, blurlevel=1)
awarpsharp(depth=warp, cm=0, blurlevel=1)
return(last)
}
function dfilter(clip c, int offx, int offy, float dc, float dct2, float dct3, float dct4, float dct5, float dct6, float dct7, float dct8) {
c.PointResize(c.width,c.height,offx,offy,c.width,c.height).dctfilter(dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8,chroma=-1)
}
*.mp4 guy
9th February 2007, 21:08
Thanks for the help (!) dctfilter doesn't crash avisynth on frames larger then 352*192 now :D.
The script cleanup is quite nice aswell. One question though, how do you set which dct dctfilter uses?
Minor update to resizing function, defaults improved, it is now possible to set the initial taps, non mod 16 imput resolutions now work, rep code had a minor cleanup and halo removal strength is now a variable:
function wdresize(clip clp, float "sharpness", bool "u64dct", int "warp", int "thresh", int "rep", int "antihalo", int "taps", int "dehalo"){
sharpness = default(sharpness, 2)
u64dct = default(u64dct, true)
warp = default(warp, 4)
thresh = default(thresh, 50)
rep = default(rep, 1)
antihalo = default(antihalo, 150)
taps = default(taps, 4)
dehalo = default(dehalo, rep)
cw = clp.width
ch = clp.height
(taps <=3) ? clp.dctus(sharpness=sharpness, u64dct=u64dct).DeHalo_alpha(ss=1, lowsens=antihalo, highsens=antihalo, rx=2, ry=2) : last
(taps >=3) ? clp.pointresize(cw*2, ch*2).dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=sharpness, dct5=0) : last
(dehalo >=1) ? last.DeHalo_alpha(ss=1, lowsens=round((antihalo/2)*3), highsens=round((antihalo/2)*3), rx=2, ry=2) : last
w = last.width
h = last.height
(taps <=3) ? pointresize(w/2, h/2) : last
OX = m(16,Clp.Width)
OY = m(16,Clp.Height)
dx = ox - clp.width
dy = oy - clp.height
addborders(dx, dy, 0, 0)
(rep>=2) ? last.dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=0.5, dct5=sharpness).dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=sharpness, dct5=0) : last
(dehalo >=2) ? last.DeHalo_alpha(ss=1, lowsens=antihalo, highsens=antihalo, rx=2, ry=2) : last
(rep>=3) ? last.dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=0.5, dct5=sharpness).dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=sharpness, dct5=0) : last
(dehalo >=3) ? last.DeHalo_alpha(ss=1, lowsens=round((antihalo/2)*3), highsens=round((antihalo/2)*3), rx=2, ry=2) : last
(rep>=4) ? last.dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=0.5, dct5=sharpness).dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=sharpness, dct5=0) : last
(dehalo >=4) ? last.DeHalo_alpha(ss=1, lowsens=round((antihalo/2)*3), highsens=round((antihalo/2)*3), rx=2, ry=2) : last
(rep>=5) ? last.dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=0.5, dct5=sharpness).dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=sharpness, dct5=0) : last
(dehalo >=5) ? last.DeHalo_alpha(ss=1, lowsens=round((antihalo/2)*3), highsens=round((antihalo/2)*3), rx=2, ry=2) : last
(rep>=6) ? last.dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=0.5, dct5=sharpness).dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=sharpness, dct5=0) : last
(dehalo >=6) ? last.DeHalo_alpha(ss=1, lowsens=round((antihalo/2)*3), highsens=round((antihalo/2)*3), rx=2, ry=2) : last
(rep>=7) ? last.dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=0.5, dct5=sharpness).dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=sharpness, dct5=0) : last
(dehalo >=7) ? last.DeHalo_alpha(ss=1, lowsens=round((antihalo/2)*3), highsens=round((antihalo/2)*3), rx=2, ry=2) : last
(rep>=8) ? last.dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=0.5, dct5=sharpness).dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=sharpness, dct5=0) : last
(dehalo >=8) ? last.DeHalo_alpha(ss=1, lowsens=round((antihalo/2)*3), highsens=round((antihalo/2)*3), rx=2, ry=2) : last
crop(dx, dy, 0, 0)
awarpsharp(depth=warp, cm=0, blurlevel=1)
awarpsharp(depth=warp, cm=0, blurlevel=1)
awarpsharp(depth=warp, cm=0, blurlevel=1)
awarpsharp(depth=warp, cm=0, blurlevel=1)
mergechroma(lanczosresize(clp,clp.Width*2 ,clp.Height*2), 1)
return(last)}
on the todo list -
-intelligent masking to tone down halos and ringing (this is going to be really hard, but worth it if I figure something out)
-chroma processing
-investigate the effects of dct-idct precision on visible artifacts after multiple frequency seperation repetitions
-tone down the flattening caused by dehaloing. (see 1)
-look into 16*16 idct speed versus 8*8 idct speed.
[edit] upsizing function updated again, now suppots up to 8 reps (which very surprisingly actually looks good on some images, though I'm beginning to suspect that the reason lenna image is used so frequently in digital image processing is that it is perfectly lowpassed... it makes every image processing algorithm look like a miracle worker)
foxyshadis
9th February 2007, 22:35
Thanks for the help (!) dctfilter doesn't crash avisynth on frames larger then 352*192 now :D.
Cool!
The script cleanup is quite nice aswell. One question though, how do you set which dct dctfilter uses?
It sets it by the processor it detects right now. There isn't any floating-point dct, only mmx/sse2 dct and mmx/isse idct, so they all have the same (lousy) precision. If I can find a way to get a float in there (like mplayer's) I'll make it selectable.
Si
9th February 2007, 22:39
Someones got to ask and it may as well be me :)
I made a dct based frequency limiter/expander. The function has variable precision, using 4, 8, 32, or 64 overlapped dct's specified by the "useXdct=true/false" parameters, the highest specified accuracy will be used, if no accuracy is specified 8X accuracy will be used, if all are set.....
And what's one of them then ?
regards
Simon
*.mp4 guy
9th February 2007, 23:09
Someones got to ask and it may as well be me :)
And what's one of them then ?
regards
Simon
It's a highly precise bluring/sharpening/line detection algorithm that can be used to remove artifacts when upsizing and downsizing by correctly removing frequencies that cause aliasing ringing and haloing, without removing frequencies that are actually detail.
It sets it by the processor it detects right now. There isn't any floating-point dct, only mmx/sse2 dct and mmx/isse idct, so they all have the same (lousy) precision. If I can find a way to get a float in there (like mplayer's) I'll make it selectable.
That might explain something, is the mmx sse2 dct more precise then the mmx isse one? I thought the results I got were uncharacteristically low on ringing after I updated dctfilter and a difference in precision would explain it.
I've been thinking about sampling theory, and the theoretically impossible sinc function, and I realised that not only would you need an infinitely precise sinc function to get perfect frequency elimination, you would also need an infinitely precise colorspace and sampling depth, IE you would need an infinte resolution image with an infinite colorspace just to store the results of the perfect sinc function. So given that it is both impossible to create a perfect sinc function and to adequately sample its results, shouldn't it then be possible to use a sufficiently precise sinc function so that the error it produces is lower then the accuracy loss of your destination resolution and colorspace, thereby giving you results that are as good as the perfect sinc functions results would be had they been subsampled to the resolution and colorspace you are using. Of couse in all likely hood such a sufficiently precise sinc function would be so slow that it would be completely useless. Given that a perfect dct transform is impossible, I think its possible that a sufficiently precise dct could impersonate the perfect sinc function with an adequately imprecise output resolution and colorspace.
Didée
10th February 2007, 01:03
The concept sounds interesting. But somehow I have some issues ... perhaps I'm missing something?
1. In whichever way I juggle around with true/false for all the useXdct, the result is always exactly the same?
2. Looking at what a dctlimit() call does to a sample frame:
original: http://img123.imageshack.us/img123/2972/dctlimitoriglm5.th.png (http://img123.imageshack.us/my.php?image=dctlimitoriglm5.png)
dctlimit: http://img293.imageshack.us/img293/706/dctlimit64dctcb5.th.png (http://img293.imageshack.us/my.php?image=dctlimit64dctcb5.png)
Well, there's definetly an effect, but I see no use for what it's giving to me ...
Is the function really doing what it's supposed to do? Am I missing something obvious?
*.mp4 guy
10th February 2007, 10:56
The concept sounds interesting. But somehow I have some issues ... perhaps I'm missing something?
1. In whichever way I juggle around with true/false for all the useXdct, the result is always exactly the same?
2. Looking at what a dctlimit() call does to a sample frame:
original: http://img123.imageshack.us/img123/2972/dctlimitoriglm5.th.png (http://img123.imageshack.us/my.php?image=dctlimitoriglm5.png)
dctlimit: http://img293.imageshack.us/img293/706/dctlimit64dctcb5.th.png (http://img293.imageshack.us/my.php?image=dctlimit64dctcb5.png)
Well, there's definetly an effect, but I see no use for what it's giving to me ...
Is the function really doing what it's supposed to do? Am I missing something obvious?
Are you
1-trying to resize the image
2-trying to lowpass
3-trying to enhance detail
If you are trying to do 1 you need to use the wdresize() function instead of dctlimit, wdresize is SLOW.
If you are trying to do #2, you just have, but you need to remove more frequencoes above the nyquist limit, try
dctlimit(use64dct=true, dct2=1, dct3=2, dct4=2, dct5=0)
dctlimit(use64dct=true, dct2=1, dct3=2, dct4=0.5, dct5=2)
dctlimit(use64dct=true, dct2=1, dct3=2, dct4=2, dct5=0)
dctlimit(use64dct=true, dct2=1, dct3=2, dct4=0.5, dct5=2)
repetition refines the frequency seperation, giving more accurate results, but also causes errors by the dct-idct algorithms to be amplified.
if you are trying to do # 3 you would call dctlimit like this
dctlimit(use64dct=true, dct2=1, dct3=1, dct4=1, dct5=1, dct6=1.5, dct7=2, dct8=2)
I havent extensively tested using dctlimit for accurate frequency sharpening.
the "usxdct" parameter adds accuracy, when all you are doing is running a single operation of dctlimit the difference between use8dct and use64dct will be impossible to see without enhancement of the image.
CAFxX
10th February 2007, 11:55
A little ago I did something similar, i.e. performing a fft on the whole image and then padding/cropping to reach the desired size.
I used the FFTW library and I got this (video is the second bravia commercial, 1280x720 downsized to 320x180 via spline36 and then upconverted with my filter (and spline36 as a reference); luma only atm; spline first, fft second):
frame 370:
http://img214.imageshack.us/img214/4466/370sye1.th.png (http://img214.imageshack.us/img214/4466/370sye1.png)
http://img214.imageshack.us/img214/4893/370fqt2.th.png (http://img214.imageshack.us/img214/4893/370fqt2.png)
frame 817:
http://img214.imageshack.us/img214/3529/817sza6.th.png (http://img214.imageshack.us/img214/3529/817sza6.png)
http://img214.imageshack.us/img214/5793/817fmi4.th.png (http://img214.imageshack.us/img214/5793/817fmi4.png)
I suppose the ringing effect near the borders is due to the limited precision but I actually can't guarantee that my code is bugless.
atm it can't do downsizing, but in matlab downsizing using this method proved interesting.
the filter is quite slow (15-20fps on my athlon64 3200), and it takes a while to load (fftw needs some time to prepare the ffts).
obviously (granted that the above mentioned ringing effect is due to limited precision) a overlapping window approach should resolve the issue. (and prove faster: fftw works in double precision... a highly tuned costant size integer/fixed-point algorithm will surely go much faster: btw, if anyone can point me towards an integer fft i may try to use that instead)
edit: found IPPs: will try them later
*.mp4 guy
10th February 2007, 15:31
Overlapping should always increase precision for frequency transforms that are not odd, that is overlapping will always improve precision when used with a dct or an fft (they only work on even blocks of data) however the optimal way to avoid problems with any frequency transform is to only use the center pixel, as the center pixel has the least error, so for the most precise 8x8 dct-idct data you would need to perform 9 dct transforms per group of four pixels, avergaing the results and using only the center four pixels of the average after idct, using a different group of 9 transforms for each group of four pixels in the entire image, each group sharing 8 transforms with its neighbors (1 left, 1 up, 1 uperleft, etc.), this would give the most precise reconstruction (better then 64x overlapping). The same aplies to the fft, so the best ways to improve results are to 1-increase transform size, 2-use sufficient overlapping and pixel binning 3-use a precise transform and inverse transform.
After some additional research it turns out that the optimal frequency domain transform is the KLT(Karhunen-Loève transform), which is better then the dct, which is better then the fft. The klt is the most optimal linear transform, for the same reason the dct is better then the fft, that is it keeps the most important data only at the lowest frequencies, whereas with the dct and fft some important information is kept at higher frequencies then unimportant information, the fft has low frequency seperation, whereas the dct has high frequency seperation, and the klt has perfect frequency seperation. A perfectly resmapled image could be made using a sufficiently precise aproximation of a klt and a sufficiently imprecise colorspace and destination resolution, the klt would have to use variable transform sizes, the interior of the image would use a transform the size of the entire image, as the transform moved twards the borders of the image the transform size would have to be reduced to stay within the image boundaries.
Didée
10th February 2007, 18:06
@ *.mp4 guy
Thanks for all the explanations, but I already know the drill. ;)
You didn't get my point ... I was wondering if the function is working correctly.
Answer is: it does, and it does not.
And if you would have looked at the sample, you should have noted that something is definetly going wrong there ...
Solution:
Like it is posted, dctlimit() will work correctly only with Avisynth v2.57.
But when used with Avisynth v2.56, the result is a joke ... because of the resizer bug of AS 2.56.
I added the needed workaround, & put up the modified script here (http://home.arcor.de/dhanselmann/_stuff/dctlimit.avs).
It's not needed for v.257, but it doesn't hurt, either.
(No need to discuss the "why still use 2.56???" question ... it is still used, and there the original function "silently" gives a b0rked result. Quite sneaky if one don't know about that ... it seems to work, but the result is crap, and people might wonder what it is all about ...
Better to play safe, for the time being.)
*.mp4 guy
10th February 2007, 18:38
The results were bad on that sample, but I wasn't sure why, I figured it was just bad settings/ a tough source, thanks for the fix/workaround.
Also, does anyone know where I can get more information on the KLT/PCA transform? Wikipedias explanation was nice, but I would like more information about practical uses.
foxyshadis
10th February 2007, 21:26
I did put up a version of dctfilter that allows you to choose dct, if you want to compare: fdct=1/3, idct=1/2/3, 1=mmx, 2=isse, 3=sse2, 0=int but I'm still trying to get that one to work. The 16-bit int method is going to be excruciatingly slow, though.
I have no idea if the simd versions really differ, but it can't hurt to be sure. The math and assembly hurts my head.
Edit: Made another change, doesn't seem to have affected allocation strategies at all, still searching.
Ah, it does seem that the pointresize is where all the memory is getting sucked into now, I guess you'd need a custom avisynth. Actually, I guess a dll with just a custom version of that would work.
CAFxX
11th February 2007, 15:04
I rewrote the code of the filter in order to use the IPPs.
It's nowhere near being optimized (nor cpu-wise, nor memory-wise) or easily usable (only "multiplicative" upsizing ATM).
As far as the name is concerned, it will probably change in future.
sincresize(clip, int factor, int window)
clip - input clip: planar, mod 2^window
factor - scaling parameter: >= 2
window - size of first DCT: >= 2
the filter works like this:
for every (square) block of size 2^window of the source frame
- perform a forward DCT
- pad the above DCT in an empty block of size (2^window)*factor
- perform the inverse DCT on the padded block
- extract from the middle of the block a window of size (2^window)*factor/2 and copy it to the destination frame (this is done to avoid blocking)
notes:IPP DFT works on single precision floating point values, near-border regions are handled by replicating the border values.
Download (uncommented source + MSVC binary): http://cafxx.strayorange.com/SincResize.7z
(development and testing platform: Athlon64 3200+, 1GB DDR400, XP SP2, AviSynth 2.57, MSVC8, IPP5.1)
*.mp4 guy
11th February 2007, 16:03
@CAFxXI got this error (http://img236.imageshack.us/img236/135/sincresizejg1.png) when I tried to use your plugin. I think when I was testing dctlimit I might have gotten a few bad sectors from heavy disk usage, so I'll run a chkdsk and report back if that changes anything.
@foxyshadis The problem with point resize is that it doesn't unallocate memory after processing?
CAFxX
11th February 2007, 16:09
@CAFxXI got this error (http://img236.imageshack.us/img236/135/sincresizejg1.png) when I tried to use your plugin. I think when I was testing dctlimit I might have gotten a few bad sectors from heavy disk usage, so I'll run a chkdsk and report back if that changes anything.
I swear I don't know what is going on there... someone else has that problem?
BTW, i forgot to mention that now the filter also processes the chroma planes.
edit: I also forgot to mention that i haven't added yet the support for named parameters... invoke it like this: sincresize(<factor>, <window>)
in your case would be sincresize(2,2). i'll do that soon, anyway.
niiyan
11th February 2007, 17:16
@foxyshadis
I downloaded DctFilter from http://forum.doom9.org/showthread.php?p=951432#post951432, but I can't extract it.
The error message of the extractor says the archive is broken.
Could you check if DctFilter.zip is OK or upload DctFilter.zip again?
CAFxX
11th February 2007, 19:34
I packaged a second version of sincresize:
- now accepts named parameters
- parameters default are factor(2) and window(3)
- enabled multi-threading via openmp (I don't have a multicore processor, so actually I can't test if it works)
- removed a couple of useless comments from the sources
download: http://cafxx.strayorange.com/SincResize2.7z
*.mp4 guy
12th February 2007, 02:53
I ran chkdsk and I've still got the problem, even after re-downloading the plugin, are you using a non-english characterset in the plugin, that might be what is causing the problems.
Adub
12th February 2007, 04:24
@niiyan
Try downloading it again. Sometimes the servers cut things off in the middle of a download so you don't actually finish the entire file.
foxyshadis
12th February 2007, 05:17
I think it was my FTP client, actually, which likes to "resume" new uploads at random. I've been uploading new versions (some of which don't crash!) over the course of the day as I'm in and out.
It has an offset codepath right now, that's going to help a lot once it works - no more need for pointresize at all! - but right now it just crashes a lot. I also found out that the original simd dcts are 16-bit, so that makes the 16-bit I was trying to hack in there pretty pointless, meh. Still haven't found any double version, if it's important I can try again some other time.
I guess this is what I get for not understanding much assembly.
Edit: Looking at the co-efficients in the debugger, I see a very easy way to increase the precision by 4 bits, just multiply everything by 16; there's a lot of unused extra precision here, probably at least 6 bits, but definitely 4.
*.mp4 guy
12th February 2007, 06:35
On a test image it looks like only 2 more bits of precision are needed to avoid any artifacts using an 8x8dct->16x16idct method, but using the current pointresize then lowpass method it could take up to 7 more bits of precision to avoid errors caused by rounding during frequency scaling =/ I know dgindex has some very precise idcts, but I don't know of any precise dcts. Version 3 of fftw has a dft equivelent to both the dct and idct, and they support variable sizes, but I don't know how precise they are, or if they are fast enough, since performing a dct using a dft is supposed to be slower then using a specialised dct algorithm. I wish I could figure out how to cludge something together in c, but most of dctfilter and sincresize are still unreadable to me.
Also IEEE explore (and all the other ones like them) are annoying, they have 90% of the papers on the dct, the hct, even the klt. meh. From googling it looks like there has been a lot of research on this topic, I can't figure out why there aren't any other implementations.
CAFxX
12th February 2007, 08:19
I ran chkdsk and I've still got the problem, even after re-downloading the plugin, are you using a non-english characterset in the plugin, that might be what is causing the problems.
I don't think... in the source file, only pure ASCII chars are used... and all the strings are in english...
Will someone else please confirm wheter the binary is broken or not?
BTW, I had a look at the sources of DGIndex, but I (obviously) found just a 8x8 iDCT: ideally I'd need a 8x8 DCT and 16x16, 32x32 (maybe even 64x64) iDCTs (if downscaling is also needed, then the full array of DCTs and iDCTs is required).
Eventually, if someone can point out a promising book on the matter, I may try to go grab it from one of the libraries of my university.
As a footnote, I found mentions of a former sourceforge project called mmxdct: unfortunately, it looks like it is not available anymore. If you happen to stumble upon a mirror, a cached version, or anything please post the address here.
*.mp4 guy
12th February 2007, 08:38
Ehm what I meant, is what charset are you compiling it with, ASCI, Unicode? I"m guessing its a charset problem becuase of the grarbled error avisynth returned, that shouldn't happen for anything but a problem with the charset. I'll let you know if I find any good dct routines.
[edit] this (http://momonga.t.u-tokyo.ac.jp/~ooura/fft.html) might be what your looking for.
CAFxX
12th February 2007, 08:49
I did not force Unicode in the MSVC project properties, and in fact if you open the dll with a hex editor and scroll down to the strings you'll see that the chars are not 16bit wide.
Anyway I'll test the dll on another computer. Maybe it's just a missing/wrong version library kind of problem.
CAFxX
12th February 2007, 09:48
[edit] this (http://momonga.t.u-tokyo.ac.jp/~ooura/fft.html) might be what your looking for.
Those are plain C double precision floating point routines...
*.mp4 guy
12th February 2007, 10:12
Well, they are the only variable size dcts I found, and you aren't doing any overlapping so it shouldn't be that slow. Have you found any other non-mod-8 dct code?
CAFxX
12th February 2007, 10:20
uhm... yes and no
IPP can do variable size DCT as well (actually the function is the same... you pass the dimensions of the DCT as parameters), and actually my filter does overlapping...
the filter works like this:
for every (square) block of size 2^window of the source frame
- perform a forward DCT
- pad the above DCT in an empty block of size (2^window)*factor
- perform the inverse DCT on the padded block
- extract from the middle of the block a window of size (2^window)*factor/2 and copy it to the destination frame (this is done to avoid blocking)
maybe it was not that clear, or maybe this is not the kind of overlapping you expected, but it definitely works (precision issues aside)
(anyway, thank you for your interest!)
foxyshadis
12th February 2007, 10:51
I really need to keep better track of my mental notes, it would save me so much time debugging later on. So anyway, I got you a version that'll do offsets, but unfortunately several attempts to get higher precision out of it failed. I'm going to have to ask someone who knows mmx/sse to find out why, because there's so much wasted extra room. But at least it takes less memory to do its thing:
Plugin (http://foxyshadis.slightlydark.com/random/DctFilter.zip)
function dctlimit(clip c, float "dct2", float "dct3", float "dct4", float "dct5", float "dct6", float "dct7", float "dct8", float "dc", bool "use8dct", bool "use32dct", bool "use64dct", bool "use4dct"){
dc = default(dc, 1)
dct2 = default(dct2, 1)
dct3 = default(dct3, 1)
dct4 = default(dct4, 1)
dct5 = default(dct5, 0)
dct6 = default(dct6, 0)
dct7 = default(dct7, 0)
dct8 = default(dct8, 0)
use4dct = default(use4dct, false)
use8dct = default(use8dct, true)
use32dct = default(use32dct, false)
use64dct = default(use64dct, false)
w = c.width
h = c.height
sourcey = c
source = sourcey
cropc = sourcey
#crop0 = sourcey.dctfilter(dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8,chroma=-1)
##################################################################-dct16-1
align1 = source.dfilter( 1, 0, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align2 = source.dfilter( 1, 1, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align3 = source.dfilter( 1, 2, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align4 = source.dfilter( 1, 3, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align5 = source.dfilter( 1, 4, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align6 = source.dfilter( 1, 5, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align7 = source.dfilter( 1, 6, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align8 = source.dfilter( 1, 7, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align9 = source.dfilter( 2, 0, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align10 = source.dfilter( 2, 1, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align11 = source.dfilter( 2, 2, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align12 = source.dfilter( 2, 3, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align13 = source.dfilter( 2, 4, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align14 = source.dfilter( 2, 5, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align15 = source.dfilter( 2, 6, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align16 = source.dfilter( 2, 7, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
################################################################## dct32 2
align17 = source.dfilter( 3, 0, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align18 = source.dfilter( 3, 1, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align19 = source.dfilter( 3, 2, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align20 = source.dfilter( 3, 3, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align21 = source.dfilter( 3, 4, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align22 = source.dfilter( 3, 5, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align23 = source.dfilter( 3, 6, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align24 = source.dfilter( 3, 7, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align25 = source.dfilter( 4, 0, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align26 = source.dfilter( 4, 1, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align27 = source.dfilter( 4, 2, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align28 = source.dfilter( 4, 3, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align29 = source.dfilter( 4, 4, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align30 = source.dfilter( 4, 5, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align31 = source.dfilter( 4, 6, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align32 = source.dfilter( 4, 7, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
################################################################## dct48 3
align33 = source.dfilter( 5, 0, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align34 = source.dfilter( 5, 1, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align35 = source.dfilter( 5, 2, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align36 = source.dfilter( 5, 3, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align37 = source.dfilter( 5, 4, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align38 = source.dfilter( 5, 5, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align39 = source.dfilter( 5, 6, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align40 = source.dfilter( 5, 7, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align41 = source.dfilter( 4, 0, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align42 = source.dfilter( 6, 1, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align43 = source.dfilter( 6, 2, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align44 = source.dfilter( 6, 3, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align45 = source.dfilter( 6, 4, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align46 = source.dfilter( 6, 5, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align47 = source.dfilter( 6, 6, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align48 = source.dfilter( 6, 7, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
################################################################## dct64 4
align49 = source.dfilter( 7, 0, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align50 = source.dfilter( 7, 1, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align51 = source.dfilter( 7, 2, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align52 = source.dfilter( 7, 3, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align53 = source.dfilter( 7, 4, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align54 = source.dfilter( 7, 5, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align55 = source.dfilter( 7, 6, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align56 = source.dfilter( 7, 7, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align57 = source.dfilter( 0, 0, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align58 = source.dfilter( 0, 1, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align59 = source.dfilter( 0, 2, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align60 = source.dfilter( 0, 3, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align61 = source.dfilter( 0, 4, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align62 = source.dfilter( 0, 5, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align63 = source.dfilter( 0, 6, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align64 = source.dfilter( 0, 7, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
dct4_1 = average(align56, 0.25, align38, 0.25, align20, 0.25, align2, 0.25)
dct8_1 = average(align57, 0.125, align56, 0.125, align38, 0.125, align47, 0.125, align20, 0.125, align29, 0.125, align2, 0.125, align11, 0.125)
dct16_1 = average(align1, 0.0625, align2, 0.0625, align3, 0.0625, align4, 0.0625, align5, 0.0625, align6, 0.0625, align7, 0.0625, align8, 0.0625, align9, 0.0625, align10, 0.0625, align11, 0.0625, align12, 0.0625, align13, 0.0625, align14, 0.0625, align15, 0.0625, align16, 0.0625)
dct32_2 = average(align17, 0.0625, align18, 0.0625, align19, 0.0625, align20, 0.0625, align21, 0.0625, align22, 0.0625, align23, 0.0625, align24, 0.0625, align25, 0.0625, align26, 0.0625, align27, 0.0625, align28, 0.0625, align29, 0.0625, align30, 0.0625, align31, 0.0625, align32, 0.0625)
dct48_3 = average(align33, 0.0625, align34, 0.0625, align35, 0.0625, align36, 0.0625, align37, 0.0625, align38, 0.0625, align39, 0.0625, align40, 0.0625, align41, 0.0625, align42, 0.0625, align43, 0.0625, align44, 0.0625, align45, 0.0625, align46, 0.0625, align47, 0.0625, align48, 0.0625)
dct64_4 = average(align49, 0.0625, align50, 0.0625, align51, 0.0625, align52, 0.0625, align53, 0.0625, align54, 0.0625, align55, 0.0625, align56, 0.0625, align57, 0.0625, align58, 0.0625, align59, 0.0625, align60, 0.0625, align61, 0.0625, align62, 0.0625, align63, 0.0625, align64, 0.0625)
align57
use4dct ? dct4_1 : last
use8dct ? dct8_1 : last
use32dct ? average(dct16_1, 0.5, dct32_2, 0.5) : last
use64dct ? average(dct16_1, 0.25, dct48_3, 0.25, dct32_2, 0.25, dct64_4, 0.25) : last
mergechroma(source, 1)
return(last)
}
function dfilter(clip c, int offx, int offy, float dc, float dct2, float dct3, float dct4, float dct5, float dct6, float dct7, float dct8) {
#c.PointResize(c.width,c.height,offx,offy,c.width,c.height).dctfilter(dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8,chroma=0,offx=offx,offy=offy).PointResize(c.width,c.height,-offx,-offy,c.width,c.height)
c.dctfilter(dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8,chroma=0,offx=offx,offy=offy)
}
(The dctlimit stuff is something I should have done the first time I cleaned it up, didn't affect anything.)
Nonetheless, I think I'm going to look at CAFxX's filter for now, unless I have any sudden insights on how to make this more efficient.
I think the current version leans too heavily on warpsharp, it really has a rather dull and hollow look at 4x, very much like EKG - toning it down looks rather nicer imho. Still, I'm having a hard time choosing between this and Photozoom2, my other current favorite. PZ2 has much more deviation in line thickness that is very pleasant, but way too much contrast, where WD retains an enormous amount of detail, but somehow or another, those thick lines could really use some help. I only wish I knew how to get that effect.
niiyan
12th February 2007, 14:56
@Merlin7777
I have already downloaded a few times via IE6 and Firefox, after removing those browsers' cache.
But I couldn't extact it.
Anyway, thank you for your reply.
@foxyshadis
I downloaded a new version (DctFilter.zip 12-Feb-2007 04:46 224k).
It was successfully decompressed.
Thanks.
*.mp4 guy
12th February 2007, 23:02
I've been finding what settings work the best, and the new defaults should perform a lot better then the old ones, tell me if it helps with the lines. The new defaults are also a lot faster. I was having trouble with chroma upsizing, so wdresize is now just luma, while wdresizeC is luma+chroma. The thickened lines where a result of a few things (mostly dehaloing), so it should be less of an issue now, since dehaloing isn't as important as I thought it was.
Function DCTus(clip clp, float "sharpness", bool "u64dct"){
OX = m(16,Clp.Width)
OY = m(16,Clp.Height)
dx = ox - clp.width
dy = oy - clp.height
sharpness = default(sharpness, 2)
u64dct = default(u64dct, false)
clp.pointresize(Clp.Width*4,Clp.Height*4)
(dx+dy >=1) ? addborders(dx*4, dy*4, 0, 0) : last
clpcc = last
last.dctlimit(dct2=sharpness, dct3=0, dct4=0, dct5=0, use64dct=u64dct, use8dct=true)
(dx>=1) ? last.crop(dx*4, 0, 0, 0) : last
(dy>=1) ? last.crop(0, dy*4, 0, 0) : last
luma = last
#lanczosresize(clpcc,Clpcc.Width*4 ,Clpcc.Height*4)
#(dx>=1) ? last.crop(dx*4, 0, 0, 0) : last
#(dy>=1) ? last.crop(0, dy*4, 0, 0) : last
#chroma = last
#mergechroma(luma, chroma, 1)
return(luma)}
Function DCTds(clip clp,int destx, int desty){
clp
(desty*destx >= clp.width*clp.height/4) ? clp.spline36resize(m(32,(desty*2)), m(32,(desty*2))) : clp
(desty*destx >= clp.width*clp.height/4) ? dctlimit(use64dct=true, dct2=1, dct3=1, dct4=1, dct5=0, dct6=0, dct7=0, dct8=0) : clp
(desty*destx >= clp.width*clp.height/4) ? pointresize(destx, desty).mergechroma(spline36resize(clp, destx, desty), 1) : last
(desty*destx >= clp.width*clp.height/3.75) ? clp.spline36resize(m(32,(desty*1.875)), m(32,(desty*1.875))) : last
(desty*destx >= clp.width*clp.height/3.75) ? dctlimit(use64dct=true, dct2=1, dct3=1, dct4=1, dct5=1, dct6=0, dct7=0, dct8=0) : last
(desty*destx >= clp.width*clp.height/3.75) ? spline36resize(destx, desty).mergechroma(spline36resize(clp, destx, desty), 1) : last
(desty*destx >= clp.width*clp.height/3.5) ? clp.spline36resize(m(32,(desty*1.75)), m(32,(desty*1.75))) : last
(desty*destx >= clp.width*clp.height/3.5) ? dctlimit(use64dct=true, dct2=1, dct3=1, dct4=1, dct5=1, dct6=1, dct7=0, dct8=0) : last
(desty*destx >= clp.width*clp.height/3.5) ? spline36resize(destx, desty).mergechroma(spline36resize(clp, destx, desty), 1) : last
(desty*destx >= clp.width*clp.height/3.25) ? clp.spline36resize(m(32,(desty*1.625)), m(32,(desty*1.625))) : last
(desty*destx >= clp.width*clp.height/3.25) ? dctlimit(use64dct=true, dct2=1, dct3=1, dct4=1, dct5=1, dct6=1, dct7=1, dct8=0) : last
(desty*destx >= clp.width*clp.height/3.25) ? spline36resize(destx, desty).mergechroma(spline36resize(clp, destx, desty), 1) : last
return last}
function wdresize(clip clp, float "sharpness", bool "u64dct", int "warp", int "thresh", int "rep", int "antihalo", int "taps", int "dehalo", float "sharpness2"){
sharpness = default(sharpness, 1.625)
u64dct = default(u64dct, true)
warp = default(warp, 0)
thresh = default(thresh, 50)
rep = default(rep, 1)
antihalo = default(antihalo, 0)
taps = default(taps, 4)
dehalo = default(dehalo, 0)
sharpness2 = default(sharpness2, 1.126)
cw = clp.width
ch = clp.height
clp
(taps <=3) ? clp.dctus(sharpness=sharpness, u64dct=u64dct) : last
(taps >=3) ? clp.pointresize(cw*2, ch*2) : last
w = last.width
h = last.height
(taps <=3) ? pointresize(w/2, h/2) : last
OX = m(16,last.Width)
OY = m(16,last.Height)
dx = ox - last.width
dy = oy - last.height
(dx+dy >=1) ? addborders(dx*4, dy*4, 0, 0) : last
clpcc = last
clpcc
(taps <=3) ? last.DeHalo_alpha(ss=1, lowsens=antihalo, highsens=antihalo, rx=2, ry=2) : last
(taps >=3) ? last.dctlimit(use64dct=u64dct, dct2=1+(sharpness/11.6), dct3=1+(sharpness/8.1), dct4=sharpness, dct5=sharpness2/8.1, dct6=sharpness2/11.6, dct7=sharpness2/16.1, dct8=sharpness2/23.1) : last
(dehalo >=1) ? last.DeHalo_alpha(ss=1, lowsens=round((antihalo/2)*3), highsens=round((antihalo/2)*3), rx=2, ry=2) : last
#(dx+dy >=1) ? addborders(dx*4, dy*4, 0, 0) : last
(rep>=2) ? last.dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=0.5, dct5=sharpness, dct6=sharpness2/8).dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=sharpness, dct5=sharpness2/8) : last
(dehalo >=2) ? last.DeHalo_alpha(ss=1, lowsens=antihalo, highsens=antihalo, rx=2, ry=2) : last
(rep>=3) ? last.dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=0.5, dct5=sharpness, dct6=sharpness2/8).dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=sharpness, dct5=sharpness2/8) : last
(dehalo >=3) ? last.DeHalo_alpha(ss=1, lowsens=round((antihalo/2)*3), highsens=round((antihalo/2)*3), rx=2, ry=2) : last
(rep>=4) ? last.dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=0.5, dct5=sharpness, dct6=sharpness2/8).dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=sharpness, dct5=sharpness2/8) : last
(dehalo >=4) ? last.DeHalo_alpha(ss=1, lowsens=round((antihalo/2)*3), highsens=round((antihalo/2)*3), rx=2, ry=2) : last
(rep>=5) ? last.dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=0.5, dct5=sharpness, dct6=sharpness2/8).dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=sharpness, dct5=sharpness2/8) : last
(dehalo >=5) ? last.DeHalo_alpha(ss=1, lowsens=round((antihalo/2)*3), highsens=round((antihalo/2)*3), rx=2, ry=2) : last
(rep>=6) ? last.dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=0.5, dct5=sharpness, dct6=sharpness2/8).dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=sharpness, dct5=sharpness2/8) : last
(dehalo >=6) ? last.DeHalo_alpha(ss=1, lowsens=round((antihalo/2)*3), highsens=round((antihalo/2)*3), rx=2, ry=2) : last
(rep>=7) ? last.dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=0.5, dct5=sharpness, dct6=sharpness2/8).dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=sharpness, dct5=sharpness2/8) : last
(dehalo >=7) ? last.DeHalo_alpha(ss=1, lowsens=round((antihalo/2)*3), highsens=round((antihalo/2)*3), rx=2, ry=2) : last
(rep>=8) ? last.dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=0.5, dct5=sharpness, dct6=sharpness2/8).dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=sharpness, dct5=sharpness2/8) : last
(dehalo >=8) ? last.DeHalo_alpha(ss=1, lowsens=round((antihalo/2)*3), highsens=round((antihalo/2)*3), rx=2, ry=2) : last
awarpsharp(depth=warp, cm=0, blurlevel=1)
awarpsharp(depth=warp, cm=0, blurlevel=1)
awarpsharp(depth=warp, cm=0, blurlevel=1)
awarpsharp(depth=warp, cm=0, blurlevel=1)
(dx>=1) ? last.crop(dx*4, 0, 0, 0) : last
(dy>=1) ? last.crop(0, dy*4, 0, 0) : last
return(last)}
function wdresizec(clip clp, float "sharpness", bool "u64dct", int "warp", int "thresh", int "rep", int "antihalo", int "taps", int "dehalo", float "sharpness2"){
sharpness = default(sharpness, 1.6)
u64dct = default(u64dct, true)
warp = default(warp, 0)
thresh = default(thresh, 50)
rep = default(rep, 1)
antihalo = default(antihalo, 0)
taps = default(taps, 4)
dehalo = default(dehalo, 0)
sharpness2 = default(sharpness2, 1.126)
clp
wdresize(sharpness=sharpness,u64dct=u64dct,warp=warp,thresh=thresh,rep=rep,antihalo=antihalo,taps=taps,dehalo=dehalo, sharpness2=sharpness2)
mergechroma(lanczos4resize(clp, clp.width*2, clp.height*2), 1)
return(last)}
dctds works now, but only gives good results when downsizing a mod 32 source by a factor of 2.
@CAFxX I would like to test your filter, tell me if you find out what went wrong on my system, I'll keep looking for the problem.
[edit] It looks like avsp screwed up the formatting, I'll see what I can do about it. [edit] fixed
CAFxX
13th February 2007, 00:28
@*.mp4 guy
Tomorrow I hope I'll have some time to try it on my second computer. I'll let you know if it worked ASAP.
BTW, those are a few other ss:
Original (http://img185.imageshack.us/img185/8560/immagineas0.png)
Spline36 (http://img185.imageshack.us/img185/4250/1462sxn5.png)
SincResize (http://img185.imageshack.us/img185/86/1462flo7.png)
and, just to remember everyone that every rose has its thorn:
Artifacts (http://img185.imageshack.us/img185/7884/immaginecq4.png)
(4x enlargment, top: SincResize(4,6), bottom:Spline36())
*.mp4 guy
13th February 2007, 02:34
@*.mp4 guy
Tomorrow I hope I'll have some time to try it on my second computer. I'll let you know if it worked ASAP.
BTW, those are a few other ss:
Original (http://img185.imageshack.us/img185/8560/immagineas0.png)
Spline36 (http://img185.imageshack.us/img185/4250/1462sxn5.png)
SincResize (http://img185.imageshack.us/img185/86/1462flo7.png)
and, just to remember everyone that every rose has its thorn:
Artifacts (http://img185.imageshack.us/img185/7884/immaginecq4.png)
(4x enlargment, top: SincResize(4,6), bottom:Spline36())
Is that using an fft or dft based aproach, or is that using dcts or dsts. You should get better results if you stick to powers of 2, ie 2-4-8-16, which usually compute faster and give better quality (because they are easier to comput accuracy is better). The dct and dst should greatly outperform there fourier counterparts at the same tap value.
CAFxX
13th February 2007, 15:04
ATM I use IPP's ippiDCTFwd_32f_C1R and ippiDCTInv_32f_C1R on blocks of size 2^Window (DCT) and (2^Window)*Factor (iDCT). They work on single precision floating point data: nevertheless all that haloing looks rather strange to me.
CAFxX
13th February 2007, 16:48
OK, I did a few tests and discovered that *probably* the "Unable to load plugin" problem was caused by MSVC that was inserting manifests during linking...
Now it should work. At least, it does on my second PC.
Notable changes:
- switched to IPP's internal memory allocator (ippiMalloc) for better (?) alignment
- removed multi-threading (I did one of the most stupid errors of my programming experience...)
- removed silly "GenuineIntel" check from IPP library (SIMD code should now be executed on AMD chips as well)
- CRT library now is statically linked
- removed manifest
known bugs:
- I'm investigating a bug occurring with big frame sizes
download:
http://cafxx.strayorange.com/SincResize3.7z
enjoy!
*.mp4 guy
13th February 2007, 22:45
It works now, its also nice and fast :). good job. The ringing has me a bit baffled though, since dctlimit doesn't have it when used with equivelent settings. Just one request.
Could you remove the restriction that factor must be greater then 1. It should be ok to use a factor of 1, and being able to do that will make it easier for me to find out where the ringing is coming from. Thanks.
CAFxX
13th February 2007, 23:12
There you go.
notable changes:
-factor can now be 1
download:
http://cafxx.strayorange.com/SincResize4.7z
*.mp4 guy
13th February 2007, 23:43
Thanks, off to test.
*.mp4 guy
14th February 2007, 09:51
Factor 1 doesn't look like it changes the image at all, I'm not even sure if there is any processing being done. However it looks like the intel ipp routines have lower accuracy on "high energy" frequencies then the dctfilter+dctlimit routines, it might be worth seeing if higher amounts of overlapping improve the situation, but the ideal solution would be higher accuracy routines with less roundoff error. Thanks to foxyshadis dctfilter optimisations dctlimit is fast enough (imo) to be worth using considering that it can avoid ringing almost completely.
Thanks for sharing your plugin CAFxX, It looks like there isn't an easy way to do frequency based interpolation, you either sacrifice speed, effectiveness, or artifacts, spline sacrifices effectiveness, lanczos artifacts and effectiveness both, dctlimit sacrifices speed with slight artifacts, and sincresize sacrifices artifacts and a small amount of speed =/.
At this point it looks like the next step to better performance frequency based interpolation is to write a custom aproximation of the KLT transform specifically for resizing, which is far beyond both my coding and math knowledge, I'll have to come back to the problem later when I have a better understanding of high level trigonometry and algebra (I beleive trig is heavily used in the dct) and linear matrix transformation equations.
Anyone is of course welcome to take any of my code and ideas from this thread and improve upon them themselves, though I can't speak for the other contributors.
CAFxX
14th February 2007, 11:11
Factor 1 doesn't look like it changes the image at all, I'm not even sure if there is any processing being done.
I noticed that as well, but the the DCT/iDCT is done nonetheless.
However it looks like the intel ipp routines have lower accuracy on "high energy" frequencies then the dctfilter+dctlimit routines, it might be worth seeing if higher amounts of overlapping improve the situation, but the ideal solution would be higher accuracy routines with less roundoff error.
In the meanwhile I've been looking for other (hopefully more precise) implementations. If I manage to find something suitable, I'll drop IPP's DCT/iDCT.
At this point it looks like the next step to better performance frequency based interpolation is to write a custom aproximation of the KLT transform specifically for resizing
One of the alternatives I'm investigating on is a template metaprogramming-based recursive transform. A solution that coupled with an arbitrary precision integer/rational/fixed-point/floating-point math library should resolve the issue.
CAFxX
15th February 2007, 14:13
Just a quick note to let you know that I'm making a few changes to my website, so the previous links may break in a near future.
I nevertheless created a page dedicated to SincResize that will contain the updated links:
http://cafxx.strayorange.com/SincResize
(still, new version announcments will be made here though)
psme
19th February 2007, 09:16
sorry, how to use dctus or wdresizec for upscale? How to specific output picture x/y size? Or the filter is not meant for such usage? Thanks in advance.
regards,
Li On
vBulletin® v3.8.11, Copyright ©2000-2025, vBulletin Solutions Inc.