• Programming
• Internet

# Fourier Transform on Color Channels

This Image Processing Reference section displays the code for an example program that demonstrates how to calculate a Fourier transform for the color channels of an image.

### FourierChannels.php

```<?php
function Clamp(\$iGray) {
if (\$iGray < 0) {
return 0;
} elseif (\$iGray > 255) {
return 255;
} else {
return \$iGray;
}
}

// The sign indicates whether it is a forward (1) or inverse (-1) transform
\$daSines     = new SplFixedArray(\$iLength+1);
\$daCosines   = new SplFixedArray(\$iLength+1);
\$iBits = IntVal(round(Log(\$iLength)/Log(2)));
for (\$i = 0; \$i < \$iLength + 1; ++\$i) {
\$daSines[\$i]   = \$iSign*sin((3.141592654*\$i)/\$iLength);
\$daCosines[\$i] = cos((3.141592654*\$i)/\$iLength);
}
\$iU = 0;
for (\$i = 0; \$i < \$iLength; ++\$i) {
\$iIndex = 0;
for (\$j = 0; \$j < \$iBits; ++\$j) {
\$iU      = (1<<\$j);
\$iIndex  = ((\$iIndex<<1) + ((\$iU&\$i)>>\$j));
}
\$iIndex <<= 1;
\$iIndex2 = (\$i<<1);
if (\$iIndex2 < \$iIndex) {
}
}
\$iArraySize = (\$iLength << 1);
for (\$iIncr = 2; \$iIncr < \$iArraySize; \$iIncr <<=1) {
\$iStep = (\$iIncr << 1);
for (\$iU = 0; \$iU < \$iIncr; \$iU += 2) {
\$a = (\$iU << \$iBits);
\$iIndex = IntVal((\$a - (\$a % \$iIncr)) / \$iIncr);
\$dCos = \$daCosines[\$iIndex];
\$dSin = \$daSines[\$iIndex];
for (\$i = \$iU; \$i < \$iArraySize; \$i += \$iStep) {
\$j = \$i + \$iIncr;
}
}
}
}

function CreateFourierTransformColorChannelsImage(\$qColorImage) {
\$iW   = ImageSX(\$qColorImage);
\$iH   = ImageSY(\$qColorImage);
// Allocate the color channel transform images
\$qImageR   = ImageCreate(256, 256);
\$qImageG   = ImageCreate(256, 256);
\$qImageB   = ImageCreate(256, 256);
for (\$iC = 0; \$iC < 256; ++\$iC) {
ImageColorAllocate(\$qImageR, \$iC,   0,   0);
ImageColorAllocate(\$qImageG,   0, \$iC,   0);
ImageColorAllocate(\$qImageB,   0,   0, \$iC);
}
// Create the Red, Green, and Blue Channel images
for (\$j = 0; \$j < \$iH; ++\$j) {
for (\$i = 0; \$i < \$iW; ++\$i) {
\$qColor  = ImageColorAt(\$qColorImage, \$i, \$j);
\$iRed    = ((\$qColor >> 16) & 0xFF);
\$iGreen  = ((\$qColor >> 8) & 0xFF);
\$iBlue   = (\$qColor & 0xFF);
ImageSetPixel(\$qImageR, \$i, \$j, \$iRed);
ImageSetPixel(\$qImageG, \$i, \$j, \$iGreen);
ImageSetPixel(\$qImageB, \$i, \$j, \$iBlue);
}
}
\$qaChannelImages = array();
\$qaChannelImages[0] = \$qImageR;
\$qaChannelImages[1] = \$qImageG;
\$qaChannelImages[2] = \$qImageB;

\$daCmplIm      = new SplFixedArray(2*\$iW*\$iH);
\$daComplex     = new SplFixedArray(2*\$iW);
for (\$iImage = 0; \$iImage < 3; ++\$iImage) {
\$qCurrImage = \$qaChannelImages[\$iImage];
for(\$i = 0; \$i < \$iW; ++\$i) {
for(\$j = 0; \$j < \$iW; ++\$j) {
\$daCmplIm[2*\$i + 2*\$iW*\$j] = ImageColorAt(\$qCurrImage, \$i, \$j);
\$daCmplIm[2*\$i + 1 + 2*\$iW*\$j] = 0;
}
}
// Transform the rows
for(\$iY = 0; \$iY < \$iW; ++\$iY) {
\$iR = \$iY*(\$iW << 1);
\$iDW = (\$iW << 1);
for(\$iX = 0; \$iX < \$iDW; ++\$iX) {
\$daComplex[\$iX] = \$daCmplIm[\$iR + \$iX];
}
FFT(\$daComplex, \$iW, 1);
for(\$iX = 0; \$iX < \$iDW; ++\$iX) {
\$daCmplIm[\$iR + \$iX] = \$daComplex[\$iX];
}
}
for(\$iX = 0; \$iX < \$iDW; \$iX +=2) {
for(\$iY = 0; \$iY < \$iW; ++\$iY) {
\$iR = \$iY*(\$iW << 1);
\$daComplex[2*\$iY]      = \$daCmplIm[\$iR + \$iX];
\$daComplex[2*\$iY + 1]  = \$daCmplIm[\$iR + \$iX + 1];
}
FFT(\$daComplex, \$iW, 1);
\$dScale = \$iW*\$iW;
for(\$iY = 0; \$iY < \$iW; ++\$iY) {
\$iR = \$iY*(\$iW << 1);
\$daCmplIm[\$iR + \$iX]      = (\$daComplex[2*\$iY]/\$iW);
\$daCmplIm[\$iR + \$iX + 1]  = (\$daComplex[2*\$iY + 1]/\$iW);
}
}
// Copy the image data back after the transform
for(\$i = 0; \$i < \$iW; ++\$i) {
for(\$j = 0; \$j < \$iW; ++\$j) {
\$iCurrPixel = Clamp(IntVal(round(sqrt(
\$daCmplIm[2*\$i + 2*\$iW*\$j]*\$daCmplIm[2*\$i + 2*\$iW*\$j]
+ \$daCmplIm[2*\$i + 2*\$iW*\$j + 1]*\$daCmplIm[2*\$i + 2*\$iW*\$j + 1]))));
\$iHalfWidth = \$iW/2;
\$iX = 0;
\$iY = 0;
if (\$i < \$iHalfWidth) {
\$iX = \$iHalfWidth - \$i - 1;
} else {
\$iX = \$iHalfWidth + \$iW - \$i - 1;
}
if (\$j < \$iHalfWidth) {
\$iY = \$iHalfWidth - \$j - 1;
} else {
\$iY = \$iHalfWidth + \$iW - \$j - 1;
}
ImageSetPixel(\$qCurrImage, \$iX, \$iY, \$iCurrPixel);
}
}
}

\$qFourierChannelImage = ImageCreateTrueColor(2*\$iW, 2*\$iH);
// Copy the transformed color channel images
ImageCopyMerge(\$qFourierChannelImage, \$qColorImage, 0, 0, 0, 0, \$iW, \$iH, 100);
ImageCopyMerge(\$qFourierChannelImage, \$qImageR, \$iW, 0, 0, 0, \$iW, \$iH, 100);
ImageCopyMerge(\$qFourierChannelImage, \$qImageG, \$iW, \$iH, 0, 0, \$iW, \$iH, 100);
ImageCopyMerge(\$qFourierChannelImage, \$qImageB, 0, \$iH, 0, 0, \$iW, \$iH, 100);

ImageDestroy(\$qImageR);
ImageDestroy(\$qImageG);
ImageDestroy(\$qImageB);
return \$qFourierChannelImage;
}

\$qOriginalImage = ImageCreateFromPng("Moses256x256.png");

\$qFourierChannelImage = CreateFourierTransformColorChannelsImage(\$qOriginalImage);