local t={}function t.None(I,t,n,a,E)for a=1,#t,1 do n[E][a]=t[a]end end function t.Sub(I,t,n,a,E)for a=1,a,1 do n[E][a]=t[a]end for I=a+1,#t,1 do local O=t[I]local C=n[E][I-a]n[E][I]=bit32.band(O+C,255)end end function t.Up(I,t,n,a,E)if E>1 then local a=n[E-1]for I=1,#t,1 do local O=t[I]local C=a[I]n[E][I]=bit32.band(O+C,255)end else I:None(t,n,a,E)end end function t.Average(I,t,n,a,E)if E>1 then for a=1,a,1 do local I=t[a]local O=n[E-1][a]O=bit32.rshift(O,1)n[E][a]=bit32.band(I+O,255)end for I=a+1,#t,1 do local O=t[I]local C=n[E-1][I]local A=n[E][I-a]local K=bit32.rshift(A+C,1)n[E][I]=bit32.band(O+K,255)end else for a=1,a,1 do n[E][a]=t[a]end for a=a+1,#t,1 do local I=t[a]local O=n[E-1][a]O=bit32.rshift(O,1)n[E][a]=bit32.band(I+O,255)end end end function t.Paeth(I,t,n,a,E)if E>1 then local I for a=1,a,1 do local I=t[a]local O=n[E-1][a]n[E][a]=bit32.band(I+O,255)end for O=a+1,#t,1 do local C=n[E][O-a]local A=n[E-1][O]local K=n[E-1][O-a]local v=t[O]local p=(C+A)-K local m=math.abs(p-C)local h=math.abs(p-A)local T=math.abs(p-K)if m<=h and m<=T then I=C elseif h<=T then I=A else I=K end n[E][O]=bit32.band(v+I,255)end else I:Sub(t,n,a,E)end end return t
local Unfilter = {}

function Unfilter:None(scanline, pixels, bpp, row)
	for i = 1, #scanline do
		pixels[row][i] = scanline[i]
	end
end

function Unfilter:Sub(scanline, pixels, bpp, row)
	for i = 1, bpp do
		pixels[row][i] = scanline[i]
	end
	
	for i = bpp + 1, #scanline do
		local x = scanline[i]
		local a = pixels[row][i - bpp]
		pixels[row][i] = bit32.band(x + a, 0xFF)
	end
end

function Unfilter:Up(scanline, pixels, bpp, row)
	if row > 1 then
		local upperRow = pixels[row - 1]
		
		for i = 1, #scanline do
			local x = scanline[i]
			local b = upperRow[i]
			pixels[row][i] = bit32.band(x + b, 0xFF)
		end
	else
		self:None(scanline, pixels, bpp, row)
	end
end

function Unfilter:Average(scanline, pixels, bpp, row)
	if row > 1 then
		for i = 1, bpp do
			local x = scanline[i]
			local b = pixels[row - 1][i]
			
			b = bit32.rshift(b, 1)
			pixels[row][i] = bit32.band(x + b, 0xFF)
		end
		
		for i = bpp + 1, #scanline do
			local x = scanline[i]
			local b = pixels[row - 1][i]
			
			local a = pixels[row][i - bpp]
			local ab = bit32.rshift(a + b, 1)
			
			pixels[row][i] = bit32.band(x + ab, 0xFF)
		end
	else
		for i = 1, bpp do
			pixels[row][i] = scanline[i]
		end
	
		for i = bpp + 1, #scanline do
			local x = scanline[i]
			local b = pixels[row - 1][i]
			
			b = bit32.rshift(b, 1)
			pixels[row][i] = bit32.band(x + b, 0xFF)
		end
	end
end

function Unfilter:Paeth(scanline, pixels, bpp, row)
	if row > 1 then
		local pr
		
		for i = 1, bpp do
			local x = scanline[i]
			local b = pixels[row - 1][i]
			pixels[row][i] = bit32.band(x + b, 0xFF)
		end
		
		for i = bpp + 1, #scanline do
			local a = pixels[row][i - bpp]
			local b = pixels[row - 1][i]
			local c = pixels[row - 1][i - bpp]
			
			local x = scanline[i]
			local p = a + b - c
			
			local pa = math.abs(p - a)
			local pb = math.abs(p - b)
			local pc = math.abs(p - c)
			
			if pa <= pb and pa <= pc then
				pr = a
			elseif pb <= pc then
				pr = b
			else
				pr = c
			end
			
			pixels[row][i] = bit32.band(x + pr, 0xFF)
		end
	else
		self:Sub(scanline, pixels, bpp, row)
	end
end

return Unfilter