public static void main(String[] args) throws Exception     
   {
      String fileName = (args.length > 0) ? args[0] : "c:\\temp\\lena.jpg";
      Image image = ImageIO.read(new File(fileName));

      if (image.getWidth(null) <= 0)
      {
         System.out.println("Cannot find file "+fileName);
         System.exit(1);
      }
      
      {
         // Square image
         int w = 512;//image.getWidth(null);
         int h = 512;//image.getHeight(null);
         GraphicsDevice gs = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()[0];
         GraphicsConfiguration gc = gs.getDefaultConfiguration();
         BufferedImage img  = gc.createCompatibleImage(w, h, Transparency.OPAQUE);
         BufferedImage img2 = gc.createCompatibleImage(w, h, Transparency.OPAQUE);
         BufferedImage img3 = gc.createCompatibleImage(w, h, Transparency.OPAQUE);
         img.getGraphics().drawImage(image, 0, 0, null);
         int[] source = new int[w * h];
         int[] destination = new int[w * h];
         img.getRaster().getDataElements(0, 0, w, h, source);
         SliceIntArray iia1 = new SliceIntArray(source, 0);
         SliceIntArray iia2 = new SliceIntArray(destination, 0);
         long before = System.nanoTime();

         ColorModelConverter cvt = new YCbCrColorModelConverter(w, h);//, (y*w)+x, ww);
         process(1, w, h, cvt, iia1, iia2);
         long after = System.nanoTime();
         System.out.println("Time elapsed [ms]: "+ (after-before)/1000000);


         ImageQualityMonitor monitor = new ImageQualityMonitor(w, h);
         int psnr1024 = monitor.computePSNR(source, destination);
         System.out.println("PSNR: "+(float) psnr1024 /1024);
         int ssim1024 = monitor.computeSSIM(source, destination);
         System.out.println("SSIM: "+(float) ssim1024 / 1024);

         boolean imgDiff = false;

         if (imgDiff == true)
         {
            for (int j = 0; j < h; j++)
            {
               for (int i = 0; i < w; i++)
               {
                  int p1 = source[j * w + i];
                  int p2 = destination[j * w + i];
                  int r1 = (p1 >> 16) & 0xFF;
                  int g1 = (p1 >> 8) & 0xFF;
                  int b1 = p1 & 0xFF;
                  int r2 = (p2 >> 16) & 0xFF;
                  int g2 = (p2 >> 8) & 0xFF;
                  int b2 = p2 & 0xFF;
                  int rr = (Math.abs(r1 - r2) & 0xFF) << 16;
                  int gg = (Math.abs(g1 - g2) & 0xFF) << 8;
                  int bb =  Math.abs(b1 - b2) & 0xFF;
                  destination[j * w + i] = rr | gg | bb;
               }
            }
         }

         img2.getRaster().setDataElements(0, 0, w, h, destination);
         JFrame frame2 = new JFrame("Reverse");
         frame2.setBounds(720, 50, w, h);
         ImageIcon newIcon2 = new ImageIcon(img2);
         frame2.add(new JLabel(newIcon2));
         frame2.setVisible(true);

         img3.getRaster().setDataElements(0, 0, w, h, source);
         JFrame frame3 = new JFrame("Original");
         frame3.setBounds(100, 50, w, h);
         ImageIcon newIcon3 = new ImageIcon(img3);
         frame3.add(new JLabel(newIcon3));
         frame3.setVisible(true);
      }
      
      {
         // Non square image
         int w = 288;//image.getWidth(null);
         int h = 512;//image.getHeight(null);
         GraphicsDevice gs = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()[0];
         GraphicsConfiguration gc = gs.getDefaultConfiguration();
         BufferedImage img  = gc.createCompatibleImage(w, h, Transparency.OPAQUE);
         BufferedImage img2 = gc.createCompatibleImage(w, h, Transparency.OPAQUE);
         BufferedImage img3 = gc.createCompatibleImage(w, h, Transparency.OPAQUE);
         img.getGraphics().drawImage(image, 0, 0, null);
         int[] source = new int[w * h];
         int[] destination = new int[w * h];
         img.getRaster().getDataElements(0, 0, w, h, source);
         SliceIntArray iia2 = new SliceIntArray(source, 0);
         SliceIntArray iia3 = new SliceIntArray(destination, 0);
         long before = System.nanoTime();

         ColorModelConverter cvt = new YCbCrColorModelConverter(w, h);//, (y*w)+x, ww);
         process(2, w, h, cvt, iia2, iia3);
         long after = System.nanoTime();
         System.out.println("Time elapsed [ms]: "+ (after-before)/1000000);


         ImageQualityMonitor monitor = new ImageQualityMonitor(w, h);
         int psnr1024 = monitor.computePSNR(source, destination);
         System.out.println("PSNR: "+(float) psnr1024 /1024);
         int ssim1024 = monitor.computeSSIM(source, destination);
         System.out.println("SSIM: "+(float) ssim1024 / 1024);

         boolean imgDiff = false;

         if (imgDiff == true)
         {
            for (int j = 0; j < h; j++)
            {
               for (int i = 0; i < w; i++)
               {
                  int p1 = source[j * w + i];
                  int p2 = destination[j * w + i];
                  int r1 = (p1 >> 16) & 0xFF;
                  int g1 = (p1 >> 8) & 0xFF;
                  int b1 = p1 & 0xFF;
                  int r2 = (p2 >> 16) & 0xFF;
                  int g2 = (p2 >> 8) & 0xFF;
                  int b2 = p2 & 0xFF;
                  int rr = (Math.abs(r1 - r2) & 0xFF) << 16;
                  int gg = (Math.abs(g1 - g2) & 0xFF) << 8;
                  int bb =  Math.abs(b1 - b2) & 0xFF;
                  destination[j * w + i] = rr | gg | bb;
               }
            }
         }

         img2.getRaster().setDataElements(0, 0, w, h, destination);
         JFrame frame2 = new JFrame("Reverse");
         frame2.setBounds(720, 600, w, h);
         ImageIcon newIcon2 = new ImageIcon(img2);
         frame2.add(new JLabel(newIcon2));
         frame2.setVisible(true);

         img3.getRaster().setDataElements(0, 0, w, h, source);
         JFrame frame3 = new JFrame("Original");
         frame3.setBounds(100, 600, w, h);
         ImageIcon newIcon3 = new ImageIcon(img3);
         frame3.add(new JLabel(newIcon3));
         frame3.setVisible(true);
      }

      try
      {
         Thread.sleep(40000);
      }
      catch (Exception e)
      {
         e.printStackTrace();
      }

      System.exit(0);
   }