Image Processing Computer Science

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
  function FFT($daData, $iLength, $iSign) {
    $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) {
        $dTemp            = $daData[$iIndex2];
        $daData[$iIndex2] = $daData[$iIndex];
        $daData[$iIndex]  = $dTemp;
        $dTemp                = $daData[$iIndex2 + 1];
        $daData[$iIndex2 + 1] = $daData[$iIndex + 1];
        $daData[$iIndex + 1]  = $dTemp;
      }
    }
    $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;
          $dTR = $dCos*$daData[$j]-$dSin*$daData[$j+1];
          $dTI = $dCos*$daData[$j+1]+$dSin*$daData[$j];
          $daData[$j]=$daData[$i]-$dTR;
          $daData[$i]=$daData[$i]+$dTR;
          $daData[$j+1]=$daData[$i+1]-$dTI;
          $daData[$i+1]=$daData[$i+1]+$dTI;
        }
      }
    }
  }

  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);

  Header('Content-type: image/png');
  ImagePng($qFourierChannelImage);
  ImageDestroy($qOriginalImage);
  ImageDestroy($qFourierChannelImage);
?>
 
 

Output

 
 

© 2007–2022 XoaX.net LLC. All rights reserved.