views:

139

answers:

5

Hi - I'm trying to read an image file and scale it by multiplying each byte by a scale its pixel levels by some absolute factor. I'm not sure I'm doing it right, though -

void scale_file(char *infile, char *outfile, float scale)
{
    // open files for reading
    FILE *infile_p = fopen(infile, 'r');
    FILE *outfile_p = fopen(outfile, 'w');

    // init data holders
    char *data;
    char *scaled_data;

    // read each byte, scale and write back
    while ( fread(&data, 1, 1, infile_p) != EOF )
    {
        *scaled_data = (*data) * scale;
        fwrite(&scaled_data, 1, 1, outfile);
    }

    // close files
    fclose(infile_p);
    fclose(outfile_p);
}

What gets me is how to do each byte multiplication (scale is 0-1.0 float) - I'm pretty sure I'm either reading it wrong or missing something big. Also, data is assumed to be unsigned (0-255). Please don't judge my poor code :)

thanks

+3  A: 
char *data;
char *scaled_data;

No memory was allocated for these pointers - why do you need them as pointers? unsigned char variables will be just fine (unsigned because it makes more sense for byte data).

Also, what happens when the scale shoots the value out of the 256-range? Do you want saturation, wrapping, or what?

Eli Bendersky
If it overshoots I'll clip it at 255, though since it's on a scale of 0-1.0, it probably wont. Still, you're right - it doesn't hurt checking.
sa125
@sa125: currently there's no clipping in your code, however
Eli Bendersky
+1  A: 

why you think you are wrong, i see nothing wrong in your algorithm except for not being efficient and char *data; and char *scaled_data; should be unsigned char data; and unsigned char scaled_data;

uray
+1  A: 

My understanding of a bitmap (just the raw data) is that each pixle is represented by three numbers one each for RGB; multiplying each by a number <=1 would just make the image darker. If you're trying to make the image wider, you could maby just output each pixle twice (to double the size), or just output every other pixel (to halve the size), but that depends on how its rasterized.

RyanD
each pixel twice would only double width or height (depending if you repeated pixels or rows), you need to both repeat each pixel and repeat each row to double the size (and for that of course you need to know the row size).
Justin Smith
+2  A: 
  1. change char *scaled_data; to char scaled_data;
  2. change *scaled_data = (*data) * scale; to scaled_data = (*data) * scale;

That would get you code that would do what you are trying to do, but ....

This could only possibly work on an image file of your own custom format. There is no standard image format that just dumps pixels in bytes in a file in sequential order. Image files need to know more information, like

  1. The height and width of the image
  2. How pixels are represented (1 byte gray, 3 bytes color, etc)
  3. If pixels are represented as an index into a palette, they have the palette
  4. All kinds of other information (GPS coordinates, the software that created it, the date it was created, etc)
  5. The method of compression used for the pixels

All of this is called Meta-data

In addition (as alluded to by #5), pixel data is usually compressed.

Lou Franco
+2  A: 

You're code is equivalent to saying "I want to scale down my image by dividing the bits in half"; it doesn't make any sense.

Images files are complex formats with headers and fields and all sorts of fun stuff that needs to be interpreted. Take nobugz's advice and check out ImageMagick. It's a library for doing exactly the kind of thing you want.

jdizzle