0

I want to able to compare 2 images (same format) and perform bit level comparison on those images. 1)create structs for headers.2) open the files and read the contents starting at the image data offset from the SOI marker.3) Store the respective values in a 3d array or a vector array.4)Do an element wise comparison and return a result. I have successfully been able to do this for a bmp using fread() and used a 3d array as a container with methods that can allocate and deallocate memory.(But bmp's are uncompressed images). Somehow this process seems a lot harder for jpeg's and tiff's.Even after understanding the header format for these 2 formats, my code says that it cannot read the color at element [45][24] .I have looked at several other options like libjpeg and CImg but I would like to get point of views before i jump into a new library.

My code for bmp is as follows : ...snip...

unsigned char*** create3dArray(FILE **fptr1,int height,int width,int depth)
{
       unsigned char*** databuff = new unsigned char **[height];

   // Allocate an array for each element of the first array
   for(int x = 0; x < height; ++x)
   {
        databuff[x] = new unsigned char *[width];

        // Allocate an array of integers for each element of this array
        for(int y = 0; y < width; ++y)
        {
            databuff[x][y] = new unsigned char[depth];

            // Specify an initial value (if desired)
            for(int z = 0; z < depth; ++z)
            {
                    databuff[x][y][z] = -1;

            }
        }
   }

   if ((sizeof(fheader) != 14) || (sizeof(iheader) != 40)) 
   {
        printf("Header structs are not properly packed\n");
    return 0;
    }

  if (fread(&fheader, sizeof(fheader), 1, *fptr1) != 1)
  {
    printf("Couldn't read fheader.\n");
    return 0;
   }

   if (fread(&iheader, sizeof(iheader), 1, *fptr1) != 1) 
  {
    printf("Couldn't read iheader.\n");
    return 0;
}
 // uncomment to get an idea of what the headers look like.
if ((iheader.height != height) || (iheader.width != width) || (iheader.bits != 24)) 
   {
    printf("This only works for 512x512 24-color bitmaps\n");
    return 0;
    }



    if (fheader.offset != 54) {
    printf("This only works if the offset is equal to 54\n");
    return 0;
    }
    for (int i = 0; i < iheader.height; i++) {
    for (int j = 0; j < iheader.width; j++) {
         if (fread(&databuff[i][j][0], 3, 1, *fptr1) != 1 ){
            printf("Couldn't read colors for element [%d][%d]\n", i, j);
                        return 0;
                    }
            }
            }

 return databuff;
}

template <typename Tx>
void destroy3dArray(Tx*** myArray)
{
delete[] **myArray;
delete[] *myArray;
delete[] myArray;
}

int main()
{
 FILE *fptr1,*fptr2;        // two file pointers one for each file.
 int count=0;
 float total_bits=0;
 float ber=0;               //variable for bit error rate
 int width,height,depth;
 cout<<"Please enter height of the image "<<endl;
 cin>>height;
 cout<<"Please enter width of the image "<<endl;
 cin>>width;
 cout<<"Please enter depth of the image. The max depth can be 3 for RGB values"<<endl;
 cin>>depth;
 char *filename = "lena512.bmp";
 char *filename2 = "lena512_2.bmp";
 //std::string trueBinaryDataInString[512][512][3];

 if ((fptr1 = fopen(filename, "r")) == NULL) {
            printf("Coulsn't open file %s for reading.\n", filename);
            return 1;
        }
 unsigned char*** trueArray = create3dArray(&fptr1,height,width,depth);

 for(int i=0;i<height;i++)
{   
    //std::cout << "Row " << i << std::endl;
    for(int j=0;j<width;j++)
    {
        for(int k=0;k<depth;k++)
        {

            total_bits += ToBinary(trueArray[i][j][k]).length();

        }
        //std::cout<<endl;
    }
//std::cout<<endl;
}
 std::cout << total_bits<<endl;
 //createAnddestroy3dArray<unsigned char> MyArray;
 if ((fptr2 = fopen(filename2, "r")) == NULL) {
            printf("Coulsn't open file %s for reading.\n", filename2);
            return 1;
        }
 unsigned char*** trueArray2 = create3dArray(&fptr2,height,width,depth);
 /*for(int i=0;i<512;i++)
{
    std::cout << "Row " << i << std::endl;
    for(int j=0;j<512;j++)
    {
        for(int k=0;k<3;k++)
        {
            std::cout<<" "<<ToBinary(trueArray2[i][j][k]);
        }
        std::cout<<endl;
    }
std::cout<<endl;
}
 */
 /******** BIT Error Rate Calculation ******/
for(int i=0;i<height;i++)
{
for(int j=0;j<width;j++)
    {
    for(int k=0;k<depth;k++)
        {
          if(ToBinary(trueArray[i][j][k])!= ToBinary(trueArray2[i][j][k]))  
            {
 std::cout<<ToBinary(trueArray[i][j][k])<< " " <<ToBinary(trueArray2[i] [j][k])<<endl;
            count++;
            }
            else 
            continue;
        }
    }
}
 ber = (count/total_bits)*100;
 std::cout<<"Bit Error Rate (BER) = "<<ber<<endl;
 destroy3dArray<unsigned char>(trueArray);    //Deallocating memory for array 1
 destroy3dArray<unsigned char>(trueArray2);   //Deallocating memory for array 2
 return 0;
 }

2 Answers2

1

JPEG and TIFF are compressed formats with perhaps greater degrees of freedom in encoding images that you perhaps might expect.

So you are approaching the problem from the wrong angle. To support choices of imaging formats you need libraries to read and decompress the files into bitmap, such as 24-bit RGB or something else. There might be a color space conversion required as one of the compared images might be decompressed into 4:2:2 YUV space and the other is 4:2:0 etc.

Leveraging some image library at your choice (perhaps you have OS constraints as well) you would be able to load and decompress the files into 2D array of pixels of format of your interest. Having that done you would feed that into your C++ number crunching code and do the comparison from there.

Roman R.
  • 68,205
  • 6
  • 94
  • 158
  • So i would have to first convert these file formats into bmp's. As in load a jpg first and then save it as a bmp and then use those files. If yes, then will the change of state affect any header info ? – user1227372 Jul 12 '12 at 21:23
  • Not necessarily to resave into .BMP, buit this is possible as well. The libraries mentioned on the answers let you load and decompress in memory, without saving into intermediate file. The libraries also let you access metadata of the original file, in case you need it. – Roman R. Jul 12 '12 at 22:21
0

Successfully parsing and handling the possible variations in JPEG and TIFF files is hard. There are a surprising number of details: color depth, progressive encoding, EXIF data, thumbnails, - the list goes on. Take advantage of the libraries and don't reinvent the wheel. Use libjpeg and libtiff to load suitable (RGB?) buffers for comparison.

http://www.libtiff.org/

http://www.ijg.org/

FWIW, libpng is pretty good, too - if you want to extend your image comparison to that format, as well. http://www.libpng.org/pub/png/libpng.html

Throwback1986
  • 5,887
  • 1
  • 30
  • 22