[Gdal-dev] code to guess the pixels and lines of a raw image

Fu Chen fchen at ne.rsgs.ac.cn
Tue Nov 11 07:10:53 EST 2003


This is a small script to guess the pixels and lines of a raw image. I think photoshop use the same engine, but more efficient. I hope this code will be useful for some pals. Enjoy!

/*==============================================================================

          ------------ Standard Info Tag -------------

    <  FILENAME >       GuessRaw.cpp
    < COPYRIGHT >       (C) 2003 - 2004, RSGS.
    <DESCRIPTION>       This cpp file includes the function to analyse the struct
      of Raw image and judge its best pixel line couple by the 
      relative value difference between the lines nearby.
    <  VERSION  >       1.0
    <  AUTHOR   >       Fu CHEN
    <   DATE    >       2003-11-02

         ------------ Modification Record ------------
    <DESCRIPTION>       Use short-cut method to speed the guess progress.
  <NOTE>       There is something can be done to guess the image with very
      few lines. We may select two the nearby scaning nLines and 
      divide into several parts, then compare the values in different part.
    <MODIFIER>          Fu CHEN
    <DATE>              2003-11-04

         ------------ Modification Record ------------
    <DESCRIPTION>       Add comments and do some modification on variable name.
    <MODIFIER>          Fu CHEN
    <DATE>              2003-11-08

==============================================================================*/

/*----- Includes ---------------------------*/
#include <stdio.h>
#include <math.h>
#include "cpl_port.h"
#include "cpl_conv.h"
#include "cpl_error.h"
#include "cpl_vsi.h"

/*----- Constants --------------------------*/
#define MAX_VALUE 256
/*----- Typedefs ---------------------------*/

/*----- Structures & Unions ----------------*/

/*----- Statics ----------------------------*/
int s_nLen;
int s_nRatio;
FILE * s_fin;

/*============================================================================*/
/*    ------ Function Bodies ------     */

/************************************************************************/
/*                             TestErr()                                */
/************************************************************************/

/**
 * This function compare the nearby scanlines to find out the average error
 * between the pixel value. The amount to exam is set by static global variable
 * s_nRatio. This function is low effience for it short of a shortcut algorithm
 * for in same situation we can know the guess is totally wrong by just watch the 
 * first few scanlines. This is implemented in TestErrShortCut().
 *
 * @param nPixels guessed number of pixels in the image.
 * @param nLines guessed number of scanlines in the image.
 * @return The average error between between the nearby scanlines
 */
double TestErr(int nPixels, int nLines)
{
 long lCount = 0;
 int nSamples = s_nLen * s_nRatio / 100 / nPixels;
 if (nSamples > 0)
 {
  GByte * a = new GByte[nPixels];
  GByte * b = new GByte[nPixels];
  for (int i = 0; i < nSamples; i++)
  {
   int j = (nLines-2) * i / nSamples; // 0..nLines-2, nLines-1
   VSIFSeek(s_fin, j*nPixels, SEEK_SET);
   VSIFRead(a, nPixels, 1, s_fin);
   VSIFSeek(s_fin, (j+1)*nPixels, SEEK_SET);
   VSIFRead(b, nPixels, 1, s_fin);
   for (int k = 0; k < nPixels; k++) 
    lCount += abs(a[k]-b[k]);
  }
  delete []a;
  delete []b;
  return 1.0 * lCount / ( nSamples * nPixels);
 }
 else
  return MAX_VALUE;
}

/************************************************************************/
/*                        TestErrShortCut()                             */
/************************************************************************/

/**
 * This function evolve form TestErr(). Add some shortcut to bypass the apperant 
 * wrong Guess candidate. 
 *
 * @param nPixels guessed number of pixels in the image.
 * @param nLines guessed number of scanlines in the image.
 * @param dMinNow the minimal error up to now.
 * @return the average error between between the nearby scanlines
 */
double TestErrShortCut(int nPixels, int nLines, double dMinNow)
{
 long lCount = 0;
 int nSamples = s_nLen * s_nRatio / 100 / nPixels;
 if (nSamples > 0)
 {
  GByte * a = new GByte[nPixels];
  GByte * b = new GByte[nPixels];
  int i;
  for (i = 0; i < nSamples/4; i++)
  {
   int j = (nLines-2) * i / nSamples; // 0..nLines-2, nLines-1
   VSIFSeek(s_fin, j*nPixels, SEEK_SET);
   VSIFRead(a, nPixels, 1, s_fin);
   VSIFSeek(s_fin, (j+1)*nPixels, SEEK_SET);
   VSIFRead(b, nPixels, 1, s_fin);
   for (int k = 0; k < nPixels; k++) 
    lCount += abs(a[k]-b[k]);
  }
  if (1.0 * lCount / ( nSamples * nPixels ) > dMinNow * 4)
   return MAX_VALUE;

  for (i = nSamples/4; i < nSamples/3; i++)
  {
   int j = (nLines-2) * i / nSamples; // 0..nLines-2, nLines-1
   VSIFSeek(s_fin, j*nPixels, SEEK_SET);
   VSIFRead(a, nPixels, 1, s_fin);
   VSIFSeek(s_fin, (j+1)*nPixels, SEEK_SET);
   VSIFRead(b, nPixels, 1, s_fin);
   for (int k = 0; k < nPixels; k++) 
    lCount += abs(a[k]-b[k]);
  }
  if (1.0 * lCount / ( nSamples * nPixels ) > dMinNow * 3)
   return MAX_VALUE;

  for (i = nSamples/3; i < nSamples/2; i++)
  {
   int j = (nLines-2) * i / nSamples; // 0..nLines-2, nLines-1
   VSIFSeek(s_fin, j*nPixels, SEEK_SET);
   VSIFRead(a, nPixels, 1, s_fin);
   VSIFSeek(s_fin, (j+1)*nPixels, SEEK_SET);
   VSIFRead(b, nPixels, 1, s_fin);
   for (int k = 0; k < nPixels; k++) 
    lCount += abs(a[k]-b[k]);
  }
  if (1.0 * lCount / ( nSamples * nPixels ) > dMinNow * 2)
   return MAX_VALUE;

  for (i = nSamples/2; i < nSamples; i++)
  {
   int j = (nLines-2) * i / nSamples; // 0..nLines-2, nLines-1
   VSIFSeek(s_fin, j*nPixels, SEEK_SET);
   VSIFRead(a, nPixels, 1, s_fin);
   VSIFSeek(s_fin, (j+1)*nPixels, SEEK_SET);
   VSIFRead(b, nPixels, 1, s_fin);
   for (int k = 0; k < nPixels; k++) 
    lCount += abs(a[k]-b[k]);
  }

  delete [] a;
  delete [] b;
  return 1.0 * lCount / ( nSamples * nPixels);
 }
 else
  return MAX_VALUE;
}

/************************************************************************/
/*                              Guess()                                 */
/************************************************************************/

/**
 * This function guess the best pixels-lines couple by exam the error
 * of each candidate by calling TestErr() or TestErrShortCut(). 
 *
 * @param dMin [in out] the minimal error of all candidates.
 * @param nPixels [out] the best candidate's pixels.
 * @param nLines [out] the best candidate's lines.
 */
void Guess(double& dMin, int& nPixels, int& nLines)
{
 int sq = (int)sqrt(s_nLen);
 for (int i = sq; i >= 2; i--)
 {
  if ( s_nLen % i == 0 )
  {
   int k = s_nLen / i;
   double dAveErr = TestErrShortCut(i, k, dMin);
   if (dAveErr < dMin)
   {
    dMin = dAveErr;
    nPixels = i;
    nLines = k;
   }
   CPLDebug("Guess", "Pixels = %d, Lines = %d, dMin = %f\n", i, k, dAveErr);
   dAveErr = TestErrShortCut(k, i, dMin);
   if (dAveErr < dMin)
   {
    dMin = dAveErr;
    nPixels = k;
    nLines = i;
   }
   CPLDebug("Guess", "Pixels = %d, Lines = %d, dMin = %f\n", k, i, dAveErr);
  }
 }
}

int main( int argc, char ** argv)
{
 if (argc < 2)
 {
  printf("GuessRaw <FileName> [ExamRatio nn%]\n");
  exit(1);
 }
 s_fin = VSIFOpen (argv[1], "rb");
 VSIFSeek (s_fin, 0, SEEK_END);
 s_nLen = VSIFTell (s_fin);

 double dMin;
 int nPixels, nLines;
 dMin = MAX_VALUE;
 
 if (argc >= 3)
  s_nRatio = atoi(argv[2]);
 else
  s_nRatio = 10; // for default, exam 10% of all content

 Guess(dMin, nPixels, nLines);
 if (dMin < MAX_VALUE)
  printf("Pixels = %d, Lines = %d, dMin = %f\n", nPixels, nLines, dMin);
 else
  printf("I don't think it is a matrix of image for its length is a prime number.\n");
 VSIFClose(s_fin);
 return 0;
}

/*----------------------------------------------------------------------------*/





More information about the Gdal-dev mailing list