将 24 位".bmp"图像转换为黑白/单色图像的可能算法是什么?



我正在尝试将彩色24位深度图像转换为单色/blackandwhite image 。因此,有两个部分图像(即(标题(位图文件标头& dib标头(和像素数组

第一部分(标题(。在这里,将单色图像的标头计算为1 的代码,我是否可以计算出其他好方法?

int nBitmapImageWidth = pBMPstructure->fngetBitmapwidth();//Structure which returm the image width
int nRowSize = ((nBitmapImageWidth + 31) / 32) * 4;//Calculation of row size 
int nSizeRawBitmap = nRowSize * (pBMPstructure->fngetBitmapheight());
int nSizeBMP = nSizeRawBitmap + 62;
//Bitmap file header starts
bReadBuffer[0] = pBMPstructure->fngetFiletype();
bReadBuffer[2] = nSizeBMP;//Error Debugging
bReadBuffer[6] = pBMPstructure->fngetReserved1();
bReadBuffer[8] = pBMPstructure->fngetReserved2();
bReadBuffer[10] = 0x3E;
//Bitmap file header ends
//DIB Header starts
bReadBuffer[14] = 0x28;
bReadBuffer[18] = nBitmapImageWidth;
bReadBuffer[22] = pBMPstructure->fngetBitmapheight();
bReadBuffer[26] = pBMPstructure->fngetColorplanes(); bReadBuffer[28] = 1; 
bReadBuffer[30] = pBMPstructure->fngetCompressionmethod();
bReadBuffer[34] = nSizeRawBitmap;//Error Debugging
bReadBuffer[38] = pBMPstructure->fngetHorizontalresolution(); 
bReadBuffer[42] = pBMPstructure->fngetVerticalresolution();
bReadBuffer[46] = pBMPstructure->fngetColorpalette(); 
bReadBuffer[50] = pBMPstructure->fngetImportantcolors();
bReadBuffer[54] = 0x00; bReadBuffer[55] = 0x00; bReadBuffer[56] = 0x00; 
bReadBuffer[57] = 0x00;
bReadBuffer[58] = 0xff; bReadBuffer[59] = 0xff; 
bReadBuffer[60] = 0xff; bReadBuffer[61] = 0x00;
//DIB Header ends
//End of creating header for black and white

第二部分(像素阵列(。这里是计算像素数组的代码2 3 4。

//Calculation of pixel array for black and white image/Monochrome begins
            DWORD bsizeofBMP = pBMPstructure->fngetSizeBMP();
            bsizeofBMP -= obj_BMP.fnreturnOffsetpixelarray();
            int nSectors = (bsizeofBMP - obj_BMP.fnreturnOffsetpixelarray()) / nLineLengthColoured;
            int nFlagHeader = 1, nFlagPixelArray = 1;
            if (obj_file_to_read.fnCreate(argv[2], GENERIC_READ, OPEN_EXISTING) == FALSE)//Creating a handle to Source image file
            {
                dwErrCode = GetLastError();//Retriving the last error code
                _tprintf(_T("ntThe error message:-%wsn"), obj_error_handler.fngeterrordescription(dwErrCode));//Retriving error message
                _tprintf(_T("ntThe error code:-%d"), obj_error_handler.fngetErrCode());//Retriving error code
                _tprintf(_T("n---------------------------------------------------------------------------------------------"));
                return EXIT_FAILURE;
            }
            if (obj_file_to_write.fnCreate(argv[3], GENERIC_WRITE, CREATE_ALWAYS) == FALSE)//Craeting a handle to destination image file
            {
                dwErrCode = GetLastError();//Retriving the last error code
                _tprintf(_T("ntThe error message:-%ws"), obj_error_handler.fngeterrordescription(dwErrCode));//Retriving error message
                _tprintf(_T("ntThe error code:-%d"), obj_error_handler.fngetErrCode());//Retriving error code
                _tprintf(_T("n---------------------------------------------------------------------------------------------"));
                return EXIT_FAILURE;
            }
            while (nSectors)
            {
                if (nFlagHeader == 1)//So that pointer goes only one times inside this very code
                {
                    if (obj_file_to_write.fnWrite(bReadBuffer, 62) == FALSE)//To write HEADERS to destination file
                    {
                        obj_file_to_write.fnClose();//Closing the handle opened for writing to the file
                        dwErrCode = GetLastError();//Retriving the last error code
                        _tprintf(_T("ntThe error message:-%wsn"), obj_error_handler.fngeterrordescription(dwErrCode));//Retriving error message
                        _tprintf(_T("ntThe error code:-%d"), obj_error_handler.fngetErrCode());//Retriving error code
                        return EXIT_FAILURE;
                    }
                    --nFlagHeader;
                }
                BYTE bNewReadBuffer[4096] = { 0 };//Creating a new array to load one line of source file
                if (nFlagPixelArray == 1)//For first iteration need to set the file pointer to after both headers so that it is not overwritten
                {
                    DWORD dwptr = SetFilePointer(obj_file_to_read.fnGetHandle(), obj_BMP.fnreturnOffsetpixelarray(), NULL, FILE_BEGIN);//SetFilePointer WinAPI
                    if (dwptr == INVALID_SET_FILE_POINTER)//Check if it is pointing to the desired or giving some garbage value
                    {
                        dwErrCode = GetLastError();//Retriving the last error code
                        _tprintf(_T("ntThe error message:-%wsn"), obj_error_handler.fngeterrordescription(dwErrCode));//Retriving error message
                        _tprintf(_T("ntThe error code:-%d"), obj_error_handler.fngetErrCode());//Retriving error code
                        return EXIT_FAILURE;
                    }
                    --nFlagPixelArray;//Decrementing so that it will no enter in this part of code
                }
                if (obj_file_to_read.fnRead(bNewReadBuffer, nLineLengthColoured) == FALSE)
                {
                    obj_file_to_read.fnClose();
                    obj_file_to_write.fnClose();
                    dwErrCode = GetLastError();//Retriving the last error code
                    _tprintf(_T("ntThe error message:-%wsn"), obj_error_handler.fngeterrordescription(dwErrCode));
                    _tprintf(_T("ntThe error code:-%d"), obj_error_handler.fngetErrCode());//Retriving error code
                    _tprintf(_T("n---------------------------------------------------------------------------------------------"));
                    return EXIT_FAILURE;
                }
                BYTE bMonoBuffer[128] = { 0 };//It is the buffer which is made for storing single line of black and white image
                int nMonoBytes = ((nLineLengthColoured - nPaddingColoured) / 3) / (nLineLengthBlackAndWhite - nPaddingBlackAndWhite);//3 is BGR values and calculating rthe sectors
                int nMonoAdditional = ((nLineLengthColoured - nPaddingColoured) / 3) % (nLineLengthBlackAndWhite - nPaddingBlackAndWhite);//Calculating the additional bytes which is remaining after calculating the sectors
                int nIteratorbNewReadBuffer = 0;
                while (nMonoBytes)//nMonoBytes specifies how many times will the bMonoBuffer will be filled
                {
                    for (int i = 0; i < (nLineLengthBlackAndWhite - nPaddingBlackAndWhite); i++)//Loop started for the amount of 1 line which is to be feeded inside the monochrome image
                    {
                        bMonoBuffer[i] = (bNewReadBuffer[nIteratorbNewReadBuffer] + bNewReadBuffer[nIteratorbNewReadBuffer + 1] + bNewReadBuffer[nIteratorbNewReadBuffer + 2]) / 3;//Algorithm for conversion from bgr value to monochrome/black ad white i.e the average of all the three value
                        nIteratorbNewReadBuffer += 3;//Incrementing the iterator for bNewReadBuffer which is containg one single line of coloured BMP
                    }
                    if (nPaddingBlackAndWhite != 0)//if padding of black and whiote is not zero
                    {
                        for (int i = (nLineLengthBlackAndWhite - nPaddingBlackAndWhite); i < nLineLengthBlackAndWhite; i++)//from the position where data of black and white image ends   
                        {
                            bMonoBuffer[i] = 00;
                        }
                    }
                    if (obj_file_to_write.fnWrite(bMonoBuffer, nLineLengthBlackAndWhite) == FALSE)
                    {
                        obj_file_to_read.fnClose();
                        obj_file_to_write.fnClose();
                        dwErrCode = GetLastError();//Retriving the last error code
                        _tprintf(_T("ntThe error message:-%wsn"), obj_error_handler.fngeterrordescription(dwErrCode));//Retriving error message
                        _tprintf(_T("ntThe error code:-%d"), obj_error_handler.fngetErrCode());//Retriving error code
                        _tprintf(_T("n---------------------------------------------------------------------------------------------"));
                        return EXIT_FAILURE;
                    }
                    nMonoBytes--;
                }
                if (nMonoAdditional != 0)//The remaining bytes
                {//Problem here is that the last remaining bytes will be of certain bytes and will be copied to destination but when next iteration starts it will continue 
                    //to convert the whole line for monobytes instead it should be the new bytes have to be readed minus the additional one already readed..
                    for (int i = 0; i < nMonoAdditional; i++)
                    {
                        bMonoBuffer[i] = (bNewReadBuffer[nIteratorbNewReadBuffer] + bNewReadBuffer[nIteratorbNewReadBuffer + 1] + bNewReadBuffer[nIteratorbNewReadBuffer + 2]) / 3;
                    }
                    nMonoAdditional--;
                }
                nSectors--;
            }

例如(.bmp image(

假设有大小的彩色图像 1,131,654字节,并且众所周知, 54个字节将是 headers 小。当我从图像大小中减去标头零件时,彩色的像素阵列大小为 1,131,600字节,并且可以进行一些 padding bytes ,让假设有色的填充是3个字节和一行彩色图像的长度为 2460字节,图像中的总线将为 460行。所需的图像是单色图像> 104字节和填充字节的线元素是 2个字节 ..,将有 2457/3 = 819 BGR Pairs 表示如果我将每对写入所需的文件(即黑色和白色(,那么它将采用 819 Pairs * 460行= 3,76,740字节,但所需的文件应为 47,840 62 = 47,902 size !!

  1. 首先,在1图中调试389和399的错误。如果是的,有什么比这更好的方法?
  2. 第二件事第二,这里的问题是剩下的字节将是一定的字节,并且将被复制到目的地,但是当下一个迭代开始时,它将继续转换单循环的整个行,而应该是新字节必须是新字节被读取减去已经读过的其他一个。
  3. 除了平均少于黑白外,什么是将颜色转换为黑白的算法。

预先感谢

好吧,这里有很多问题,由于缺乏上下文,其中大多数是无法回答的。我唯一可以回答的是为什么您的图像数据大小为376,740字节,而不是47,840字节。

376,740字节与每个像素1个字节(= 8位(的819x460单色/灰度图像一致。但是,当我们谈论"黑白"图像时,我们通常是指每个像素的1 。每行819位为我们提供819/8 = 102.375字节每扫描线。每次扫描线上获得104个字节,均达到了偶数的字节。乘以460个扫描线,我们获得了47,840字节的图像数据。

最新更新