10#include "matrixCTA.hpp"
12#include "fimImgTransMap.hpp"
13#include "FgSerial.hpp"
14#include "FgMatrixC.hpp"
24 const FimImgRgbaUbC & src,
30 const FimImgRgbaUbC & img,
36 const FimImgRgbaFC & img,
42 const FimImgRgbaUbC & src,
47 const FimImgRgbaFC & src,
51fgImgShrinkInt(
const FimImgRgbaUbC& src,FimImgRgbaUbC& dst,uint factor);
58 const FimImgRgbaFC & src,
68template<
class T,
class U>
74 FGASSERT(img.imageAllocated());
75 uint wid = img.width(),
80 T *ptr = img.imageData();
81 uint step = img.widthStepType();
83 if (wid == ((wid >> 2) << 2))
85 for (uint yy=0; yy<hgt; yy++)
87 for (uint xx=0; xx<wid; xx+=4)
89 opArgs.opUnary(ptr[xx]);
90 opArgs.opUnary(ptr[xx+1]);
91 opArgs.opUnary(ptr[xx+2]);
92 opArgs.opUnary(ptr[xx+3]);
99 uint wid2 = ((wid >> 2) << 2);
100 for (uint yy=0; yy<hgt; yy++)
102 for (uint xx=0; xx<wid2 && wid2>=4; xx+=4)
104 opArgs.opUnary(ptr[xx]);
105 opArgs.opUnary(ptr[xx+1]);
106 opArgs.opUnary(ptr[xx+2]);
107 opArgs.opUnary(ptr[xx+3]);
109 for (uint xx2=wid2; xx2<wid; ++xx2)
111 opArgs.opUnary(ptr[xx2]);
120template<
class T1,
class T2,
class U>
126 FGASSERT(img1.imageAllocated());
127 uint wid = img1.width(),
129 img2.resize(wid,hgt);
131 T1 * img1ptr = img1.imageData();
132 T2 * img2Ptr = img2.imageData();
133 uint img1step = img1.widthStepType(),
134 img2Step = img2.widthStepType();
136 for (uint yy=0; yy<hgt; yy++)
138 for (uint xx=0; xx<wid; xx++)
140 opArgs.opBinary(img1ptr[xx],img2Ptr[xx]);
148template<
class T1,
class T2,
class U>
151 const FimImgT<T1> & img1,
154 FGASSERT(img1.imageAllocated());
155 uint wid = img1.width(),
157 img2.resize(wid,hgt);
159 const T1 * img1ptr = img1.imageData();
160 T2 * img2Ptr = img2.imageData();
161 uint img1step = img1.widthStepType(),
162 img2Step = img2.widthStepType();
164 for (uint yy=0; yy<hgt; yy++)
166 for (uint xx=0; xx<wid; xx++)
168 opArgs.opBinary(img1ptr[xx],img2Ptr[xx]);
176template<
class T1,
class T2,
class U>
179 const FimImgT<T1> & img1,
180 const FimImgT<T2> & img2)
182 FGASSERT(img1.imageAllocated());
183 uint wid = img1.width(),
185 FGASSERT(img1.width() == img2.width());
186 FGASSERT(img1.height() == img2.height());
188 const T1 * img1ptr = img1.imageData();
189 const T2 * img2Ptr = img2.imageData();
190 uint img1step = img1.widthStepType(),
191 img2Step = img2.widthStepType();
193 for (uint yy=0; yy<hgt; yy++)
195 for (uint xx=0; xx<wid; xx++)
197 opArgs.opBinary(img1ptr[xx],img2Ptr[xx]);
205template<
class T1,
class T2,
class T3,
class U>
209 const FimImgT<T1> & img1,
210 const FimImgT<T2> & img2,
213 FGASSERT(img1.imageAllocated());
214 FGASSERT(img2.imageAllocated());
215 uint wid = img1.width(),
217 FGASSERT(wid == img2.width());
218 FGASSERT(hgt == img2.height());
219 img3.resize(wid,hgt);
221 T1 *img1ptr = (T1 *)img1.imageData();
222 T2 *img2Ptr = (T2 *)img2.imageData();
223 T3 *img3Ptr = (T3 *)img3.imageData();
224 uint img1step = img1.widthStepType(),
225 img2Step = img2.widthStepType(),
226 img3Step = img3.widthStepType();
228 for (uint yy=0; yy<hgt; yy++)
230 for (uint xx=0; xx<wid; xx++)
232 opArgs.opTernary(img1ptr[xx],img2Ptr[xx],img3Ptr[xx]);
248 void opBinary(T
const &a,T &b)
270 void opTernary(T
const &a,T
const &b,T &c)
283 dst.resize(src1.width(),src1.height());
296 acc.
c[FIMRGBA_R] += (float)inp.
c[FIMRGBA_R];
297 acc.
c[FIMRGBA_G] += (float)inp.
c[FIMRGBA_G];
298 acc.
c[FIMRGBA_B] += (float)inp.
c[FIMRGBA_B];
299 acc.
c[FIMRGBA_A] += (float)inp.
c[FIMRGBA_A];
303inline void fimAlphaAcc(
321 void opBinary(schar src,uchar &dst)
323 dst = (uchar)((
int)src + val);
327inline void fimAddConvert(
333 dst.resize(src.width(),src.height());
343 void opBinary(
float src,uchar &dst)
345 dst = (uchar)((
float)src + val);
349inline void fimAddConvert(
355 dst.resize(src.width(),src.height());
362inline uchar fimOpAffineGamma(uchar a,
float gamma,
float black,
float gain)
364 float ftmp = ((float)a - black) * gain / 255.0f;
365 if (ftmp < 0.0) ftmp = 0.0f;
366 if (ftmp > 1.0) ftmp = 1.0f;
367 ftmp = pow(ftmp,gamma);
368 return (uchar)(ftmp * 255.0f + 0.5f);
378 gamma(gam), black(blk), gain(gn) {};
382 a.
c[FIMRGBA_R] = fimOpAffineGamma(a.
c[FIMRGBA_R],gamma,black,gain);
383 a.
c[FIMRGBA_G] = fimOpAffineGamma(a.
c[FIMRGBA_B],gamma,black,gain);
384 a.
c[FIMRGBA_B] = fimOpAffineGamma(a.
c[FIMRGBA_A],gamma,black,gain);
410 if (val.
c[FIMRGBA_A] < 128.0f)
419 float alpha = val.
c[FIMRGBA_A];
420 val.
c[FIMRGBA_R] = val.
c[FIMRGBA_R] * 255.0f / alpha;
421 val.
c[FIMRGBA_G] = val.
c[FIMRGBA_G] * 255.0f / alpha;
422 val.
c[FIMRGBA_B] = val.
c[FIMRGBA_B] * 255.0f / alpha;
423 val.
c[FIMRGBA_A] = 255.0f;
444 if (i.
c[FIMRGBA_A] < 255.0f)
471 d.
c[FIMRGBA_A] = s.
c[FIMRGBA_A] & d.
c[FIMRGBA_A];
475inline void fimAndAlpha(
480 dst.resize(src.width(),src.height());
492inline FimRgbaUbC fimScaledPixelAdd4(
493 FimRgbaUbC pix1, FimRgbaUbC pix2, FimRgbaUbC pix3, FimRgbaUbC pix4,
494 double scale1,
double scale2,
double scale3,
double scale4)
497 for (
int clr=0; clr<FIMRGBA_SIZE; ++clr)
499 retval.c[clr] = (uchar)(0.5 + (
double) pix1.c[clr] * scale1 +
500 (double) pix2.c[clr] * scale2 +
501 (
double) pix3.c[clr] * scale3 +
502 (double) pix4.c[clr] * scale4 );
507inline uchar fimScaledPixelAdd4(
508 uchar pix1, uchar pix2, uchar pix3, uchar pix4,
509 double scale1,
double scale2,
double scale3,
double scale4)
511 return ( (uchar)(0.5 + (
double) pix1 * scale1 +
512 (
double) pix2 * scale2 +
513 (
double) pix3 * scale3 +
514 (
double) pix4 * scale4) );
517inline schar fimScaledPixelAdd4(
518 schar pix1, schar pix2, schar pix3, schar pix4,
519 double scale1,
double scale2,
double scale3,
double scale4)
521 return ( (schar)((
double) pix1 * scale1 +
522 (
double) pix2 * scale2 +
523 (
double) pix3 * scale3 +
524 (
double) pix4 * scale4) );
527inline short fimScaledPixelAdd4(
528 short pix1,
short pix2,
short pix3,
short pix4,
529 double scale1,
double scale2,
double scale3,
double scale4)
531 return ( (
short)((
double) pix1 * scale1 +
532 (
double) pix2 * scale2 +
533 (
double) pix3 * scale3 +
534 (
double) pix4 * scale4) );
537inline long fimScaledPixelAdd4(
538 long pix1,
long pix2,
long pix3,
long pix4,
539 double scale1,
double scale2,
double scale3,
double scale4)
541 return ( (
long)((
double) pix1 * scale1 +
542 (
double) pix2 * scale2 +
543 (
double) pix3 * scale3 +
544 (
double) pix4 * scale4) );
547inline float fimScaledPixelAdd4(
548 float pix1,
float pix2,
float pix3,
float pix4,
549 double scale1,
double scale2,
double scale3,
double scale4)
551 return ( (
float)((
double) pix1 * scale1 +
552 (
double) pix2 * scale2 +
553 (
double) pix3 * scale3 +
554 (
double) pix4 * scale4) );
557inline double fimScaledPixelAdd4(
558 double pix1,
double pix2,
double pix3,
double pix4,
559 double scale1,
double scale2,
double scale3,
double scale4)
561 return ( pix1 * scale1 + pix2 * scale2 + pix3 * scale3 + pix4 * scale4 );
566bool fimBilinearOversample(
568 const FimImgT<T> &src,
580 if (fr2Log2Floor(scale) != fr2Log2Ceil(scale))
584 int newWidth = src.width() * scale;
585 int newHeight = src.height() * scale;
586 dst.resize(newWidth,newHeight);
589 int denorm = scale*2;
590 double oneOverDenormSqr = 1.0 / (double)(denorm*denorm);
591 Svec<Mat22D> factors; factors.reserve(scale*scale);
592 for (
int rr=0, rfactor=denorm-1, ii=0; rr<scale; ++rr, rfactor-=2) {
593 for (
int cc=0, cfactor=denorm-1; cc<scale; ++cc, cfactor-=2, ++ii) {
594 factors.emplace_back(
595 (
double)(cfactor*rfactor) * oneOverDenormSqr,
596 (
double)((denorm-cfactor)*rfactor) * oneOverDenormSqr,
597 (double)(cfactor*(denorm-rfactor)) * oneOverDenormSqr,
598 (
double)((denorm-cfactor)*(denorm-rfactor)) * oneOverDenormSqr);
602 uint dstRowWidth = dst.widthStepType();
603 uint dstRowWidthBytes = dst.widthStepByte();
604 uint srcRowWidth = src.widthStepType();
607 int halfScale = scale / 2;
608 T
const *srcPtr = src.imageData();
609 T *dstPtr = dst.imageData() + halfScale*dstRowWidth;
611 for (
int dstRow=halfScale, rCount=0; dstRow<newHeight-halfScale; ++dstRow)
613 T
const *srcPtr2 = srcPtr + srcRowWidth;
614 int idx1 = ((dstRow-halfScale) % scale) * scale;
616 for (
int dstCol=halfScale, srcCol=0, cCount=0;
617 dstCol<newWidth-halfScale; ++dstCol)
619 int ii = idx1 + ((dstCol-halfScale) % scale);
621 dstPtr[dstCol] = fimScaledPixelAdd4(
622 srcPtr[srcCol], srcPtr[srcCol+1],
623 srcPtr2[srcCol], srcPtr2[srcCol+1],
624 factors[ii].rc(0,0), factors[ii].rc(0,1),
625 factors[ii].rc(1,0), factors[ii].rc(1,1));
635 dstPtr += dstRowWidth;
640 srcPtr += srcRowWidth;
645 T *dstPtr1 = dst.imageData();
646 T *dstPtr2 = dst.imageData()+dstRowWidth*(newHeight-1);
647 T *dstSrc1 = dst.imageData()+dstRowWidth*halfScale;
648 T *dstSrc2 = dst.imageData()+dstRowWidth*(newHeight-1-halfScale);
649 for (
int dstRow=0; dstRow<halfScale; ++dstRow)
651 memcpy(dstPtr1,dstSrc1,dstRowWidthBytes);
652 memcpy(dstPtr2,dstSrc2,dstRowWidthBytes);
653 dstPtr1 += dstRowWidth;
654 dstPtr2 -= dstRowWidth;
656 dstPtr1 = dst.imageData();
657 dstPtr2 = dst.imageData()+newWidth-halfScale;
658 dstSrc1 = dst.imageData()+halfScale;
659 dstSrc2 = dst.imageData()+newWidth-1-halfScale;
660 for (
int dstRow=0; dstRow<newHeight; ++dstRow)
662 for (
int dstCol=0; dstCol<halfScale; ++dstCol)
664 dstPtr1[dstCol] = dstSrc1[0];
665 dstPtr2[dstCol] = dstSrc2[0];
667 dstPtr1 += dstRowWidth;
668 dstPtr2 += dstRowWidth;
669 dstSrc1 += dstRowWidth;
670 dstSrc2 += dstRowWidth;
679template<
class T,
class U>
690template<
class T,
class U>
696 dst.resize(src.width(),src.height());
706 const FimImgT<T> &src,
709 FGASSERT(src.imageAllocated());
710 FGASSERT((src.width() > 0) && (src.height() > 0));
712 dst.resize(src.width(),src.height());
714 memcpy(dst.imageData(),src.imageData(),src.widthStepByte() * src.height());
722 const FimImgRgbaFC & src,
734fimCopyAlphaMaskThresh(
735 const FimImgRgbaFC & src,
736 const FimImgRgbaFC & alpha,
739 FGASSERT(src.height() == alpha.height());
740 dst.resize(src.width(),src.height());
741 for (uint row=0; row<src.height(); ++row)
743 for (uint col=0; col<src.width(); ++col)
745 if (alpha[row][col].c[FIMRGBA_A] == 0.0f)
747 dst[row][col] = src[row][col];
751 float * dstPtr = &(dst[row][col].c[0]);
775 FGASSERT(src.imageAllocated());
776 FGASSERT((xh >= xl) && (yh >= yl));
777 FGASSERT((src.width() > xh) && (src.height() > yh));
779 dst.resize(xh-xl+1,yh-yl+1);
781 T *srcPtr = (T *)src.imageData();
782 T *dstPtr = (T *)dst.imageData();
783 uint srcStep = src.widthStepType(),
784 dstStep = dst.widthStepType(),
785 dstByte = dst.width() *
sizeof(T);
787 srcPtr += yl * srcStep;
788 for (uint ii=yl; ii<=yh; ii++)
790 memcpy(dstPtr,&(srcPtr[xl]),dstByte);
813 tot += double(i1.
c[FIMRGBA_R]) * double(i2.
c[FIMRGBA_R]) +
814 double(i1.
c[FIMRGBA_G]) * double(i2.
c[FIMRGBA_G]) +
815 double(i1.
c[FIMRGBA_B]) * double(i2.
c[FIMRGBA_B]);
825 val = fimLoopBinary(val,i1,i2);
856template<
class T,
class U>
864 futConvert(in.
c[channel],out);
868template<
class T,
class U>
869inline void fimGetChannel(
875 FGASSERT(channel < 4);
876 dst.resize(src.width(),src.height());
892 p.
c[FIMRGBA_R] = lut[p.
c[FIMRGBA_R]];
893 p.
c[FIMRGBA_G] = lut[p.
c[FIMRGBA_G]];
894 p.
c[FIMRGBA_B] = lut[p.
c[FIMRGBA_B]];
904 FGASSERT(
sizeof(T) <= 2);
919 d.
c[FIMRGBA_R] = lut[s.
c[FIMRGBA_R]];
920 d.
c[FIMRGBA_G] = lut[s.
c[FIMRGBA_G]];
921 d.
c[FIMRGBA_B] = lut[s.
c[FIMRGBA_B]];
922 d.
c[FIMRGBA_A] = s.
c[FIMRGBA_A];
933 FGASSERT(
sizeof(T) <= 2);
950 if (v.
c[FIMRGBA_R] > maxv) maxv = v.
c[FIMRGBA_R];
951 if (v.
c[FIMRGBA_G] > maxv) maxv = v.
c[FIMRGBA_G];
952 if (v.
c[FIMRGBA_B] > maxv) maxv = v.
c[FIMRGBA_B];
953 if (v.
c[FIMRGBA_R] < minv) minv = v.
c[FIMRGBA_R];
954 if (v.
c[FIMRGBA_G] < minv) minv = v.
c[FIMRGBA_G];
955 if (v.
c[FIMRGBA_B] < minv) minv = v.
c[FIMRGBA_B];
962 FGASSERT((img.width() > 0) && (img.height() > 0));
965 v = fimLoopUnary(v,img);
977 void opBinary(
const schar &a,
int &b) {b += val * int(a); };
981inline void fimMultAccConv(
987 imgOut.resize(imgInp.width(),imgInp.height());
992void fimMultAccConvRoi(
994 const FimImgT<schar> &imgInp,
995 FimImgT<int> &imgOut,
1009 p.
c[FIMRGBA_R] = (uchar)((
float)p.
c[FIMRGBA_R] * val + 0.5);
1010 p.
c[FIMRGBA_G] = (uchar)((
float)p.
c[FIMRGBA_G] * val + 0.5);
1011 p.
c[FIMRGBA_B] = (uchar)((
float)p.
c[FIMRGBA_B] * val + 0.5);
1018 fimMaxMin(img,max,min);
1020 fimLoopUnary(r,img);
1042 val += sqr(
double(i2.
c[FIMRGBA_R]) -
double(i1.
c[FIMRGBA_R]));
1043 val += sqr(
double(i2.
c[FIMRGBA_G]) -
double(i1.
c[FIMRGBA_G]));
1044 val += sqr(
double(i2.
c[FIMRGBA_B]) -
double(i1.
c[FIMRGBA_B]));
1054 FGASSERT(i1.width() == i2.width());
1055 FGASSERT(i1.height() == i2.height());
1057 val = fimLoopBinary(val,i1,i2);
1064template <
typename T>
1068 const FimImgT<T> &src,
1071 uint srcWidth = src.width();
1072 uint srcHeight = src.height();
1075 FGASSERT(srcHeight);
1077 if (srcWidth == 0 || srcHeight == 0)
return;
1079 uint dstWidth = srcHeight;
1080 uint dstHeight = srcWidth;
1082 dst.resize(dstWidth,dstHeight);
1084 uint dstRowSize = dst.widthStepType();
1085 T *dstPtr = dst.imageData();
1086 uint srcRowSize = src.widthStepType();
1090 for (uint dstRow=0; dstRow<dstHeight; ++dstRow)
1092 T
const *srcPtr = src.imageData() + srcWidth-1 - dstRow;
1093 for (uint dstCol=0; dstCol<dstWidth; ++dstCol)
1095 dstPtr[dstCol] = *srcPtr;
1096 srcPtr += srcRowSize;
1098 dstPtr += dstRowSize;
1103 for (uint dstRow=0; dstRow<dstHeight; ++dstRow)
1105 T
const *srcPtr = src.imageData() + srcRowSize * (srcHeight-1)
1107 for (uint dstCol=0; dstCol<dstWidth; ++dstCol)
1109 dstPtr[dstCol] = *srcPtr;
1110 srcPtr -= srcRowSize;
1112 dstPtr += dstRowSize;
1120template<
class T,
class U>
1128 futConvert(in,out.
c[channel]);
1132template<
class T,
class U>
1133inline void fimSetChannel(
1139 FGASSERT(channel < 4);
1140 dst.resize(src.width(),src.height());
1154 pix.
c[channel] = val;
1159inline void fimSetChannel(
1165 FGASSERT(channel < FIMRGBA_SIZE);
1176 out.
c[FIMRGBA_R] = fgClampToSchar(
int(out.
c[FIMRGBA_R]) +
int(i1.
c[FIMRGBA_R]) -
int(i2.
c[FIMRGBA_R]));
1177 out.
c[FIMRGBA_G] = fgClampToSchar(
int(out.
c[FIMRGBA_G]) +
int(i1.
c[FIMRGBA_G]) -
int(i2.
c[FIMRGBA_G]));
1178 out.
c[FIMRGBA_B] = fgClampToSchar(
int(out.
c[FIMRGBA_B]) +
int(i1.
c[FIMRGBA_B]) -
int(i2.
c[FIMRGBA_B]));
1179 out.
c[FIMRGBA_A] = 0;
1200 out.
c[FIMRGBA_R] = i1.
c[FIMRGBA_R] - i2.
c[FIMRGBA_R];
1201 out.
c[FIMRGBA_G] = i1.
c[FIMRGBA_G] - i2.
c[FIMRGBA_G];
1202 out.
c[FIMRGBA_B] = i1.
c[FIMRGBA_B] - i2.
c[FIMRGBA_B];
1203 out.
c[FIMRGBA_A] = 0.0f;
1224 ImageInterp(uint sourceWid,uint sourceHgt,uint destRatio) :
1225 wid(sourceWid), hgt(sourceHgt), ratio(destRatio) {};
1226 void setPoint(uint destX,uint destY)
1228 uint yy = ((destY << 4) + 8) / ratio,
1229 xx = ((destX << 4) + 8) / ratio;
1230 int xhi = int((xx+8) & 0xFFFFFFF0), xlo = xhi - 16,
1231 yhi = int((yy+8) & 0xFFFFFFF0), ylo = yhi - 16;
1232 xlu = xlo < 0 ? 0 : xlo >> 4;
1233 ylu = ylo < 0 ? 0 : ylo >> 4;
1234 uint xht = xhi >> 4,
1236 xhu = (xht >= wid) ? xlu : xht;
1237 yhu = (yht >= hgt) ? ylu : yht;
1238 xlw = xhi + 8 - xx; xhw = 16 - xlw,
1239 ylw = yhi + 8 - yy; yhw = 16 - ylw;
1243 template<
typename PixelType>
1244 typename PixelType::pixel_index_type
1245 getVal(
const PixelType *srcImg,uint clr)
1247 typedef typename PixelType::pixel_index_type pixel_index_t;
1248 uint val = srcImg[yindl+xlu].c[clr] * xlw * ylw +
1249 srcImg[yindl+xhu].c[clr] * xhw * ylw +
1250 srcImg[yindh+xlu].c[clr] * xlw * yhw +
1251 srcImg[yindh+xhu].c[clr] * xhw * yhw;
1252 return pixel_index_t(val >> 8);
1258 uint xlu,xhu,ylu,yhu;
1259 uint xlw,xhw,ylw,yhw;