1 | initial version |
MFC requires DWORD
memory alignment for bitmaps. Than cv::Mat mat
must be continuous (no ROI nor sparse) and mat.cols % 4 = 0
. In case could use this:
Mat mat;
mat=imread("aaa.bmp");
//really you could avoid this because is done by MFC StretchDIBits
//resize(mat,mat,cv::Size(rc.Width(),rc.Height()));
int x=mat.cols;
int y=mat.rows;
int padding = 4 - (x % 4);
if(padding==4)
padding = 0;
cv::Mat matTmp;
if (padding > 0 || mat.isContinuous() == false)
{
// Adding needed columns on the right (max 3 px)
cv::copyMakeBorder(mat, matTmp, 0, 0, 0, padding, cv::BORDER_CONSTANT, 0);
}
else
{
matTmp = mat;
}
Now you have right memory shape for a MFC bitmap. You can draw it avoiding the border using:
//real cols in the bitmap header
pheader->biWidth = matTmp.cols;
//wanted cols (original cols) for drawing
StretchDIBits( dc.GetSafeHdc()
,0, 0, rc.Width(), rc.Height()
,0, 0, x, y,
matTmp.data, &bmi, DIB_RGB_COLORS, SRCCOPY);
Finally your code will not work in case the image is grey scale because you need to prepare right palette in BITMAPINFOHEADER
2 | No.2 Revision |
MFC requires DWORD
memory alignment for bitmaps. Than bitmaps rows , than cv::Mat mat
must be continuous be:
mat.cols (bpp * mat.cols) % 4 == 0
. Looking at How the image matrix is stored in the memory? you can see that for a cv::Mat BytesForRows = bpp * mat.cols
where bpp
is number of byte for each pixel.
Definitely you should have cols as multiple of 4: cols % 4 == 0
. In case could use this:This is fine for GRAY and RGB images because 4colsbpp is always a multiple of 4 than DWORD aligned on rows.
here the code:
Mat mat;
mat=imread("aaa.bmp");
if ( mat.type() == CV_8UC1 ) {
cout << "not working because a greyscale palette is needed";
return;
}
else if ((mat.type() != CV_8UC3) && (mat.type() != CV_8UC4)) {
cout << "image type not supported";
return;
}
//really you could avoid this because is done by MFC StretchDIBits
//resize(mat,mat,cv::Size(rc.Width(),rc.Height()));
int x=mat.cols;
int y=mat.rows;
int padding = 0;
if (mat.type() != CV_8UC4) // padding is not needed for 32bit images
{
padding = 4 - (x % 4);
if(padding==4)
if(padding==4 || )
padding = 0;
}
cv::Mat matTmp;
if (padding > 0 || mat.isContinuous() == false)
{
// Adding needed columns on the right (max 3 px)
cv::copyMakeBorder(mat, matTmp, 0, 0, 0, padding, cv::BORDER_CONSTANT, 0);
}
else
{
matTmp = mat;
}
Now you have right memory shape for a MFC bitmap. You can draw it avoiding the border using:
//real cols in the bitmap header
pheader->biWidth = matTmp.cols;
//wanted cols (original cols) for drawing
StretchDIBits( dc.GetSafeHdc()
,0, 0, rc.Width(), rc.Height()
,0, 0, x, y,
matTmp.data, &bmi, DIB_RGB_COLORS, SRCCOPY);
Finally your code will not work in case the image is grey scale because you need to prepare right palette in BITMAPINFOHEADER
3 | No.3 Revision |
MFC requires DWORD
memory alignment for bitmaps rows , than cv::Mat mat
must be:
(bpp * mat.cols) % 4 == 0
. Looking at How the image matrix is stored in the memory? you can see that for a cv::Mat BytesForRows = bpp * mat.cols
where bpp
is number of byte for each pixel.
Definitely you should have cols as multiple of 4: cols % 4 == 0
. This is fine for GRAY and RGB images because 4colsbpp is always a multiple of 4 than DWORD aligned on rows.
here the code:
Mat mat;
mat=imread("aaa.bmp");
if ( mat.type() == CV_8UC1 ) {
cout << "not working because a greyscale palette is needed";
return;
}
else if ((mat.type() != CV_8UC3) && (mat.type() != CV_8UC4)) {
cout << "image type not supported";
return;
}
//really you could avoid this because is done by MFC StretchDIBits
//resize(mat,mat,cv::Size(rc.Width(),rc.Height()));
int x=mat.cols;
int y=mat.rows;
int padding = 0;
if (mat.type() != CV_8UC4) // padding is not needed for 32bit images
{
padding = 4 - (x % 4);
if(padding==4 || )
if(padding==4)
padding = 0;
}
cv::Mat matTmp;
if (padding > 0 || mat.isContinuous() == false)
{
// Adding needed columns on the right (max 3 px)
cv::copyMakeBorder(mat, matTmp, 0, 0, 0, padding, cv::BORDER_CONSTANT, 0);
}
else
{
matTmp = mat;
}
Now you have right memory shape for a MFC bitmap. You can draw it avoiding the border using:
//real cols in the bitmap header
pheader->biWidth = matTmp.cols;
//wanted cols (original cols) for drawing
StretchDIBits( dc.GetSafeHdc()
,0, 0, rc.Width(), rc.Height()
,0, 0, x, y,
matTmp.data, &bmi, DIB_RGB_COLORS, SRCCOPY);
Finally your code will not work in case the image is grey scale because you need to prepare right palette in BITMAPINFOHEADER
4 | No.4 Revision |
DWORD
memory alignment for bitmaps rows Than
cv::Mat mat
must be: cv::cvtColor
(bpp * mat.cols) % 4 == 0
. cv::copyMakeBorder
or cv::cvtColor
Looking If the image is not continuous (eg is a ROI) you should use in-place operation with care because it would be not continuous again.
About memory alignment, looking at How the image matrix is stored in the memory? you can see that for a cv::Mat BytesForRows = bpp * mat.cols
where bpp
is number of byte for each pixel.
Definitely you should have 32bit image or image cols as multiple of 4: cols % 4 == 0
. This is fine for GRAY and RGB images because 4colsbpp is always a multiple of 4 than DWORD aligned on rows.
here the code:
Mat mat;
mat=imread("aaa.bmp");
if ( mat.type() == CV_8UC1 ) {
cout << "not working because a greyscale palette is needed";
needed or you could use cv::cvtColor";
return;
}
else if ((mat.type() != CV_8UC3) && (mat.type() != CV_8UC4)) {
cout << "image type not supported";
supported or you could use cv::cvtColor";
return;
}
//really you could avoid this because is done by MFC StretchDIBits
//resize(mat,mat,cv::Size(rc.Width(),rc.Height()));
int x=mat.cols;
int y=mat.rows;
int padding = 0;
if (mat.type() != CV_8UC4) // padding is not needed for 32bit images
{
padding = 4 - (x % 4);
if(padding==4)
padding = 0;
}
cv::Mat matTmp;
if (padding > 0 || mat.isContinuous() == false)
{
// Adding needed columns on the right (max 3 px)
cv::copyMakeBorder(mat, matTmp, 0, 0, 0, padding, cv::BORDER_CONSTANT, 0);
}
else
{
matTmp = mat;
}
Now you have right memory shape for a MFC bitmap. You can draw it avoiding the border using:
//real cols in the bitmap header
pheader->biWidth = matTmp.cols;
//wanted cols (original cols) for drawing
StretchDIBits( dc.GetSafeHdc()
,0, 0, rc.Width(), rc.Height()
,0, 0, x, y,
matTmp.data, &bmi, DIB_RGB_COLORS, SRCCOPY);
Finally your code will not work in case the image is grey scale because you need to prepare right palette in BITMAPINFOHEADER
As alternative, instead of cv::copyMakeBorder
you could use cv::cvtColor(mat,xxx2BGRA)
. This is slower (because of math operations) and memory consuming (because of needed channels) but will works for all imput format. Example: given a BGR image 3(CH)x800(R)x801(C)
:
copyMakeBorder(..,3)
will creates a new BGR image 3CHx800Rx804C
adds 38003 =7KBytecvtColor(...,BGR2BGRA)
will creates a new BGRA image 4CHx800Rx801C
adds 1800801 = 626KByteremeber to use in-place operation with care with discontinuous Mat.
5 | No.5 Revision |
DWORD
memory alignment for bitmaps rows Than cv::Mat mat
must be:
cv::cvtColor
(bpp * mat.cols) % 4 == 0
. You could use cv::copyMakeBorder
or cv::cvtColor
If the image is not continuous (eg is a ROI) you should use in-place operation with care because it would be not continuous again.
About memory alignment, looking at How the image matrix is stored in the memory? you can see that for a cv::Mat BytesForRows = bpp * mat.cols
where bpp
is number of byte for each pixel.
Definitely you should have 32bit image or image cols as multiple of 4: cols % 4 == 0
. This is fine for GRAY and RGB images because 4cols4 x cols x bpp is always a multiple of 4 than DWORD aligned on rows.
here the code:
Mat mat;
mat=imread("aaa.bmp");
if ( mat.type() == CV_8UC1 ) {
cout << "not working because a greyscale palette is needed or you could use cv::cvtColor";
return;
}
else if ((mat.type() != CV_8UC3) && (mat.type() != CV_8UC4)) {
cout << "image type not supported or you could use cv::cvtColor";
return;
}
//really you could avoid this because is done by MFC StretchDIBits
//resize(mat,mat,cv::Size(rc.Width(),rc.Height()));
int x=mat.cols;
int y=mat.rows;
int padding = 0;
if (mat.type() != CV_8UC4) // padding is not needed for 32bit images
{
padding = 4 - (x % 4);
if(padding==4)
padding = 0;
}
cv::Mat matTmp;
if (padding > 0 || mat.isContinuous() == false)
{
// Adding needed columns on the right (max 3 px)
cv::copyMakeBorder(mat, matTmp, 0, 0, 0, padding, cv::BORDER_CONSTANT, 0);
}
else
{
matTmp = mat;
}
Now you have right memory shape for a MFC bitmap. You can draw it avoiding the border using:
//real cols in the bitmap header
pheader->biWidth = matTmp.cols;
//wanted cols (original cols) for drawing
StretchDIBits( dc.GetSafeHdc()
,0, 0, rc.Width(), rc.Height()
,0, 0, x, y,
matTmp.data, &bmi, DIB_RGB_COLORS, SRCCOPY);
Finally your code will not work in case the image is grey scale because you need to prepare right palette in BITMAPINFOHEADER
As alternative, instead of cv::copyMakeBorder
you could use cv::cvtColor(mat,xxx2BGRA)
. This is slower (because of math operations) and memory consuming (because of needed channels) but will works for all imput format. Example: given a BGR image
:3(CH)x800(R)x801(C)3(CH) x 800(R) x 801(C)
copyMakeBorder(..,3)
will creates a new BGR image 3CHx800Rx804C3CH x 800R x 804C
adds cvtColor(...,BGR2BGRA)
will creates a new BGRA image 4CHx800Rx801C4CH x 800R x 801C
adds remeber to use in-place operation with care with discontinuous Mat.
6 | No.6 Revision |
DWORD
memory alignment for bitmaps rows Than cv::Mat mat
must be:
cv::cvtColor
(bpp * mat.cols) % 4 == 0
. You could use cv::copyMakeBorder
or cv::cvtColor
If the image is not continuous (eg is a ROI) you should use in-place operation with care because it would be not continuous again.
About memory alignment, looking at How the image matrix is stored in the memory? you can see that for a cv::Mat BytesForRows = bpp * mat.cols
where bpp
is number of byte for each pixel.
Definitely you should have 32bit image or image cols as multiple of 4: cols % 4 == 0
. This is fine for GRAY and RGB images because 4 x cols x bpp is always a multiple of 4 than DWORD aligned on rows.
here the code:
Mat mat;
mat=imread("aaa.bmp");
if ( mat.type() == CV_8UC1 ) {
cout << "not working because a greyscale palette is needed or you could use cv::cvtColor";
return;
}
else if ((mat.type() != CV_8UC3) && (mat.type() != CV_8UC4)) {
cout << "image type not supported or you could use cv::cvtColor";
return;
}
//really you could avoid this because is done by MFC StretchDIBits
//resize(mat,mat,cv::Size(rc.Width(),rc.Height()));
int x=mat.cols;
int y=mat.rows;
int padding = 0;
if (mat.type() != CV_8UC4) // padding is not needed for 32bit images
{
padding = 4 - (x % 4);
if(padding==4)
padding = 0;
}
cv::Mat matTmp;
if (padding > 0 || mat.isContinuous() == false)
{
// Adding needed columns on the right (max 3 px)
cv::copyMakeBorder(mat, matTmp, 0, 0, 0, padding, cv::BORDER_CONSTANT, 0);
}
else
{
matTmp = mat;
}
Now you have right memory shape for a MFC bitmap. You can draw it avoiding the border using:
//real cols in the bitmap header
pheader->biWidth = matTmp.cols;
//wanted cols (original cols) for drawing
StretchDIBits( dc.GetSafeHdc()
,0, 0, rc.Width(), rc.Height()
,0, 0, x, y,
matTmp.data, &bmi, DIB_RGB_COLORS, SRCCOPY);
Finally your code will not work in case the image is grey scale because you need to prepare right palette in BITMAPINFOHEADER
As alternative, instead of cv::copyMakeBorder
you could use cv::cvtColor(mat,xxx2BGRA)
. This is slower (because of math operations) and memory consuming (because of needed channels) but will works for all imput input format. Example: given a BGR image 3(CH) x 800(R) x 801(C)
:
copyMakeBorder(..,3)
will creates a new BGR image 3CH x 800R x 804C
adds 3 x 800 x 3 =7KBytecvtColor(...,BGR2BGRA)
will creates a new BGRA image 4CH x 800R x 801C
adds 1 x 800 x 801 = 626KByteremeber to use in-place operation with care with discontinuous Mat.