📄 grayi.cpp
字号:
for (CoordI x = left; x < right; x++) {
*ppxliRet++ = *ppxliOrgX;
ppxliOrgX += rateX;
}
ppxliOrgY += skipY;
}
return piiRet;
}
own CIntImage* CIntImage::decimateBinaryShape (UInt rateX, UInt rateY) const
{
const CoordI left = where ().left / (CoordI) rateX;
const CoordI top = where ().top / (CoordI) rateY;
Int roundR = (where ().right >= 0) ? rateX - 1 : 1 - rateX;
Int roundB = (where ().bottom >= 0) ? rateY - 1 : 1 - rateY;
const CoordI right = (where ().right + roundR) / (CoordI) rateX;
const CoordI bottom = (where ().bottom + roundB) / (CoordI) rateY;
CIntImage* piiRet = new CIntImage (CRct (left, top, right, bottom));
PixelI* ppxliRet = (PixelI*) piiRet -> pixels ();
const PixelI* ppxliOrgY = pixels ();
Int skipY = rateY * where ().width;
CoordI x, y;
CoordI iXOrigLeft, iYOrigTop; //left top of a sampling square
for (y = top, iYOrigTop = where().top; y < bottom; y++, iYOrigTop += rateY) {
const PixelI* ppxliOrgX = ppxliOrgY;
for (x = left, iXOrigLeft = where().left; x < right; x++, iXOrigLeft += rateX) {
CoordI iXOrig, iYOrig; //for scanning of the sampling square
const PixelI* ppxliOrigScanY = ppxliOrgX; //same
*ppxliRet = transpValue;
for (iYOrig = iYOrigTop; iYOrig < (iYOrigTop + (Int) rateY); iYOrig++) {
if (iYOrig >= where().bottom || *ppxliRet == opaqueValue)
break;
const PixelI* ppxliOrigScanX = ppxliOrigScanY; //for scan also
for (iXOrig = iXOrigLeft; iXOrig < (iXOrigLeft + (Int) rateX); iXOrig++) {
if (iXOrig >= where().right)
break;
assert (*ppxliOrigScanX == transpValue || *ppxliOrigScanX == opaqueValue);
if (*ppxliOrigScanX == opaqueValue) {
*ppxliRet = opaqueValue;
break;
}
ppxliOrigScanX++;
}
ppxliOrigScanY += where().width;
}
assert (*ppxliRet == transpValue || *ppxliRet == opaqueValue);
ppxliRet++;
ppxliOrgX += rateX;
}
ppxliOrgY += skipY;
}
return piiRet;
}
own CIntImage* CIntImage::zoomup (UInt rateX, UInt rateY) const
{
const CoordI left = where ().left * rateX; // left-top coordinate remain the same
const CoordI top = where ().top * rateY;
const CoordI right = where ().right * rateX;
const CoordI bottom = where ().bottom * rateY;
CIntImage* piiRet = new CIntImage (CRct (left, top, right, bottom));
PixelI* ppxlRet = (PixelI*) piiRet -> pixels ();
for (CoordI y = top; y < bottom; y++) {
for (CoordI x = left; x < right; x++)
*ppxlRet++ = pixel ((CoordI) (x / rateX), (CoordI) (y / rateY));
}
return piiRet;
}
own CIntImage* CIntImage::expand (UInt rateX, UInt rateY) const // expand by putting zeros in between
{
const CoordI left = where ().left * rateX; // left-top coordinate remain the same
const CoordI top = where ().top * rateY;
const CoordI right = where ().right * rateX;
const CoordI bottom = where ().bottom * rateY;
CIntImage* piiRet = new CIntImage (CRct (left, top, right, bottom));
PixelI* ppxlRet = (PixelI*) piiRet -> pixels ();
const PixelI* ppxlThis = pixels ();
for (CoordI y = top; y < bottom; y++) {
for (CoordI x = left; x < right; x++) {
if (x % rateX == 0 && y % rateY == 0)
*ppxlRet++ = *ppxlThis++;
else
*ppxlRet++ = 0;
}
}
return piiRet;
}
own CIntImage* CIntImage::biInterpolate () const // bilinearly interpolate the vframe
{
const CoordI left = where ().left << 1; // left-top coordinate remain the same
const CoordI top = where ().top << 1;
const CoordI right = where ().right << 1;
const CoordI bottom = where ().bottom << 1;
const CoordI width = right - left;
CoordI x, y;
CIntImage* piiRet = new CIntImage (CRct (left, top, right, bottom));
PixelI* ppxliRet = (PixelI*) piiRet -> pixels ();
const PixelI* ppxli = pixels ();
const CoordI right1 = right - 2;
for (y = top; y < bottom; y += 2) { // x-direction interpolation
for (x = left; x < right1; x += 2) {
*ppxliRet++ = *ppxli++;
*ppxliRet++ = (*ppxli + *(ppxli - 1) + 1) >> 1;
}
*ppxliRet++ = *ppxli;
*ppxliRet++ = *ppxli++; // the last pixel of every row do not need average
ppxliRet += width;
}
ppxliRet = (PixelI*) piiRet -> pixels ();
ppxliRet += width; // start from the second row
const CoordI width2 = width << 1;
const CoordI bottom1 = bottom - 1;
for (x = left; x < right; x++) { // y-direction interpolation
PixelI* ppxliRett = ppxliRet++;
for (y = top + 1; y < bottom1; y += 2) {
*ppxliRett = (*(ppxliRett - width) + *(ppxliRett + width) + 1) >> 1;
ppxliRett += width2;
}
*ppxliRett = *(ppxliRett - width); // the last pixel of every column do not need average
}
return piiRet;
}
own CIntImage* CIntImage::downsampleForSpatialScalability () const
{
static Int rgiFilterVertical[13] = {2, 0, -4, -3, 5, 19, 26, 19, 5, -3, -4, 0, 2};
static Int rgiFilterHorizontal[4] = {5, 11, 11, 5};
Int iWidthSrc = where (). width;
Int iHeightSrc = where (). height ();
assert (iWidthSrc % 2 == 0 && iHeightSrc % 2 == 0);
Int iWidthDst = iWidthSrc / 2;
Int iHeightDst = iHeightSrc / 2;
CIntImage* piiBuffer = new CIntImage (CRct (0, 0, iWidthSrc, iHeightDst));
CIntImage* piiRet = new CIntImage (CRct (0, 0, iWidthDst, iHeightDst));
assert (piiBuffer != NULL);
assert (piiRet != NULL);
//filter and downsample vertically
const PixelI* ppxliSrc;
const PixelI* ppxliColumnHeadSrc = pixels ();
PixelI* ppxliDst = (PixelI*) piiBuffer->pixels ();
PixelI* ppxliColumnHeadDst = (PixelI*) piiBuffer->pixels ();
Int i, j, k;
for (i = 0; i < iWidthSrc; i++) {
ppxliSrc = ppxliColumnHeadSrc;
ppxliDst = ppxliColumnHeadDst;
for (j = 0; j < iHeightDst; j++) {
k = j * 2;
const PixelI* ppxliMinusOne = ( k < 1 ) ? ppxliSrc : ppxliSrc - iWidthSrc;
const PixelI* ppxliMinusTwo = ( k < 2 ) ? ppxliSrc : ppxliMinusOne - iWidthSrc;
const PixelI* ppxliMinusThree = ( k < 3 ) ? ppxliSrc : ppxliMinusTwo - iWidthSrc;
const PixelI* ppxliMinusFour = ( k < 4 ) ? ppxliSrc : ppxliMinusThree - iWidthSrc;
const PixelI* ppxliMinusFive = ( k < 5 ) ? ppxliSrc : ppxliMinusFour - iWidthSrc;
const PixelI* ppxliMinusSix = ( k < 6 ) ? ppxliSrc : ppxliMinusFive - iWidthSrc;
const PixelI* ppxliPlusOne = ( k >= iHeightSrc - 1) ? ppxliSrc : ppxliSrc + iWidthSrc;
const PixelI* ppxliPlusTwo = ( k >= iHeightSrc - 2) ? ppxliPlusOne : ppxliPlusOne + iWidthSrc;
const PixelI* ppxliPlusThree = ( k >= iHeightSrc - 3) ? ppxliPlusTwo : ppxliPlusTwo + iWidthSrc;
const PixelI* ppxliPlusFour = ( k >= iHeightSrc - 4) ? ppxliPlusThree : ppxliPlusThree + iWidthSrc;
const PixelI* ppxliPlusFive = ( k >= iHeightSrc - 5) ? ppxliPlusFour : ppxliPlusFour + iWidthSrc;
const PixelI* ppxliPlusSix = ( k >= iHeightSrc - 6) ? ppxliPlusFive : ppxliPlusFive + iWidthSrc;
*ppxliDst = checkrange (
(Int) ((*ppxliMinusSix * rgiFilterVertical [0] +
*ppxliMinusFive * rgiFilterVertical [1] +
*ppxliMinusFour * rgiFilterVertical [2] +
*ppxliMinusThree * rgiFilterVertical [3] +
*ppxliMinusTwo * rgiFilterVertical [4] +
*ppxliMinusOne * rgiFilterVertical [5] +
*ppxliSrc * rgiFilterVertical [6] +
*ppxliPlusOne * rgiFilterVertical [7] +
*ppxliPlusTwo * rgiFilterVertical [8] +
*ppxliPlusThree * rgiFilterVertical [9] +
*ppxliPlusFour * rgiFilterVertical [10] +
*ppxliPlusFive * rgiFilterVertical [11] +
*ppxliPlusSix * rgiFilterVertical [12] + 32) >> 6),
0, 255
);
ppxliSrc += 2 * iWidthSrc;
ppxliDst += iWidthSrc;
}
ppxliColumnHeadSrc++;
ppxliColumnHeadDst++;
}
//filter and downsample horizontally
ppxliSrc = piiBuffer->pixels ();
ppxliDst = (PixelI*) piiRet->pixels ();
for (j = 0; j < iHeightDst; j++) {
for (i = 0; i < iWidthDst; i++) {
k = i * 2;
const PixelI* ppxliMinusOne = ( k < 1 ) ? ppxliSrc : ppxliSrc - 1;
const PixelI* ppxliPlusOne = ( k >= iWidthSrc - 1) ? ppxliSrc : ppxliSrc + 1;
const PixelI* ppxliPlusTwo = ( k >= iWidthSrc - 2) ? ppxliSrc : ppxliSrc + 2;
*ppxliDst = checkrange (
(Int) ((*ppxliMinusOne * rgiFilterHorizontal [0] +
*ppxliSrc * rgiFilterHorizontal [1] +
*ppxliPlusOne * rgiFilterHorizontal [2] +
*ppxliPlusTwo * rgiFilterHorizontal [3] + 16) >> 5),
0, 255
);
ppxliSrc += 2;
ppxliDst++;
}
}
delete piiBuffer;
return piiRet;
}
own CIntImage* CIntImage::upsampleForSpatialScalability () const
{
CRct rctDst = where () * 2;
Int iWidthSrc = where (). width;
Int iHeightSrc = where (). height ();
Int iHeightDst = iHeightSrc * 2;
CIntImage* piiBuffer = new CIntImage (CRct (where().left, rctDst.top, where().right, rctDst.bottom));
CIntImage* piiRet = new CIntImage (CRct (rctDst.left, rctDst.top, rctDst.right, rctDst.bottom));
//upsample vertically
const PixelI* ppxliSrc;
const PixelI* ppxliSrcPlusOne;
const PixelI* ppxliColumnHeadSrc = pixels ();
PixelI* ppxliDst;
PixelI* ppxliColumnHeadDst = (PixelI*) piiBuffer->pixels ();
Int i, j;
for (i = 0; i < iWidthSrc; i++) {
ppxliSrc = ppxliColumnHeadSrc;
ppxliSrcPlusOne = ppxliSrc + iWidthSrc;
ppxliDst = ppxliColumnHeadDst;
for (j = 0; j < iHeightSrc; j++) {
*ppxliDst = checkrange (
(Int) ((*ppxliSrc * 3 + *ppxliSrcPlusOne + 2) >> 2),
0, 255
);
ppxliDst += iWidthSrc;
*ppxliDst = checkrange (
(Int) ((*ppxliSrc + *ppxliSrcPlusOne * 3 + 2) >> 2),
0, 255
);
ppxliDst += iWidthSrc;
ppxliSrc += iWidthSrc;
ppxliSrcPlusOne = (j >= iHeightSrc - 2) ? ppxliSrc : ppxliSrc + iWidthSrc;
}
ppxliColumnHeadSrc++;
ppxliColumnHeadDst++;
}
//upsample horizontally
ppxliSrc = piiBuffer->pixels ();
ppxliDst = (PixelI*) piiRet->pixels ();
for (j = 0; j < iHeightDst; j++) {
ppxliSrcPlusOne = ppxliSrc + 1;
for (i = 0; i < iWidthSrc; i++) {
*ppxliDst = checkrange (
(Int) ((*ppxliSrc * 3 + *ppxliSrcPlusOne + 2) >> 2),
0, 255
);
ppxliDst++;
*ppxliDst = checkrange (
(Int) ((*ppxliSrc + *ppxliSrcPlusOne * 3 + 2) >> 2),
0, 255
);
ppxliDst++;
ppxliSrc++;
ppxliSrcPlusOne = (i >= iWidthSrc - 2) ? ppxliSrc : ppxliSrc + 1;
}
}
delete piiBuffer;
return piiRet;
}
own CIntImage* CIntImage::biInterpolate (UInt accuracy) const // bilinearly interpolate the vframe
{
const CoordI left = where ().left * accuracy;
const CoordI top = where ().top * accuracy;
const CoordI right = where ().right * accuracy;
const CoordI bottom = where ().bottom * accuracy;
CIntImage* piiRet = new CIntImage (CRct (left, top, right, bottom));
PixelI* ppxliRet = (PixelI*) piiRet -> pixels ();
for (CoordI y = top; y < bottom; y++) { // x-direction interpolation
for (CoordI x = left; x < right; x++) {
*ppxliRet = pixel (x, y, accuracy);
ppxliRet++;
}
}
return piiRet;
}
own CIntImage* CIntImage::transpose () const
{
CRct rctDst = where ();
rctDst.transpose ();
CIntImage* piiDst = new CIntImage (rctDst);
const PixelI* ppxlSrc = pixels ();
PixelI* ppxlDstRow = (PixelI*) piiDst->pixels ();
PixelI* ppxlDst;
UInt height = where ().height ();
for (CoordI iy = where ().top; iy < where ().bottom; iy++) {
ppxlDst = ppxlDstRow;
for (CoordI ix = where ().left; ix < where ().right; ix++) {
*ppxlDst = *ppxlSrc++;
ppxlDst += height;
}
ppxlDstRow++;
}
return piiDst;
}
own CIntImage* CIntImage::warp (const CAffine2D& aff) const // affine warp
{
CSiteD stdLeftTopWarp = aff * CSiteD (where ().left, where ().top);
CSiteD stdRightTopWarp = aff * CSiteD (where ().right, where ().top);
CSiteD stdLeftBottomWarp = aff * CSiteD (where ().left, where ().bottom);
CSiteD stdRightBottomWarp = aff * CSiteD (where ().right, where ().bottom);
CRct rctWarp (stdLeftTopWarp, stdRightTopWarp, stdLeftBottomWarp, stdRightBottomWarp);
CIntImage* piiRet = new CIntImage (rctWarp);
PixelI* ppxliRet = (PixelI*) piiRet -> pixels ();
CAffine2D affInv = aff.inverse ();
for (CoordI y = rctWarp.top; y < rctWarp.bottom; y++) {
for (CoordI x = rctWarp.left; x < rctWarp.right; x++) {
CSiteD src = affInv * CSiteD (x, y);
CoordI fx = (CoordI) floor (src.x); //.5 is for better truncation
CoordI fy = (CoordI) floor (src.y); //.5 is for better truncation
CoordI cx = (CoordI) ceil (src.x); //.5 is for better truncation
CoordI cy = (CoordI) ceil (src.y); //.5 is for better truncation
if (
where ().includes (fx, fy) &&
where ().includes (fx, cy) &&
where ().includes (cx, fy) &&
where ().includes (cx, cy)
)
*ppxliRet = pixel (src);
ppxliRet++;
}
}
return piiRet;
}
own CIntImage* CIntImage::warp (const CPerspective2D& persp) const // perspective warp
{
CSiteD src [4], dest [4];
src [0] = CSiteD (where ().left, where ().top);
src [1] = CSiteD (where ().right, where ().top);
src [2] = CSiteD (where ().left, where ().bottom);
src [3] = CSiteD (where ().right, where ().bottom);
for (UInt i = 0; i < 4; i++) {
dest [i] = (persp * src [i]).s;
}
CRct rctWarp (dest [0], dest [1], dest [2], dest [3]);
CIntImage* piiRet = new CIntImage (rctWarp);
PixelI* ppxliRet = (PixelI*) piiRet -> pixels ();
CPerspective2D perspInv = CPerspective2D (dest, src);
for (CoordI y = rctWarp.top; y != rctWarp.bottom; y++) {
for (CoordI x = rctWarp.left; x != rctWarp.right; x++) {
CSiteD src = (perspInv * CSiteD (x, y)).s;
CoordI fx = (CoordI) floor (src.x); //.5 is for better truncation
CoordI fy = (CoordI) floor (src.y); //.5 is for better truncation
CoordI cx = (CoordI) ceil (src.x); //.5 is for better truncation
CoordI cy = (CoordI) ceil (src.y); //.5 is for better truncation
if (
where ().includes (fx, fy) &&
where ().includes (fx, cy) &&
where ().includes (cx, fy) &&
where ().includes (cx, cy)
)
*ppxliRet = pixel (src);
ppxliRet++;
}
}
return piiRet;
}
own CIntImage* CIntImage::warp (const CPerspective2D& persp, const CRct& rctWarp) const // perspective warp
{
CIntImage* piiRet = new CIntImage (rctWarp);
PixelI* ppxliRet = (PixelI*) piiRet -> pixels ();
CPerspective2D perspInv = persp.inverse ();
for (CoordI y = rctWarp.top; y != rctWarp.bottom; y++) {
for (CoordI x = rctWarp.left; x != rctWarp.right; x++) {
CSiteD src = (perspInv * CSiteD (x, y)).s;
CoordI fx = (CoordI) floor (src.x); //.5 is for better truncation
CoordI fy = (CoordI) floor (src.y); //.5 is for better truncation
CoordI cx = (CoordI) ceil (src.x); //.5 is for better truncation
CoordI cy = (CoordI) ceil (src.y); //.5 is for better truncation
if (
where ().includes (fx, fy) &&
where ().includes (fx, cy) &&
where ().includes (cx, fy) &&
where ().includes (cx, cy)
)
*ppxliRet = pixel (src);
ppxliRet++;
}
}
return piiRet;
}
own CIntImage* CIntImage::warp (const CPerspective2D& persp, const CRct& rctWarp, const UInt accuracy) const // perspective warp
{
CIntImage* piiRet = new CIntImage (rctWarp);
PixelI* ppxliRet = (PixelI*) piiRet -> pixels ();
for (CoordI y = rctWarp.top; y != rctWarp.bottom; y++) {
for (CoordI x = rctWarp.left; x != rctWarp.right; x++) {
CSite src = (persp * CSite (x, y)).s;
CoordI fx = (CoordI) floor ((CoordD) src.x / (CoordD) accuracy); //.5 is for better truncation
CoordI fy = (CoordI) floor ((CoordD) src.y / (CoordD) accuracy); //.5 is for better truncation
CoordI cx = (CoordI) ceil ((CoordD) src.x / (CoordD) accuracy); //.5 is for better truncation
CoordI cy = (CoordI) ceil ((CoordD) src.y / (CoordD) accuracy); //.5 is for better truncation
if (
where ().includes (fx, fy) &&
where ().includes (fx, cy) &&
where ().includes (cx, fy) &&
where ().includes (cx, cy)
)
*ppxliRet = pixel (src, accuracy);
ppxliRet++;
}
}
return piiRet;
}
PixelI CIntImage::pixel (CoordD x, CoordD y) const
{
CoordI left = (CoordI) floor (x); // find the coordinates of the four corners
CoordI wLeft = where ().left, wRight1 = where ().right - 1, wTop = where ().top, wBottom1 = where ().bottom - 1;
left = checkrange (left, wLeft, wRight1);
CoordI right = (CoordI) ceil (x);
right = checkrange (right, wLeft, wRight1);
CoordI top = (CoordI) floor (y);
top = checkrange (top, wTop, wBottom1);
CoordI bottom = (CoordI) ceil (y);
bottom = checkrange (bottom, wTop, wBottom1);
const PixelI lt = pixel (left, top);
const PixelI rt = pixel (right, top);
const PixelI lb = pixel (left, bottom);
const PixelI rb = pixel (right, bottom);
const Double distX = x - left;
const Double distY = y - top;
Double x01 = distX * (rt - lt) + lt; // use p.59's notation (Wolberg, Digital Image Warping)
Double x23 = distX * (rb - lb) + lb;
PixelI pxlRet = checkrange ((Int) (x01 + (x23 - x01) * distY + .5), 0, 255);
return pxlRet;
}
PixelI CIntImage::pixel (CoordI x, CoordI y, UInt accuracy) const // accuracy indicates the 2/4/8/16 quantization
{
CoordI left = (CoordI) floor ((CoordD) x / (CoordD) accuracy); // find the coordinates of the four corners
CoordI wLeft = where ().left, wRight1 = where ().right - 1, wTop = where ().top, wBottom1 = where ().bottom - 1;
left = checkrange (left, wLeft, wRight1);
CoordI right = (CoordI) ceil ((CoordD) x / (CoordD) accuracy);
right = checkrange (right, wLeft, wRight1);
CoordI top = (CoordI) floor ((CoordD) y / (CoordD) accuracy);
top = checkrange (top, wTop, wBottom1);
CoordI bottom = (CoordI) ceil ((CoordD) y / (CoordD) accuracy);
bottom = checkrange (bottom, wTop, wBottom1);
const PixelI lt = pixel (left, top);
const PixelI rt = pixel (right, top);
const PixelI lb = pixel (left, bottom);
const PixelI rb = pixel (right, bottom);
const CoordI distX = x - left * accuracy;
const CoordI distY = y - top * accuracy;
Double x01 = distX * (rt - lt) + accuracy * lt; // use p.59's notation (Wolberg, Digital Image Warping)
Double x23 = distX * (rb - lb) + accuracy * lb;
PixelI pxlRet = checkrange ((Int) ((accuracy * x01 + (x23 - x01) * distY)) / (accuracy * accuracy), 0, 255);
return pxlRet;
}
own CIntImage* CIntImage::complement () const
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -