MagickCore WriteImage sometimes writes grayscale images as RGB files

Questions and postings pertaining to the development of ImageMagick, feature enhancements, and ImageMagick internals. ImageMagick source code and algorithms are discussed here. Usage questions which are too arcane for the normal user list should also be posted here.
Post Reply
epirwoz
Posts: 1
Joined: 2017-11-03T09:37:15-07:00
Authentication code: 1152

MagickCore WriteImage sometimes writes grayscale images as RGB files

Post by epirwoz »

I'm using (ImageMagick 7.0.7-8 Q16 x64) MagickCore functions to write a buffer containing a 16 bpp grayscale image to file, e.g., PNG, BMP. This sometimes results in the file containing a 1-channel grayscale image and other times a 3-channel RGB image, but I'd like it to always result in a 1-channel grayscale image. The code below illustrates this issue. Example input and corresponding output files can be found here: https://cseweb.ucsd.edu/~bochoa/private/magick/ input1.png is read as a grayscale image, then written to output1.png, which contains an RGB image (not desired). However, input2.png is also read as a grayscale image, then written to output2.png, which contains a grayscale image (desired). Are there any ImageInfo or Image parameters that must be set to ensure that WriteImage() always writes a 1-channel grayscale image?

Code: Select all

int main( int argc, char *argv[] )
{
    if ( 3 > argc )
    {
        return 1;
    }
    const char* infilename  = argv[1];
    const char* outfilename = argv[2];

    // Read image
    ImageInfo* pimageinfo = AcquireImageInfo();
    GetImageInfo( pimageinfo );
    strncpy( pimageinfo->filename, infilename, MaxTextExtent - 1 );
    ExceptionInfo* pexceptioninfo = AcquireExceptionInfo();
    Image* pimage = ReadImage( pimageinfo, pexceptioninfo );
    // Image buffer
    const size_t rows    = pimage->rows;
    const size_t columns = pimage->columns;
    uint16_t* pData = (uint16_t*) malloc( rows * columns * 2 );
    // Copy ImageMagick image to the destination buffer
    QuantumInfo quantuminfo;
    GetQuantumInfo( pimageinfo, &quantuminfo );
    quantuminfo.depth  = 16;
    quantuminfo.endian = LSBEndian;
    const Quantum* pquantum = 0;
    for ( int y = 0; y < rows; ++y )
    {
        pquantum = GetVirtualPixels( pimage, 0, y, columns, 1, pexceptioninfo );
        ExportQuantumPixels( pimage, 0, &quantuminfo, GrayQuantum, 
            (unsigned char*)( pData + y * columns ), pexceptioninfo );
    }
    // Completely clean up
    DestroyImage( pimage );
    pimage = 0;
    DestroyExceptionInfo( pexceptioninfo );
    pexceptioninfo = 0;
    DestroyImageInfo( pimageinfo );
    pimageinfo = 0;

    // Write image
    pimageinfo = AcquireImageInfo();
    GetImageInfo( pimageinfo );
    strncpy( pimageinfo->filename, outfilename, MaxTextExtent - 1 );
    pimageinfo->depth  = 16;
    pimageinfo->endian = LSBEndian;
    pimageinfo->type   = GrayscaleType;
    pexceptioninfo = AcquireExceptionInfo();
    pimage = AcquireImage( pimageinfo, pexceptioninfo );
    pimage->columns = columns;
    pimage->rows    = rows;
    pimage->depth   = 16;
    SetImageType( pimage, pimageinfo->type, pexceptioninfo );
    // Copy source buffer to the ImageMagick image
    QuantumInfo* pquantuminfo = AcquireQuantumInfo( pimageinfo, pimage );
    pquantum = 0;
    for ( int y = 0; y < rows; ++y )
    {
        pquantum = GetAuthenticPixels( pimage, 0, y, columns, 1, 
            pexceptioninfo );
        ImportQuantumPixels( pimage, 0, pquantuminfo, GrayQuantum, 
            (unsigned char*)( pData + y * columns ), pexceptioninfo );
    }
    DestroyQuantumInfo( pquantuminfo );

    WriteImage( pimageinfo, pimage, pexceptioninfo );
    DestroyImage( pimage );
    DestroyExceptionInfo( pexceptioninfo );
    DestroyImageInfo( pimageinfo );

    free( pData );

    return 0;
}
Post Reply