📄 grayf.cpp
字号:
*ppxlfDst = checkrange ( (*ppxlfSrc * 3 + *ppxlfSrcPlusOne) / 4,
0.0F, 255.0F);
ppxlfDst++;
*ppxlfDst = checkrange ( (*ppxlfSrc + *ppxlfSrcPlusOne * 3) / 4,
0.0F, 255.0F);
ppxlfDst++;
ppxlfSrc++;
ppxlfSrcPlusOne = (i >= iWidthSrc - 2) ? ppxlfSrc : ppxlfSrc + 1;
}
}
delete pfiBuffer;
return pfiRet;
}
own CFloatImage* CFloatImage::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;
CFloatImage* pfiRet = new CFloatImage (CRct (left, top, right, bottom));
PixelF* ppxlfRet = (PixelF*) pfiRet -> pixels ();
for (CoordI y = top; y < bottom; y++) { // x-direction interpolation
for (CoordI x = left; x < right; x++) {
*ppxlfRet = pixel (x, y, accuracy);
ppxlfRet++;
}
}
return pfiRet;
}
own CFloatImage* CFloatImage::transpose () const
{
CRct rctDst = where ();
rctDst.transpose ();
CFloatImage* pfiDst = new CFloatImage (rctDst);
const PixelF* ppxlSrc = pixels ();
PixelF* ppxlDstRow = (PixelF*) pfiDst->pixels ();
PixelF* 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 pfiDst;
}
own CFloatImage* CFloatImage::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);
CFloatImage* pfiRet = new CFloatImage (rctWarp);
PixelF* ppxlfRet = (PixelF*) pfiRet -> 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)
)
*ppxlfRet = pixel (src);
ppxlfRet++;
}
}
return pfiRet;
}
own CFloatImage* CFloatImage::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]);
CFloatImage* pfiRet = new CFloatImage (rctWarp);
PixelF* ppxlfRet = (PixelF*) pfiRet -> 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)
)
*ppxlfRet = pixel (src);
ppxlfRet++;
}
}
return pfiRet;
}
own CFloatImage* CFloatImage::warp (const CPerspective2D& persp, const CRct& rctWarp) const // perspective warp
{
CFloatImage* pfiRet = new CFloatImage (rctWarp);
PixelF* ppxlfRet = (PixelF*) pfiRet -> 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)
)
*ppxlfRet = pixel (src);
ppxlfRet++;
}
}
return pfiRet;
}
own CFloatImage* CFloatImage::warp (const CPerspective2D& persp, const CRct& rctWarp, const UInt accuracy) const // perspective warp
{
CFloatImage* pfiRet = new CFloatImage (rctWarp);
PixelF* ppxlfRet = (PixelF*) pfiRet -> 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)
)
*ppxlfRet = pixel (src, accuracy);
ppxlfRet++;
}
}
return pfiRet;
}
PixelF CFloatImage::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 PixelF lt = pixel (left, top);
const PixelF rt = pixel (right, top);
const PixelF lb = pixel (left, bottom);
const PixelF 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;
PixelF pxlRet = checkrange ((Float) (x01 + (x23 - x01) * distY), 0.0f, 255.0f);
return pxlRet;
}
PixelF CFloatImage::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 PixelF lt = pixel (left, top);
const PixelF rt = pixel (right, top);
const PixelF lb = pixel (left, bottom);
const PixelF 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;
PixelF pxlRet = checkrange ((Float) ((accuracy * x01 + (x23 - x01) * distY)) / (accuracy * accuracy), 0.0f, 255.0f);
return pxlRet;
}
own CFloatImage* CFloatImage::complement () const
{
CFloatImage* pfiDst = new CFloatImage (where(), (PixelF) transpValue);
const PixelF* ppxlfSrc = pixels ();
PixelF* ppxlfDst = (PixelF*) pfiDst->pixels ();
for (UInt iPxl = 0; iPxl < where ().area (); iPxl++) {
if (*ppxlfSrc == (PixelF) opaqueValue)
*ppxlfDst = (PixelF) transpValue;
else if (*ppxlfSrc == (PixelF) transpValue)
*ppxlfDst = (PixelF) opaqueValue;
else
assert (FALSE); //complemetn only work on pseudo-binary data
ppxlfSrc++;
ppxlfDst++;
}
return pfiDst;
}
Void CFloatImage::overlay (const CFloatImage& fi)
{
if (!valid () || !fi.valid () || fi.where ().empty ()) return;
CRct r = m_rc;
r.include (fi.m_rc); // overlay is defined on union of rects
where (r);
if (!valid ()) return;
assert (fi.m_ppxlf != NULL);
CRct rctFi = fi.m_rc;
Int widthFi = rctFi.width;
Int widthCurr = where ().width;
PixelF* ppxlfThis = (PixelF*) pixels (rctFi.left, rctFi.top);
const PixelF* ppxlfFi = fi.pixels ();
for (CoordI y = rctFi.top; y < rctFi.bottom; y++) { // loop through VOP CRct
memcpy (ppxlfThis, ppxlfFi, rctFi.width * sizeof (PixelF));
ppxlfThis += widthCurr;
ppxlfFi += widthFi;
}
}
own CFloatImage* CFloatImage::smooth_ (UInt window) const
{
const UInt offset = window >> 1;
const UInt offset2 = offset << 1;
const UInt size = window * window; // array size to be sorted
const UInt med = size >> 1;
CFloatImage* pfmgRet = new CFloatImage (*this);
// bound of the image to be filtered.
const CoordI left = where ().left + offset;
const CoordI top = where ().top + offset;
const CoordI right = where ().right - offset;
const CoordI bottom = where ().bottom - offset;
const Int width = where ().width;
const Int dist = offset + offset * width;
const Int wwidth = width - window;
PixelF* rgValues = new PixelF [size];
PixelF* pRet = (PixelF*) pfmgRet -> pixels (left, top);
const PixelF* p = pixels (left, top);
for (CoordI y = top; y != bottom; y++) {
for (CoordI x = left; x != right; x++) {
const PixelF* pp = p - dist; // get correct index
UInt numTransp = 0;
for (UInt sy = 0; sy != window; sy++) {
for (UInt sx = 0; sx != window; sx++) {
if (*pp == (PixelF) transpValue)
numTransp++;
pp++;
}
pp += wwidth;
}
*pRet++ = (PixelF) ((numTransp <= med) ? opaqueValue : transpValue);
p++;
}
pRet += offset2;
p += offset2;
}
delete [] rgValues;
return pfmgRet;
}
own CFloatImage* CFloatImage::smooth (UInt window) const
{
UInt offset = window >> 1;
CRct rctExp (where ());
rctExp.expand (offset);
CFloatImage* pfiExp = new CFloatImage (*this, rctExp);
CFloatImage* pfiSmooth = pfiExp -> smooth_ (window);
pfiSmooth -> where (where ());
delete pfiExp;
return pfiSmooth;
}
Void CFloatImage::xorFi (const CFloatImage& fi)
{
CRct rctIntersect = m_rc;
rctIntersect.clip (fi.where());
if (!rctIntersect.valid () || rctIntersect.empty ()) return;
PixelF* ppxlfRowStart1 = (PixelF*) pixels (rctIntersect.left, rctIntersect.top);
const PixelF* ppxlfRowStart2 = fi.pixels (rctIntersect.left, rctIntersect.top);
for (CoordI iy = rctIntersect.top; iy < rctIntersect.bottom; iy++) {
PixelF* ppxlf1 = ppxlfRowStart1;
const PixelF* ppxlf2 = ppxlfRowStart2;
for (CoordI ix = rctIntersect.left; ix < rctIntersect.right; ix++) {
assert (*ppxlf1 == (PixelF) transpValue || *ppxlf1 == (PixelF) opaqueValue);
assert (*ppxlf2 == (PixelF) transpValue || *ppxlf2 == (PixelF) opaqueValue);
if (*ppxlf1 == *ppxlf2)
*ppxlf1 = (PixelF) transpValue;
else
*ppxlf1 = (PixelF) opaqueValue;
ppxlf1++;
ppxlf2++;
}
ppxlfRowStart1 += where().width;
ppxlfRowStart2 += fi.where().width;
}
}
Void CFloatImage::orFi (const CFloatImage& fi)
{
CRct rctIntersect = m_rc;
rctIntersect.clip (fi.where());
if (!rctIntersect.valid () || rctIntersect.empty ()) return;
PixelF* ppxlfRowStart1 = (PixelF*) pixels (rctIntersect.left, rctIntersect.top);
const PixelF* ppxlfRowStart2 = fi.pixels (rctIntersect.left, rctIntersect.top);
for (CoordI iy = rctIntersect.top; iy < rctIntersect.bottom; iy++) {
PixelF* ppxlf1 = ppxlfRowStart1;
const PixelF* ppxlf2 = ppxlfRowStart2;
for (CoordI ix = rctIntersect.left; ix < rctIntersect.right; ix++) {
assert (*ppxlf1 == (PixelF) transpValue || *ppxlf1 == (PixelF) opaqueValue);
assert (*ppxlf2 == (PixelF) transpValue || *ppxlf2 == (PixelF) opaqueValue);
if (*ppxlf2 == opaqueValue)
*ppxlf1 = (PixelF) opaqueValue;
ppxlf1++;
ppxlf2++;
}
ppxlfRowStart1 += where().width;
ppxlfRowStart2 += fi.where().width;
}
}
Void CFloatImage::andFi (const CFloatImage& fi)
{
CRct rctIntersect = m_rc;
rctIntersect.clip (fi.where());
if (!rctIntersect.valid () || rctIntersect.empty ()) return;
PixelF* ppxlfRowStart1 = (PixelF*) pixels (rctIntersect.left, rctIntersect.top);
const PixelF* ppxlfRowStart2 = fi.pixels (rctIntersect.left, rctIntersect.top);
for (CoordI iy = rctIntersect.top; iy < rctIntersect.bottom; iy++) {
PixelF* ppxlf1 = ppxlfRowStart1;
const PixelF* ppxlf2 = ppxlfRowStart2;
for (CoordI ix = rctIntersect.left; ix < rctIntersect.right; ix++) {
assert (*ppxlf1 == (PixelF) transpValue || *ppxlf1 == (PixelF) opaqueValue);
assert (*ppxlf2 == (PixelF) transpValue || *ppxlf2 == (PixelF) opaqueValue);
if (*ppxlf2 == transpValue)
*ppxlf1 = (PixelF) transpValue;
ppxlf1++;
ppxlf2++;
}
ppxlfRowStart1 += where().width;
ppxlfRowStart2 += fi.where().width;
}
}
Void CFloatImage::maskOut (const CFloatImage& fi)
{
CRct rctIntersect = m_rc;
rctIntersect.clip (fi.where());
if (!rctIntersect.valid () || rctIntersect.empty ()) return;
PixelF* ppxlfRowStart = (PixelF*) pixels (rctIntersect.left, rctIntersect.top);
const PixelF* ppxlfRowStartMask = fi.pixels (rctIntersect.left, rctIntersect.top);
for (CoordI iy = rctIntersect.top; iy < rctIntersect.bottom; iy++) {
PixelF* ppxlf = ppxlfRowStart;
const PixelF* ppxlfMask = ppxlfRowStartMask;
for (CoordI ix = rctIntersect.left; ix < rctIntersect.right; ix++) {
assert (*ppxlfMask == (PixelF) transpValue || *ppxlfMask == (PixelF) opaqueValue);
assert (*ppxlf == (PixelF) transpValue || *ppxlf == (PixelF) opaqueValue);
if (*ppxlfMask == (PixelF) transpValue) {
}
else
*ppxlf = (PixelF) transpValue;
ppxlf++;
ppxlfMask++;
}
ppxlfRowStart += where().width;
ppxlfRowStartMask += fi.where().width;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -