DCT
forked from DFT (diff: 121)
The Discrete Cosine Transform TODO - blockwise operation - quantization
ActionScript3 source code
/**
* Copyright wrotenodoc ( http://wonderfl.net/user/wrotenodoc )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/owlp
*/
// forked from wrotenodoc's DFT
package {
import flash.display.Sprite
import flash.display.Bitmap
import flash.display.BitmapData
import flash.text.TextField
public class DCT_Test extends Sprite {
public function DCT_Test() {
// write as3 code here..
var bd:BitmapData = new BitmapData(64, 64, true, 0x0)
bd.perlinNoise(32, 32, 4, 0, false, true, 7, true)
var bmp:Bitmap = new Bitmap(bd)
bmp.y = 20
bmp.scaleX = bmp.scaleY = 3
addChild(bmp)
var dct:DCTResult = DCT(bd)
var dctBD:BitmapData = dct2bd(dct)
var dctBMP:Bitmap = new Bitmap(dctBD)
with(addChild(dctBMP)){
x = 64 * 3
y = 20
scaleX = scaleY = 3
}
var idct:BitmapData = IDCT(dct)
var idctBMP:Bitmap = new Bitmap(idct)
with(addChild(idctBMP)){
scaleX = scaleY = 3
y = bmp.y + bmp.height
}
var tf1:TextField = makeText("original", bmp.x+bmp.width/2, bmp.y-10)
var tf2:TextField = makeText("dct", dctBMP.x+dctBMP.width/2, dctBMP.y-10)
var tf3:TextField = makeText("idct", idctBMP.x+idctBMP.width/2, idctBMP.y+idctBMP.height+10)
function makeText(msg:String, tx:Number, ty:Number):TextField {
var tf:TextField = new TextField
tf.selectable = false
tf.autoSize = "center"
tf.text = msg
tf.x = tx - tf.width/2 ; tf.y = ty - tf.height/2
addChild(tf)
return tf
}
}
private function bd2ary(bd:BitmapData):Array {
var ary:Array = []
for(var y:int=0; y<bd.height; y++){
ary[y] = []
for(var x:int=0; x<bd.width; x++){
ary[y][x] = bd.getPixel(x, y) & 0xFF
}
}
return ary
}
private function dct2bd(dct:DCTResult):BitmapData {
var bd:BitmapData = new BitmapData(dct.width, dct.height, false, 0x0)
for(var y:int=0; y<dct.height; y++){
for(var x:int=0; x<dct.width; x++){
var color:uint = uint(Math.log(1 + (dct.data[y][x] - dct.minValue)/(dct.maxValue - dct.minValue)) * 255 * 255)
bd.setPixel(x, y, color<<16 | color<<8 | color)
}
}
return bd
}
private const pi2:Number = Number.PI * 2
private function DCT(image:BitmapData):DCTResult {
var N:int = image.height
var M:int = image.width
var PI_M:Number = Math.PI / M
var PI_N:Number = Math.PI / N
var result:DCTResult = new DCTResult(M, N)
var i:int, j:int
for(i=0; i<N; i++){
for(j=0; j<N; j++){
result.data[i][j] = sum(i, j)
}
}
result.minValue = Infinity
result.maxValue = -Infinity
var r:Number
for(i=0; i<N; i++){
for(j=0; j<N; j++){
r = result.data[i][j]
if(r > result.maxValue) result.maxValue = r
if(r < result.minValue) result.minValue = r
}
}
return result
function sum(i:int, j:int):Number {
var real:Number = 0
var col:uint
for(var y:int=0; y<N; y++){
for(var x:int=0; x<M; x++){
col = image.getPixel(x, y) & 0xFF
real += 4 * col * Math.cos(PI_M*(x+.5)*j) * Math.cos(PI_N*(y+.5)*i)
}
}
return real
}
}
private function IDCT(dct:DCTResult):BitmapData {
var N:int = dct.height, M:int = dct.width
var PI_M:Number = Math.PI / M
var PI_N:Number = Math.PI / N
var MN:int = M * N
var i:int, j:int
var bd:BitmapData = new BitmapData(M, N, false, 0x0)
var col:uint
for(i=0; i<N; i++){
for(j=0; j<M; j++){
col = uint(sum(i, j))
bd.setPixel(j, i, col<<16 | col<<8 | col)
}
}
return bd
function sum(i:int, j:int):Number {
var real:Number = 0
var accum:Number
var w1:Number, w2:Number
for(var y:int=0; y<N; y++){
accum = 0
for(var x:int=0; x<M; x++){
w1 = x == 0 ? .5 : 1
w2 = y == 0 ? .5 : 1
accum += w1*w2*dct.data[y][x] * Math.cos(PI_M*(j+.5)*x) * Math.cos(PI_N*(i+.5)*y)
}
real += accum / MN
}
return real
}
}
}
}
class DCTResult {
public var data:Vector.<Vector.<Number>>
public var maxValue:Number, minValue:Number
public var width:int, height:int
public function DCTResult(width:int, height:int) {
data = new Vector.<Vector.<Number>>(height, true)
for(var i:int=0; i<height; i++) data[i] = new Vector.<Number>(width, true)
this.width = width
this.height = height
}
}
