2
votes

I'm trying to calculate DCT and IDCT of an input image, and display the IDCT output as resultant image. But my IDCT values are going above 300. My input image is a '.rgb' image. I am also considering the height and width of the input image as constant i.e., 352*288

I am representing my input red, green and blue integers of each pixels as rgb[3][64][1583] where [3] -> index of red/green/blue and [64] -> index of pixel in each block and the [1583]-> index of the 8*8 block i.e., one of the block in 1583 blocks.

And lastly im keeping my quantization table as which has uniform value -> 2^N where N is passed as parameter.In this code the quantLevel is the N above.

Following is my Code:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Jpeg {    
   double rgb[][][]=new double[3][64][1584];
   double rgbfinal[][][]=new double[3][64][1584];
   double R[][]=new double[64][1584];
   double G[][]=new double[64][1584];
   double B[][]=new double[64][1584];

   public void go(String fname, int quantLevel){       
     int numBlocks=(352*288)/64;           

    String fileName = fname;
    int width=352,height=288;   
    BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

    try {
            File file = new File(fname);
        InputStream is = new FileInputStream(file);

        long len = file.length();
        byte[] bytes = new byte[(int)len];

        int offset = 0;
            int numRead = 0;
            while (offset < bytes.length && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
                offset += numRead;
        }               
        int ind = 0;
        for(int y = 0; y < height; y++){    
            for(int x = 0; x < width; x++){                     
                byte r = bytes[ind];
                byte g = bytes[ind+height*width];
                byte b = bytes[ind+height*width*2];                 
                int pix = 0xff000000 | ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff);             
                img.setRGB(x,y,pix);
                ind++;
            }
        }           
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }

   int indexRow=0,indexCol=0,indexBlock=0,indexBits=0,indexPixelBlock=0,indexPixel=0;
   long  count=0L;
   String binary="";

       indexPixel=0;
       indexBlock=0;   
       int i=0;
           while(count!=(long)(numBlocks*64)){                                                                                                         
               int pix = img.getRGB(indexCol, indexRow);
               int red = (pix >> 16) & 0x000000FF;
               int green = (pix >>8 ) & 0x000000FF;
               int blue = (pix) & 0x000000FF;

               rgb[0][indexPixel][indexBlock]=red;               
               rgb[1][indexPixel][indexBlock]=green;               
               rgb[2][indexPixel][indexBlock]=blue;

              count++;         
              indexPixel++;

              if(indexCol==width-1 && indexRow==height-1)               
                  break;                

              if(indexCol%7==0 && indexCol!=0 && indexPixel%8==0)
                  {                                                 
                      indexPixel=indexPixelBlock;
                      indexBlock++;                                                                                                   
                  }

              if(indexPixel%8==0 && indexCol%7!=0 && indexBlock!=1583)
                  {
                     indexPixel=indexPixelBlock;
                     indexBlock++;
                  }

              if(indexCol==width-1)
                  {                       
                      indexCol=0;                   
                      indexRow++;
                  } 
              else
                  indexCol++;                                                                                                                  

              if((indexPixel)%8==0 && indexBlock==numBlocks-1 && indexCol%7==0)            
                 {                        
                      indexBlock=0;
                      indexPixelBlock=indexPixel;                                              
                 }                                                 
           }
    calcQuantizedDCT(quantLevel);                    
    calcInverseDCT(quantLevel);

    JFrame frame = new JFrame();
    frame.setLocation(0,0);
    frame.setSize(1024, 720);                
    frame.getContentPane().setBackground(Color.WHITE);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);       

    JPanel p=new JPanel();   
    p.setLayout(new FlowLayout(FlowLayout.LEFT));
    p.setLocation(100,100);    

    JLabel label = new JLabel(new ImageIcon(img));    
    label.setLocation(0,0);
    label.setSize(352,288);

    p.add(label);
    frame.add(p);        
    frame.setVisible(true);

    return;
   }

   void calcQuantizedDCT(int quantLevel)
   {      
       String binary="";
       int indexBlock=0,indexPixel=0,indexBits=0,red=0,green=0,blue=0,x=0,y=0,indexPixelTemp=0,u=0,v=0;

       double sumRed=0,sumGreen=0,sumBlue=0;
       String substr="";
        int i=0;
       for(indexBlock=0;indexBlock<1584;indexBlock++)       
       {                               
           indexPixel=0;           
           //
           while(indexPixel!=64 && u<8)
           {                              
               while(indexPixelTemp<64 && x<8)
               {                                                                                               
                   red=(int)rgb[0][indexPixelTemp][indexBlock];
                   green=(int)rgb[1][indexPixelTemp][indexBlock];
                   blue=(int)rgb[2][indexPixelTemp][indexBlock];
                  // System.out.println(red);                           
                   sumRed+=red*Math.cos((Math.PI*(2*y+1)*u)/(2*8))*Math.cos((Math.PI*(2*x+1)*v)/(2*8));                                          
                   sumGreen+=green*Math.cos((Math.PI*(2*x+1)*u)/(2*8))*Math.cos((Math.PI*(2*y+1)*v)/(2*8));                                                                
                   sumBlue+=blue*Math.cos((Math.PI*(2*x+1)*u)/(16))*Math.cos((Math.PI*(2*y+1)*v)/(16));

                   indexPixelTemp++;
                   y++;
                   if(y==8)
                   {
                       x++;
                       y=0;                       
                   }       

               }              
               //System.out.println("SumRed :"+sumRed);

               if(u==0 && v==0)                   
               {                                      
                   //System.out.println("U & V & Pixel & Block "+u+" "+v+" "+indexPixel+" "+indexBlock);
                   R[indexPixel][indexBlock]=(Math.sqrt(1.0/64.0)*sumRed)/Math.pow(2,quantLevel);
                   G[indexPixel][indexBlock]=(Math.sqrt(1.0/64.0)*sumGreen)/Math.pow(2,quantLevel);
                   B[indexPixel][indexBlock]=(Math.sqrt(1.0/64.0)*sumBlue)/Math.pow(2,quantLevel);                   
               }
               else
               {
                   //System.out.println("U & V & Pixel & Block "+u+" "+v+" "+indexPixel+" "+indexBlock);                   
                   R[indexPixel][indexBlock]=(Math.sqrt(2.0/32.0)*sumRed)/Math.pow(2,quantLevel);  
                   G[indexPixel][indexBlock]=(Math.sqrt(2.0/32.0)*sumGreen)/Math.pow(2,quantLevel);  
                   B[indexPixel][indexBlock]=(Math.sqrt(2.0/32.0)*sumBlue)/Math.pow(2,quantLevel);                    
               }                   

               indexPixel++;     

               if(indexPixel==64)
                   break;
               indexPixelTemp=0;
               v++;

               if(v==8)
               {
                   v=0;
                   u++;
               }
               x=0;y=0;sumGreen=0;sumRed=0;sumBlue=0;               
           }                      

           u=0;v=0;                   
       }       

         /*  for(int j=0;j<64;j++)       
           {
               System.out.print(R[j][0]+" ");
               if(j%7==0 && j!=0)
                   System.out.println();
           }   
           */   
   }   

   void calcInverseDCT(int quantLevel)
   {       
       String binary="";
       int indexBlock=0,indexPixel=0,indexBits=0,u=0,v=0,x=0,y=0,indexPixelTemp=0,sumRed=0,sumGreen=0,sumBlue=0,red=0,green=0,blue=0;

       for(indexBlock=0;indexBlock<1584;indexBlock++)
       {            
           for(indexPixel=0;indexPixel<64;indexPixel++)
           {           
               R[indexPixel][indexBlock]=R[indexPixel][indexBlock]*Math.pow(2,quantLevel);
               G[indexPixel][indexBlock]=G[indexPixel][indexBlock]*Math.pow(2,quantLevel);
               B[indexPixel][indexBlock]=B[indexPixel][indexBlock]*Math.pow(2,quantLevel);

           } 
       }
       int i=0;
       indexPixelTemp=0;
       indexPixel=0;
       for(indexBlock=0;indexBlock<1584;indexBlock++)
       {                      
           indexPixel=0;            
           while(indexPixel<64 && x<8)
           {
               indexPixelTemp=0;
               while(indexPixelTemp<64 && u<8)
               { 
                   red=(int)R[indexPixelTemp][indexBlock];                 
                   if(u==0 && v==0)                   
                       sumRed+=Math.sqrt(1.0/2.0)*red*Math.cos((Math.PI*(2*x+1)*u)/(2*8))*Math.cos((Math.PI*(2*y+1)*v)/(2*8));                   
                   else
                       sumRed+=red*Math.cos((Math.PI*(2*x+1)*u)/(2*8))*Math.cos((Math.PI*(2*y+1)*v)/(2*8));                                                              

                   green=(int)G[indexPixelTemp][indexBlock];
                   if(u==0 && v==0)                   
                       sumGreen+=Math.sqrt(1.0/2.0)*green*Math.cos((Math.PI*(2*x+1)*u)/(2*8))*Math.cos((Math.PI*(2*y+1)*v)/(2*8));
                   else
                       sumGreen+=green*Math.cos((Math.PI*(2*x+1)*u)/(2*8))*Math.cos((Math.PI*(2*y+1)*v)/(2*8));

                   blue=(int)B[indexPixelTemp][indexBlock];
                   if(u==0 && v==0)                   
                       sumBlue+=Math.sqrt(1.0/2.0)*blue*Math.cos((Math.PI*(2*x+1)*u)/(2*8))*Math.cos((Math.PI*(2*y+1)*v)/(2*8));
                   else
                       sumBlue+=blue*Math.cos((Math.PI*(2*x+1)*u)/(2*8))*Math.cos((Math.PI*(2*y+1)*v)/(2*8)); 

                   indexPixelTemp++;
                   v++;
                   if(v==8)
                   {
                       u++;
                       v=0;
                   }                                  
               }

               rgbfinal[0][indexPixel][indexBlock]=sumRed;
               rgbfinal[1][indexPixel][indexBlock]=sumGreen;
               rgbfinal[2][indexPixel][indexBlock]=sumBlue;                  

               indexPixel++;                                   
               indexPixelTemp=0;
               y++;

               if(y==8)
               {
                   y=0;
                   x++;
               }               
               u=0;v=0;sumGreen=0;sumRed=0;sumBlue=0;               
           }             
           if(i==3)
               break;
           x=0;y=0;                   
       }

       System.out.println();       
       /*for(i=0;i<64;i++)
       {
           System.out.print(rgbfinal[0][i][0]+" ");
           if(i%7==0 && i!=0)
               System.out.println();
       }*/
   }

   public static void main(String args[]){
        Jpeg a = new Jpeg();
        a.go("src/image2.rgb",0);         
    }    
}

I am not trying to display the output image as the ouput of IDCT for Red which i checked goes above 255.

Please help.

1

1 Answers

1
votes

First, are you hoping the create a JPEG-compatible codec? Or are you just toying with multimedia coding concepts? If the latter, then more power to you. If the former, you have a lot of work ahead.

To directly answer your question: It's normal to transform an 8x8 block using a 2D forward DCT and get numbers that go above 255. Low-level implementations of the forward DCT usually take an 8x8 vector of unsigned 8-bit samples as input and output an 8x8 vector of signed 16-bit samples.

If you actually are hoping to create a JPEG-compatible codec, you still have a few topics to study. For starters, JPEG does not compress RGB. RGB data is converted to YUV and those blocks get transformed (then quantized, zigzagged, and entropy coded).