Page 1 of 1

MagickCore WriteImage sometimes writes grayscale images as RGB files

Posted: 2017-11-03T10:07:49-07:00
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;
}