We help IT Professionals succeed at work.

read & write binary png file

loki982
loki982 asked
on
496 Views
Last Modified: 2008-03-06
hello all,
I am trying to open a png file and send it over the network. To get the binary data within the png file I have the following code:

/*
Copy PNG Test
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX      1024

int main (void) {
      char buf[MAX];
      FILE *fptr, *cptr, *sptr;

      char *string;
      string = malloc(15360);

      fptr=fopen("./img/some_image.png","rb");
      cptr = fopen("./img/cptr_temp.png","wb");
      sptr = fopen("./img/sptr_temp.png","wb");

      if (fptr==NULL) return 1;

      sprintf(string,"");
      while(fread(buf,MAX,1,fptr) > 0 )
      {
            fwrite(buf,MAX,1,cptr);     // bottom portion of image cut off
            sprintf(string,"%s%s",string,buf);     // no image
      }
      fwrite(string,strlen(string),1,sptr);

      fclose(fptr);
      fclose(cptr);
      fclose(sptr);
      return 0;
}

When i run the following code on a png file of size 9.4K for example cptr_temp is 9.0K (missing the lower portion of the image) and sptr_temp [The array I really want] is about 713 bytes (no image). Can anyone see what I'm doing wrong?
Thankz,
~Sean
Comment
Watch Question

Commented:
The fread function will return the number of full "chunks" it read. In your case each chunk is set to be 1024 bytes and count is 1. So it will only return 1 if it can read 1024 bytes. This will work fine if your files have sizes that are multiples of 1024. However, if that is not the case, the trailing (smaller) chunk at the end of each file would be lost because the fread that gets it will return 0, and whatever is in buf will not get "fwritten" out.

Author

Commented:
i change the MAX in fread() & fwrite() to 1 and this does fix the cptr_temp image;
sptr_temp is now 9.1K (still using the 9.4K example image), and it is still "corrupt" and still unreadable...
Kent OlsenData Warehouse / Database Architect
CERTIFIED EXPERT

Commented:
Hi loki,

Several problems here.  Within the while() loop, the sprintf() function is acting essentially as a strcat().  Your trying to append the new block onto the previous block.  Two things are working against you here.  You're dealing with binary data so ANY zero byte in the buffer is treated as end of line.  The copy stops there.  Also, string[] is only MAX bytes long.  Even if your append process works, you're going to overflow string[] and clobber something critical.  Use realloc() and memcpy().

About the fread() and fwrite() functions -- there's nothing wrong with setting MAX to 1024.  You just need to swap the parameters so that you're trying to read 1024 1-byte items instead of 1 1024-byte item.


Good Luck,
Kent

Author

Commented:
the string[] is actually malloc'd up above the while with some 'huuge' number,
MAX is only used for the buffer... This still does not solve the zero byte data in the buffer;
hummmmm   ...so i can't just concatenate the binary data to a string.
is there perhaps a conversion method or something?
i'm open to any suggestions...
thankz
CERTIFIED EXPERT
Top Expert 2006

Commented:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX     1024

int main (void) {
     char buf[MAX];
     FILE *fptr, *cptr, *sptr;

     char *string;
     int ret;
     int count = 0;
     string = (char *) malloc(15360);

     fptr=fopen("./img/some_image.png","rb");
     cptr = fopen("./img/cptr_temp.png","wb");
     sptr = fopen("./img/sptr_temp.png","wb");

     if (fptr==NULL) return 1;

     memset(string,0,15360);

     while(ret = fread(buf,1,MAX,fptr) > 0 )
     {
          fwrite(buf,1,ret,cptr);     // write only that much which you have read
          memcpy(string+count,buf,ret);
          count = count + ret;
     }
     fwrite(string,strlen(string),1,sptr); /* replace this on your own ;o) .. btw do you really need it ? */

     fclose(fptr);
     fclose(cptr);
     fclose(sptr);
     return 0;
}

as a general rule, never use string functions for binary data and try to make use of return values ....

Author

Commented:
thankz sunnycoder... i have this part up and running
what i'm trying to do is send the image over the network (from client to server) and then write it out. At this point the client can now make a flawless copy but the server does not.


client code:
...      if(fptr = fopen(src_name, "rb")) {
            while(ret = fread(buffer,1,1,fptr) > 0 )
            {
                  memcpy(string+count,buffer,ret);
                  count = count + ret;
            }
            fclose(fptr);

      }
...

server code:
...                              char buf[15360];
                              
                              bzero(buf, 15360);//BUFFER_SIZE);
                              if( recv(ns, buf, 1024/*BUFFER_SIZE*/, 0) == -1 ) {
                                    fprintf(stderr, "recv() did not get client data\n");
                                    exit(6);
                              }
                              if( send( ns, "OK", sizeof("OK"), 0) < 0) {
                                    fprintf(stderr, "send() failed.\n");
                                    exit(7);
                              }

                              int i;
                              FILE *fptr;
                              char *string;

                              string = (char *) malloc(15360);
                              memset(string,0,15360);

                              memcpy(string,buf,15360);

                              fptr = fopen("./img/image.png","wb");
                              for(i=0;i<5767;i++) {
                                    fwrite(string,1,1,fptr);
                                    *string++;
                              }
                              fclose(fptr);
...

now when the server writes the file out, it is the same size as the client png but it only has the upper half of the image - the rest is just black
thankz,
~sean











Author

Commented:
btw in:   for(i=0;i<5767;i++) {   5767 is just count hardcoded in the server
CERTIFIED EXPERT
Top Expert 2006
Commented:
This one is on us!
(Get your first solution completely free - no credit card required)
UNLOCK SOLUTION

Author

Commented:
it werkz perfectly!
i have taken all of the string functions out and am now adding the return value functionallity.
1000 thankz
~sean

Gain unlimited access to on-demand training courses with an Experts Exchange subscription.

Get Access
Why Experts Exchange?

Experts Exchange always has the answer, or at the least points me in the correct direction! It is like having another employee that is extremely experienced.

Jim Murphy
Programmer at Smart IT Solutions

When asked, what has been your best career decision?

Deciding to stick with EE.

Mohamed Asif
Technical Department Head

Being involved with EE helped me to grow personally and professionally.

Carl Webster
CTP, Sr Infrastructure Consultant
Empower Your Career
Did You Know?

We've partnered with two important charities to provide clean water and computer science education to those who need it most. READ MORE

Ask ANY Question

Connect with Certified Experts to gain insight and support on specific technology challenges including:

  • Troubleshooting
  • Research
  • Professional Opinions
Unlock the solution to this question.
Join our community and discover your potential

Experts Exchange is the only place where you can interact directly with leading experts in the technology field. Become a member today and access the collective knowledge of thousands of technology experts.

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.