Thread: reading bitmap into array

  1. #16
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Why do you want to encrypt only the image data and not the entire file?
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  2. #17
    Registered User
    Join Date
    Jul 2009
    Posts
    14
    So currently my main looks like this
    Code:
    int main(int argc, char* argv[]){
      FILE* in;
      Bitmap* map = malloc(sizeof(Bitmap));
      if(argc <=3){
        printf("Usage: %s [-e] [-d] inputFileName outputFileName\n", argv[0]);
        return 0;
      }
      if((in = fopen(argv[2], "rb")) == NULL){
        printf("Input file: %s cannot be opened\n", argv[2]);
        exit(EXIT_FAILURE);
      }
      if(strcmp(argv[1],"-e")== 0){
        readImage(argv[2], map);
        encrypt(map);
        writeImage(argv[3], map);
      }
      else if(strcmp(argv[1],"-d")==0){
        readImage(argv[2], map);
        decrypt(map);
        writeImage(argv[3], map);
      }
      else{
        printf("You have not entered valid choices\n");
        return 0;
      }
      
     
      return EXIT_SUCCESS;
    }
    and I have very simple things written under encrypt and decrypt, but when I try running the program, there's an issue with the realloc under readImage

    Code:
    void readImage(char* infile, Bitmap *bitmap){
      int i;
      FILE* input = fopen(infile, "rb");
      char* array = malloc(sizeof(n));
      for(i=0; i<n; i++){
        fread(&array[i], 1, 1, input);
        bitmap->size +=1;
        if((bitmap->size)==n){
          array = realloc(array, (2*n));
        }
      }
      bitmap->header = &array[0];
      bitmap->data = &array[54];
      fclose(input);
    }
    I have done some printf's and it is getting to the realloc correctly, when size is 10,000. I think I am using the realloc function incorrectly then.

    Also, my writeImage currently looks like this
    Code:
    void writeImage(char* outfile, Bitmap *bitmap){
      int i;
      FILE* output = fopen(outfile, "wb");
      for(i=0; i<54; i++){
        fwrite(&(bitmap->header[i]), 1, 1, output);
      }
      for(i=0; i<((bitmap->size)-54); i++){
        fwrite(&(bitmap->data[i]), 1, 1, output);
      }
      fclose(output);
    }
    I'm not sure if that's the correct way I should be passing the data and header back out to a new bitmap file.

  3. #18
    Registered User
    Join Date
    Jul 2009
    Posts
    14
    Quote Originally Posted by brewbuck View Post
    Why do you want to encrypt only the image data and not the entire file?
    That is what I'm asked to do, just encrypt image data, keeping header intact.

  4. #19
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    I can think of a couple of reasons:
    1 - by preserving the key header information, the result is still a valid BMP file, and thus can be viewed with a normal BMP viewing tool.
    2 - if the encryption is "good", the result will just be random dots. However, poor encryption will reveal itself as a vaguely recognisable image.

    > I think I am using the realloc function incorrectly then.
    Well what is 'n'?


    > char* array = malloc(sizeof(n));
    int n = 5000;
    sizeof(n) is still 4 - probably not what you want.

    > array = realloc(array, (2*n));
    You also need to increase n as well.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #20
    Registered User
    Join Date
    Jul 2009
    Posts
    14
    At the top of the program, after the includes, there is
    #define n 10000

    I have put in some edits, but now there is a compile error regarding the reassigned n value,

    n = n*2

    error: invalid lvalue in assignment

    Is this because n is defined so I can't change it?

    Code:
    void readImage(char* infile, Bitmap *bitmap){
      int i;
      FILE* input = fopen(infile, "rb");
      char* array = malloc(n);
      for(i=0; i<n; i++){
        fread(&array[i], 1, 1, input);
        bitmap->size +=1;
        if((bitmap->size)==n){
          array = realloc(array,(n*2));
          n *=2;
        }
      }
      bitmap->header = &array[0];
      bitmap->data = &array[54];
      fclose(input);
    }
    Last edited by kallistine; 07-26-2009 at 01:35 PM. Reason: new note

  6. #21
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Well yes, it needs to be a variable if you intend to modify it's value.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #22
    Registered User
    Join Date
    Jul 2009
    Posts
    14
    Thanks! The realloc is working correctly now, but it seems to increase indefinitely, is this because there's something wrong with how my fread is working? Is this due to the fact that I lack some sort of break statement when fread has finished reading the file? To prevent the for loop from going on forever? Is there something simliar to fscanf when it reaches EOF? Here is my latest readImage function.

    Code:
    void readImage(char* infile, Bitmap *bitmap){
      int i, nsize = n;
      FILE* input = fopen(infile, "rb");
      char* array = malloc(nsize);
      for(i=0; i<nsize; i++){
        fread(&array[i], 1, 1, input);
        bitmap->size +=1;
        if((bitmap->size)==nsize){
          nsize *=2;
          printf("resizing from %d to %d\n", (bitmap->size), nsize);
          array = realloc(array,nsize);
        }
      }
      bitmap->header = &array[0];
      bitmap->data = &array[54];
      fclose(input);
    }
    the test image I am using has a size of 270,056 bytes.
    Last edited by kallistine; 07-26-2009 at 01:57 PM. Reason: another point

  8. #23
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> The realloc is working correctly now, but it seems to increase indefinitely, is this because there's something wrong with how my fread is working?

    You are using 'nsize' as a loop control variable:

    Code:
    for(i=0; i<nsize; i++)
    And then once bitmap::size reaches it, you double 'nsize' and so the process continues ad infinitum:

    Code:
        if((bitmap->size)==nsize){
          nsize *=2;
          printf("resizing from %d to %d\n", (bitmap->size), nsize);
          array = realloc(array,nsize);
        }
    But there's also the issue that 'n' (which initializes 'nsize') doesn't even belong there in the first place. What's the point of guessing the file size? This is the easiest way to do it:

    Code:
    fopen file
    fseek to the end
    ftell to get the file-size
    malloc file-size bytes
    rewind the file pointer
    fread the entire bitmap
    *validate* all of the fields in the bitmap header
    encrypt/decrypt
    rewind the file pointer
    fwrite tranformed data to file
    fclose file
    free bytes
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  9. #24
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by kallistine View Post
    Is this due to the fact that I lack some sort of break statement when fread has finished reading the file? To prevent the for loop from going on forever? Is there something simliar to fscanf when it reaches EOF?
    It doesn't look like that is so. Anyway, fread() returns the number of bytes read; at the end, it will read 0, so you can use the return value of fread().

    What you might want to do is stat the file or something first to get the exact size of the bmp so you can just malloc the right size buffer. Since the file size is in the header, you can try something like this, which is how you can read most of the header data:
    Code:
    int main() {
    	FILE *bmp = fopen("some.bmp","rb");
    	char buffer[54];
    	int *size;
    	fread(buffer,27,2,bmp); 
    	size = (int*)&buffer[2];  /* the offset to the "size" field in the header */
    	printf("size: %d",*size);
            /* now try height and width */
            	size = (int*)&buffer[18];
    	printf("\nwidth: %d",*size);
    	size = (int*)&buffer[22];
    	printf("\nheight: %d",*size);
    I just tried this and it gives the correct file size for .bmp images. So I would have to say to Sebastiani that this is the easiest way to do it .

    So: you can read in the 54 byte header, determine the size, and then malloc the buffer for *data based on that. The height and width came out correct as well -- not so hard. I just looked at:
    http://www.fastgraph.com/help/bmp_header_format.html
    Last edited by MK27; 07-26-2009 at 02:32 PM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  10. #25
    Registered User
    Join Date
    Jul 2009
    Posts
    14
    Thanks for all the suggestions but despite my constant resizing being inefficient, it's part of the directions, so I will follow that.

    I have inserted
    Code:
        if((bitmap->size >300000) && (array[i] == 0)){
          printf("breaking \n");
          break;
        }
    into the for loop to test somethings out, and my outfile bmp file displayed correctly so now I can get working on my a better encryption method and also figure out a better way to break. I can't use '0' to break because some of the RGB values are 0. Any suggestions? Thanks a lot.

  11. #26
    Registered User
    Join Date
    Jul 2009
    Posts
    14
    Actually, I think I will get more out of this assignment if I learn how to extract things from the header, I will try to implement what MK27 did. Thanks a lot!

  12. #27
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> I have inserted

    Well if you're going to do it incrementally, doesn't it make sense to at least do it the *right* way, and not just some way that randomly happens to work for you right now?
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  13. #28
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> FILE *bmp = fopen("some.bmp","rb");

    It might be a good idea to check the return value there.

    >> fread(buffer,27,2,bmp);

    Ditto.

    >> I just tried this and it gives the correct file size for .bmp images. So I would have to say to Sebastiani that this is the easiest way to do it

    And if it's an invalid file and the size is meaningless?
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  14. #29
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Sebastiani View Post
    And if it's an invalid file and the size is meaningless?
    puts("The ship is sunk! Head for the lifeboats!");
    exit (666);
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  15. #30
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    puts("The ship is sunk! Head for the lifeboats!");
    exit (666);
    I think you mean:

    puts("Iceberg at 12 o'clock - full speed ahead!");
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 7
    Last Post: 02-02-2009, 07:27 AM
  2. Reading a list of ints from file into an array
    By mesmer in forum C Programming
    Replies: 1
    Last Post: 11-10-2008, 06:45 AM
  3. Reading integers from a File into an Array
    By bobby19 in forum C Programming
    Replies: 13
    Last Post: 10-09-2006, 01:36 AM
  4. Reading a file into an array for fast access later
    By matsharp in forum C Programming
    Replies: 10
    Last Post: 08-03-2006, 02:42 AM
  5. Replies: 1
    Last Post: 04-25-2006, 12:14 AM