• BMP format: trying to make the color of the image more saturated

    From modelling.data@gmail.com@21:1/5 to All on Mon Jan 18 06:46:12 2016
    Hello!

    I am doing a free online course, and one of the exercises offers
    a code that copies a given file and then writes it into another
    file. The original file have a picture of a face covered by red
    pixels. The task is to remove the red color by changing all pixels
    with that are 0000ff into ffffff (into white ones). I have managed
    to achieve this because it is a very straightforward task.

    But the image I see is very blurred and is in light blue color. Hence
    I have tried to make the blue color more saturated by changing the value of pixels that have the value of red != ff. I have decided to do that after checking the information on pixels by xxd.

    Please, take a look at the program (it is written by the course staff). I am highlighting the piece of code that is supposed to change only certain
    blue pixels to saturated blue. Obviously I am doing something wrong, most likely I am interpreting the result of xxd command correctly.

    This piece of code make the whole picture a mixture of blue and white.
    Please, explain where I can read the information on how to handle these
    issues correctly, and please do not simply solve the problem for me - but
    I will be grateful for helpful hints and explanations.

    if (triple.rgbtRed != 0xff)
    {
    triple.rgbtRed = 0x0a;
    triple.rgbtGreen = 0x84;
    }

    Program:
    /*
    * Copies a BMP piece by piece.
    */

    #include <stdio.h>
    #include <stdlib.h>

    #include "bmp.h"

    int main(int argc, char* argv[])
    {
    // ensure proper usage
    if (argc != 3)
    {
    printf("Usage: ./copy infile outfile\n");
    return 1;
    }

    // remember filenames
    char* infile = argv[1];
    char* outfile = argv[2];

    // open input file
    FILE* inptr = fopen(infile, "r");
    if (inptr == NULL)
    {
    printf("Could not open %s.\n", infile);
    return 2;
    }

    // open output file
    FILE* outptr = fopen(outfile, "w");
    if (outptr == NULL)
    {
    fclose(inptr);
    fprintf(stderr, "Could not create %s.\n", outfile);
    return 3;
    }

    // read infile's BITMAPFILEHEADER
    BITMAPFILEHEADER bf;
    fread(&bf, sizeof(BITMAPFILEHEADER), 1, inptr);

    // read infile's BITMAPINFOHEADER
    BITMAPINFOHEADER bi;
    fread(&bi, sizeof(BITMAPINFOHEADER), 1, inptr);

    // ensure infile is (likely) a 24-bit uncompressed BMP 4.0
    if (bf.bfType != 0x4d42 || bf.bfOffBits != 54 || bi.biSize != 40 ||
    bi.biBitCount != 24 || bi.biCompression != 0)
    {
    fclose(outptr);
    fclose(inptr);
    fprintf(stderr, "Unsupported file format.\n");
    return 4;
    }

    // write outfile's BITMAPFILEHEADER
    fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, outptr);

    // write outfile's BITMAPINFOHEADER
    fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, outptr);

    // determine padding for scanlines
    int padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

    // iterate over infile's scanlines
    for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
    {
    // iterate over pixels in scanline
    for (int j = 0; j < bi.biWidth; j++)
    {
    // temporary storage
    RGBTRIPLE triple;

    // read RGB triple from infile
    fread(&triple, sizeof(RGBTRIPLE), 1, inptr);

    if (triple.rgbtRed == 0xff && triple.rgbtBlue == 0x00 && triple.rgbtGreen == 0x00)
    {
    triple.rgbtBlue = 0xff;
    triple.rgbtGreen = 0xff;
    }

    /*** THIS PIECE DOESN'T WORK CORRECTLY ***/
    if (triple.rgbtRed != 0xff)
    {
    triple.rgbtRed = 0x0a;
    triple.rgbtGreen = 0x84;
    }

    // write RGB triple to outfile
    fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
    }

    // skip over padding, if any
    fseek(inptr, padding, SEEK_CUR);

    // then add it back (to demonstrate how)
    for (int k = 0; k < padding; k++)
    {
    fputc(0x00, outptr);
    }
    }

    // close infile
    fclose(inptr);

    // close outfile
    fclose(outptr);

    // that's all folks
    return 0;
    }

    bmp.h
    #include <stdint.h>

    /**
    * Common Data Types
    *
    * The data types in this section are essentially aliases for C/C++
    * primitive data types.
    *
    * Adapted from http://msdn.microsoft.com/en-us/library/cc230309.aspx.
    * See http://en.wikipedia.org/wiki/Stdint.h for more on stdint.h.
    */
    typedef uint8_t BYTE;
    typedef uint32_t DWORD;
    typedef int32_t LONG;
    typedef uint16_t WORD;

    /**
    * BITMAPFILEHEADER
    *
    * The BITMAPFILEHEADER structure contains information about the type, size,
    * and layout of a file that contains a DIB [device-independent bitmap].
    *
    * Adapted from http://msdn.microsoft.com/en-us/library/dd183374(VS.85).aspx.
    */
    typedef struct
    {
    WORD bfType;
    DWORD bfSize;
    WORD bfReserved1;
    WORD bfReserved2;
    DWORD bfOffBits;
    } __attribute__((__packed__))
    BITMAPFILEHEADER;

    /**
    * BITMAPINFOHEADER
    *
    * The BITMAPINFOHEADER structure contains information about the
    * dimensions and color format of a DIB [device-independent bitmap].
    *
    * Adapted from http://msdn.microsoft.com/en-us/library/dd183376(VS.85).aspx.
    */
    typedef struct
    {
    DWORD biSize;
    LONG biWidth;
    LONG biHeight;
    WORD biPlanes;
    WORD biBitCount;
    DWORD biCompression;
    DWORD biSizeImage;
    LONG biXPelsPerMeter;
    LONG biYPelsPerMeter;
    DWORD biClrUsed;
    DWORD biClrImportant;
    } __attribute__((__packed__))
    BITMAPINFOHEADER;

    /**
    * RGBTRIPLE
    *
    * This structure describes a color consisting of relative intensities of
    * red, green, and blue.
    *
    * Adapted from http://msdn.microsoft.com/en-us/library/aa922590.aspx.
    */
    typedef struct
    {
    BYTE rgbtBlue;
    BYTE rgbtGreen;
    BYTE rgbtRed;
    } __attribute__((__packed__))
    RGBTRIPLE;

    Results of xxd:

    1) after I have taken away red "noise"
    $ xxd -l240 -c24 -g3 -s54 verdict_fin0.bmp
    0000036: ffffff ffff88 ffff82 ffff83 ffffff ffff81 ffff83 ffff82 ........................
    000004e: feff7c ffff83 ffffff ffffff ffffff ffffff ffff83 ffffff ..|.....................
    0000066: ffffff ffff83 ffff88 feff8a ffff83 feff7d ffffff ffffff .................}......
    000007e: ffffff ffff83 ffffff ffff88 ffff88 ffffff ffffff ffffff ........................
    0000096: ffff88 ffff83 ffff88 ffff83 ffff88 ffff7f feff8a ffffff ........................
    00000ae: ffffff ffffff ffff88 ffffff ffff8c ffffff ffff88 feff8a ........................
    00000c6: ffffff ffffff ffff88 ffffff feff8a ffffff feff8e ffff88 ........................
    00000de: ffffff ffffff ffffff ffffff ffff88 ffffff ffffff ffff7b .......................{
    00000f6: feff82 fefe82 ffffff ffffff ffffff ffff83 ffffff ffffff ........................
    000010e: ffffff ffffff ffff88 ffffff ffffff ffff88 ffff88 ffffff ........................

    2) after the attempt to make blue more saturated

    0000036: ffffff ff840a ff840a ff840a ffffff ff840a ff840a ff840a ........................
    000004e: fe840a ff840a ffffff ffffff ffffff ffffff ff840a ffffff ........................
    0000066: ffffff ff840a ff840a fe840a ff840a fe840a ffffff ffffff ........................
    000007e: ffffff ff840a ffffff ff840a ff840a ffffff ffffff ffffff ........................
    0000096: ff840a ff840a ff840a ff840a ff840a ff840a fe840a ffffff ........................
    00000ae: ffffff ffffff ff840a ffffff ff840a ffffff ff840a fe840a ........................
    00000c6: ffffff ffffff ff840a ffffff fe840a ffffff fe840a ff840a ........................
    00000de: ffffff ffffff ffffff ffffff ff840a ffffff ffffff ff840a ........................
    00000f6: fe840a fe840a ffffff ffffff ffffff ff840a ffffff ffffff ........................
    000010e: ffffff ffffff ff840a ffffff ffffff ff840a ff840a ffffff ........................

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)