0

Certain things have changed since this was originally posted. I've marked them with an Edit header.

I'm writing an image file from a source with a different format. This is data which is 1024x1024 and has 2 bytes per pixel.

The source and destination image formats both consist of a header of a variable number of bytes(containing metadata such as the bytes per pixel etc) which is then followed by the Image data.

Don't know if relevant, but we're using a 40+ year old software (called Mcidas) to display these images Previously, I read both bytes into an unsigned short array. Then some bit manipulations concatenated them to a new unsigned short. I then use the fwrite() function to write them into the target file.

Edit
I'm now using fread() on data directly.

The read operation is working well (tried both fputc() and fread())

Edit
The image data part of hexdumps of the two files completely match. However, for some reason, the image seems to show a bit error in certain bytes. The source file seems to be clean, too.

Here's the Image (a 2MB file):
http://pdsimage.wr.usgs.gov/archive/mess-e_v_h-mdis-2-edr-rawdata-v1.0/MSGRMDS_1001/DATA/2007_156/EW0089565661F.IMG

You could save this as "source.IMG" to test it.

Below is a comparison of the source and final images, with a line scan done on the first line.

Source file and Image

Note the sudden jumps for certain pixels, that give rise to contours. These seem to be about 256 in length, which leads us to suspect that there might be a flip of bits somewhere(the sign bit maybe?). The identical hexdumps indicate otherwise however.

Here's the errant code:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
unsigned char data_arr[2];
unsigned short data;
data=0;
int pixel_per_line=1024;
char path1[80]="source.IMG";
char path[80]="destination"
fp=fopen(path1,"rb");
bin=fopen(path,"wb");
//fp points to the input file, bin to the output file.
fseek(fp,8193,SEEK_SET);//sets the pointer to the relevant byte in the source file. 
//A similar fseek() is used on bin in the original program
while(!feof(fp))
{
//fflush(fp); (Removed the fflush()s now)
int j;
for(j=0;j<pixels_per_line;j++)//iterate through all pixels in one line
        {
        for(int i=0;i<2;i++)
            data_arr[i]=fgetc(fp);
        //data=(data_arr[0] << 8) | data_arr[1];// bit manipulations done in the earlier version. 
        //This fails to give the right output.
         data=data_arr[0]*256 + data_arr[1]; // This switches alternate bytes. 
        if(fwrite(&data,1,sizeof(data),bin)!=2) 
            printf("Write pains!");
        }
//fflush(bin);
}
}

EDIT:

  1. Added the fopen() statements and tested with fflush() removed, the error remains.

  2. Added declaration for unsigned short data

  3. The code should run now.

EDIT

Problem solved for the 2 byte image! All I did was switch alternate bytes. Look at the corrected code. I am not sure why it works though. Is it an endianness issue? Note that bitshifts did not work.

I am having a similar problem for four byte images now. The data is stored as a floating point number. I fread() the bytes into a float, scale it and cast it into an integer. The results are similarly grainy. Permuting the bytes with bitshifts does not solve the problem.

Can anyone throw some light on this?

Community
  • 1
  • 1
Mihir Kulkarni
  • 171
  • 1
  • 1
  • 4
  • `fflush(fp);` is undefined behavior, you need to fix things like that before you can expect anything to work. Show how you're opening your files. – Crowman Jul 03 '14 at 01:51
  • `fwrite(&data,1,2,bin)` You have an unnecessary magic number there. Better to use `fwrite(&data,1,sizeof(data),bin)`. It's a small detail, but it shows the reader explicitly that you don't have a overwrite from misunderstanding the size and promotes maintainability in the future. – dmckee --- ex-moderator kitten Jul 03 '14 at 01:54
  • 5
    While `while(!feof(fp))` doesn't do what you think, either. It won't return true until `fgetc()` has already failed once. – Crowman Jul 03 '14 at 01:58
  • 1
    Related to what Paul Griffiths mentions: http://stackoverflow.com/questions/5431941/while-feof-file-is-always-wrong – mafso Jul 03 '14 at 02:14
  • Make sure you open the file in binary mode. Maybe not a coincidence that the first errant line is also the first line with `0d` on it – M.M Jul 03 '14 at 02:29
  • What is `pixels_per_line` – M.M Jul 03 '14 at 02:30
  • 2
    What is the desired result of the bit manipulations? I assume the problem is caused by sign extension on `fgetc()`. – humodz Jul 03 '14 at 02:31
  • `fflush()` was something I'd added while debugging a previous problem, the issue remains even when it's removed. – Mihir Kulkarni Jul 03 '14 at 16:55
  • I don't see any reason for "bit manipulations", as (apparently) you want to copy the image unchanged. Does the issue magically go away if you use `fread(&data,1,2,fp)` instead of manually concatenating bytes with `fgetc`? – Jongware Jul 03 '14 at 17:41
  • 1) Show declaration of `data`. 2) Is the input file unchangeable during the run of the program? Does your reading of it have an exclusive lock? – chux - Reinstate Monica Jul 03 '14 at 18:10
  • 1
    @humodz `fgetc()` returns an `int` in the range of `unsigned char` and `EOF`. (e.g. 0-255 and -1). Any sign extension issues would only occur if the value was saved in something longer than an `int`. – chux - Reinstate Monica Jul 03 '14 at 18:17
  • @Jongware, using `fread(&data,1,2,fp)` gives exactly the same output. @chux, I'm not using a lock here- can you tell me why I'd need one? There's only reading being done from the source file. – Mihir Kulkarni Jul 04 '14 at 01:48
  • 1
    Mihir, to get better help you need to post a [MVCE](http://stackoverflow.com/help/mcve) – M.M Jul 04 '14 at 01:52
  • EDIT: Using `fread(&data,1,2,fp)` *did* solve the problem. The hexdumps now match. However, the image still looks off. Problems with the display software? – Mihir Kulkarni Jul 04 '14 at 02:01
  • 1
    As @Matt McNabb said, without a MVCE, folks are left to guessing many issues not posted. It appears that `fread(&data,1,2,fp)` solves the issue, but I suspect something else was wrong that is also fixed. Best to post the MVCE. (Maybe a missing #include ?, `data_arr` mis-declaration, etc.?) – chux - Reinstate Monica Jul 04 '14 at 05:30
  • See edits. What's especially puzzling is that the hexdumps are identical. Could this be an issue with endianness? I am on a Linux system while the data has come from an IBM computer. However, such format conversions have been done multiple times in the past without any such issue. – Mihir Kulkarni Jul 10 '14 at 00:37

1 Answers1

0

Minor problem:

Do not use feof(fp), instead use:

while (1) {
  ...
  int ch = fgetc(fp);
  if (ch == EOF) break;
  data_arr[0] = ch;
  ch = fgetc(fp);
  if (ch == EOF) break;
  data_arr[1] = ch; 

Larger issue: I suspect your input file, though open as "rb" is changing as you read it. Perhaps you do not have an exclusive lock on it.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256