2

I'm using fwrite to write a file (it's an image).

First, I'm writing a header that has a fixed size

int num_meta_write_bytes = fwrite(headerBuffer, 1, headerSize, file);

This works OK

Then I have to write the pixels:

num_write_bytes = fwrite(data_pointer, 1, image_size, file);

This works OK

For my case, I have to write a variable number of zeros between the header and the pixels, the (ugly?) solution I found is:

for (size_t i = 0; i < padding_zeros; i++) //padding_zeros is calculated in runtime
{
    uint8_t zero = 0;
    num_meta_write_bytes += fwrite(&zero, 1, sizeof(uint8_t), fp);
}

(This code is placed before writing the pixels)

My question is: is there a way to directly tell fwrite to continously write the same value padding_zeros times? instead of using this for loop?

Ivan
  • 1,352
  • 2
  • 13
  • 31
  • 4
    Remember that in C (since the C99 standard) you can define [variable-length arrays](https://en.wikipedia.org/wiki/Variable-length_array). You could define such an array of the exact size, `memset` it to zero, and write it in a single call to `fwrite`. – Some programmer dude Mar 16 '22 at 11:00
  • What does the padding depend on? Why does it have to be calculated in runtime? Sounds a bit strange to me. – Aconcagua Mar 16 '22 at 11:02
  • @Aconcagua our app works with several different cameras, the padding depends on the camera resolution and it's pixel depth – Ivan Mar 16 '22 at 11:03
  • @Someprogrammerdude I'll try this :) – Ivan Mar 16 '22 at 11:04
  • 1
    Also, some filesystems support *holes* in files. So you could try to just seek over the padding area and start writing the data. When read, the hole should be read as zeros. – Some programmer dude Mar 16 '22 at 11:05
  • I cannot imagine how padding would help to solve this problem. When reading images back, how do you know that there are padding bytes? Why wouldn't you interprete these paddings as part of the image? *If* you know that these bytes are padding anyway, you don't need to include them right from the start. – Aconcagua Mar 16 '22 at 11:10
  • @Aconcagua this is a bit out of the question scope, but FYI :) I'm saving a raw image and the software we use has no way of knowing where the header starts or ends (for displaying). So we are actually displaying the header (which leads to ugly pixels) . Here the padding is necessary due to the fact that the header size might not be a multiple of the image's width, which results in a shifted image in the display software. – Ivan Mar 16 '22 at 13:12
  • 1
    @Ivan *'out of scope'* is a relative – you might have presented an [XY-problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) and for the true problem there might be a better solution, but we can only hint to if we know what you *actually* intend to do – which is why I've been asking. Still wondering how you or this software handles different image sizes and color depths (maybe scaling all images to the same format...), but that might finally really go out of scope here... – Aconcagua Mar 16 '22 at 15:56

2 Answers2

6

You can create a zero-filled block of data with calloc(), then write that data to the file in one call (and remember to free the data afterwards):

uint8_t* zeros = calloc(padding_zeros, sizeof(uint8_t));
if (zeros) {
    num_meta_write_bytes += fwrite(zeros, sizeof(uint8_t), padding_zeros, fp);
    free(zeros);
}
else {
    // Error handling, or use your 'loop' method if calloc fails
}

As mentioned in the comments, you could also use a variable length array; however, VLAs are an 'optional' feature in C (since the C11 Standard), and you would anyway have to explicitly set the data to zeros (with a call to memset), as VLAs cannot be initialized like ordinary (fixed-size) arrays.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
1

I found another solution, althouht I think is OS dependent:

fseek(fp, padding_zeros, SEEK_CUR);

This is quite fast as there is no allocation. Just when copying the resulting file, the OS will generate the actual zeros.

This worked fine in my linux target.

Ivan
  • 1,352
  • 2
  • 13
  • 31