gitee.com/h79/goutils@v1.22.10/common/images/dct.go (about)

     1  package images
     2  
     3  import (
     4  	"math"
     5  	"sync"
     6  )
     7  
     8  // DCT1D function returns result of DCT-II.
     9  // DCT type II, unscaled. Algorithm by Byeong Gi Lee, 1984.
    10  func DCT1D(input []float64) []float64 {
    11  	temp := make([]float64, len(input))
    12  	forwardTransform(input, temp, len(input))
    13  	return input
    14  }
    15  
    16  func forwardTransform(input, temp []float64, Len int) {
    17  	if Len == 1 {
    18  		return
    19  	}
    20  
    21  	halfLen := Len / 2
    22  	for i := 0; i < halfLen; i++ {
    23  		x, y := input[i], input[Len-1-i]
    24  		temp[i] = x + y
    25  		temp[i+halfLen] = (x - y) / (math.Cos((float64(i)+0.5)*math.Pi/float64(Len)) * 2)
    26  	}
    27  	forwardTransform(temp, input, halfLen)
    28  	forwardTransform(temp[halfLen:], input, halfLen)
    29  	for i := 0; i < halfLen-1; i++ {
    30  		input[i*2+0] = temp[i]
    31  		input[i*2+1] = temp[i+halfLen] + temp[i+halfLen+1]
    32  	}
    33  	input[Len-2], input[Len-1] = temp[halfLen-1], temp[Len-1]
    34  }
    35  
    36  // DCT2D function returns a  result of DCT2D by using the seperable property.
    37  func DCT2D(input [][]float64, w int, h int) [][]float64 {
    38  	output := make([][]float64, h)
    39  	for i := range output {
    40  		output[i] = make([]float64, w)
    41  	}
    42  	// 加快速度
    43  	wg := new(sync.WaitGroup)
    44  	for i := 0; i < h; i++ {
    45  		wg.Add(1)
    46  		go func(i int) {
    47  			cols := DCT1D(input[i])
    48  			output[i] = cols
    49  			wg.Done()
    50  		}(i)
    51  	}
    52  	wg.Wait()
    53  
    54  	for i := 0; i < w; i++ {
    55  		wg.Add(1)
    56  		in := make([]float64, h)
    57  		go func(i int) {
    58  			for j := 0; j < h; j++ {
    59  				in[j] = output[j][i]
    60  			}
    61  			rows := DCT1D(in)
    62  			for j := 0; j < len(rows); j++ {
    63  				output[j][i] = rows[j]
    64  			}
    65  			wg.Done()
    66  		}(i)
    67  	}
    68  	wg.Wait()
    69  	return output
    70  }