Repository: opencv/opencv
File: modules/imgcodecs/src/grfmt_bmp.cpp (C++)

Code before:
            if( m_width > 0 && m_height != 0 &&
               (m_bpp == 1 || m_bpp == 4 || m_bpp == 8 ||
                m_bpp == 24 || m_bpp == 32 ))
            {
                if( m_bpp <= 8 )
                {
                    uchar buffer[256*3];
                    int j, clrused = 1 << m_bpp;
                    m_strm.getBytes( buffer, clrused*3 );
                    for( j = 0; j < clrused; j++ )
                    {
                        m_palette[j].b = buffer[3*j+0];
                        m_palette[j].g = buffer[3*j+1];
                        m_palette[j].r = buffer[3*j+2];
                    }
                }
                result = true;
            }
        }
    }
    catch(...)
    {
        throw;
    }
    // in 32 bit case alpha channel is used - so require CV_8UC4 type
    m_type = iscolor ? (m_bpp == 32 ? CV_8UC4 : CV_8UC3 ) : CV_8UC1;
    m_origin = m_height > 0 ? ORIGIN_BL : ORIGIN_TL;
    if ( m_height == std::numeric_limits<int>::min() ) {
        // abs(std::numeric_limits<int>::min()) is undefined behavior.
        result = false;
    } else {
        m_height = std::abs(m_height);
    }

    if( !result )
    {
        m_offset = -1;
        m_width = m_height = -1;
        m_strm.close();
    }
    return result;
}


bool  BmpDecoder::readData( Mat& img )
{
    uchar* data = img.ptr();
    int step = validateToInt(img.step);
    bool color = img.channels() > 1;
    uchar  gray_palette[256] = {0};
    bool   result = false;

Review comment (suggestion):
According to the documentation (32-bit section of the table):

> The bitmap has a maximum of 2^32 colors. If the bV5Compression member of the BITMAPV5HEADER is BI_RGB, the bmiColors member of [BITMAPINFO](https://learn.microsoft.com/en-us/windows/desktop/api/wingdi/ns-wingdi-bitmapinfo) is NULL. Each DWORD in the bitmap array represents the relative intensities of blue, green, and red for a pixel. The value for blue is in the least significant 8 bits, followed by 8 bits each for green and red. The high byte in each DWORD is not used. The bmiColors color table is used for optimizing colors used on palette-based devices, and must contain the number of entries specified by the bV5ClrUsed member of the BITMAPV5HEADER.If the bV5Compression member of the BITMAPV5HEADER is BI_BITFIELDS, the bmiColors member contains three DWORD color masks that specify the red, green, and blue components of each pixel. Each DWORD in the bitmap array represents a single pixel.

The bitmap with BMP_RGB flag and 32-bit per channel is 3 channel image. The high byte is not used.
I propose to revert imread changes and corresponding test.
Images with BI_RBG/BMP_RGB should be 3 channel images.
Images with BI_BITFIELD/RGB_BITFIELD - 4 channel images.

Code after:
            if( m_width > 0 && m_height != 0 &&
               (m_bpp == 1 || m_bpp == 4 || m_bpp == 8 ||
                m_bpp == 24 || m_bpp == 32 ))
            {
                if( m_bpp <= 8 )
                {
                    uchar buffer[256*3];
                    int j, clrused = 1 << m_bpp;
                    m_strm.getBytes( buffer, clrused*3 );
                    for( j = 0; j < clrused; j++ )
                    {
                        m_palette[j].b = buffer[3*j+0];
                        m_palette[j].g = buffer[3*j+1];
                        m_palette[j].r = buffer[3*j+2];
                    }
                }
                result = true;
            }
        }
    }
    catch(...)
    {
        throw;
    }
    // in 32 bit case alpha channel is used - so require CV_8UC4 type
    m_type = iscolor ? ((m_bpp == 32 && m_rle_code != BMP_RGB) ? CV_8UC4 : CV_8UC3 ) : CV_8UC1;
    m_origin = m_height > 0 ? ORIGIN_BL : ORIGIN_TL;
    if ( m_height == std::numeric_limits<int>::min() ) {
        // abs(std::numeric_limits<int>::min()) is undefined behavior.
        result = false;
    } else {
        m_height = std::abs(m_height);
    }

    if( !result )
    {
        m_offset = -1;
        m_width = m_height = -1;
        m_strm.close();
    }
    return result;
}


bool  BmpDecoder::readData( Mat& img )
{
    uchar* data = img.ptr();
    int step = validateToInt(img.step);
    bool color = img.channels() > 1;
    uchar  gray_palette[256] = {0};
    bool   result = false;