template<class _mm,bool chroma,bool avih,bool uniform> void TimgFilterNoise::addNoise(const unsigned char *src,stride_t srcStride,unsigned char *dst,stride_t dstStride,unsigned int dx,unsigned int dy,short *noiseMask,stride_t noiseMaskStride,int noiseStrength) { typename _mm::__m noisenext64; if (!avih) { noisenext64=Tnoise<_mm>::noisenext(); } typename _mm::__m noiseStrength64=_mm::set1_pi16((short)noiseStrength); typename _mm::__m m0=_mm::setzero_si64(),m255=_mm::set1_pi16(255),m128=_mm::set1_pi16(128); for (const unsigned char *srcEnd=src+srcStride*dy; src!=srcEnd; src+=srcStride,dst+=dstStride,noiseMask+=noiseMaskStride) { int x=0; for (; x<int(dx-_mm::size/2+1); x+=_mm::size/2) { typename _mm::__m noise; if (!avih) { noise=noisenext64=_mm::add_pi16(_mm::madd_pi16(noisenext64,Tnoise<_mm>::noiseConst()),Tnoise<_mm>::noiseConst()); noise=_mm::subs_pi16(_mm::and_si64(noise,m255),m128); } else { movVqu(noise, noiseMask+x); //SSE3 } typename _mm::__m noiseMul,src8=_mm::unpacklo_pi8(_mm::load2(src+x),m0); if (uniform) { noiseMul=noise; } else { noiseMul=src8; if (chroma) { noiseMul=_mm::subs_pi16(noiseMul,m128); noiseMul=_mm::slli_pi16(noiseMul,3); } noiseMul=_mm::srai_pi16(_mm::mullo_pi16(noiseMul,noise),8); } if (!avih) { movVqu(noiseMask+x,noiseMul=_mm::srai_pi16(_mm::mullo_pi16(noiseMul,noiseStrength64),8)); } _mm::store2(dst+x,_mm::packs_pu16(_mm::add_pi16(noiseMul,src8),m0)); } for (; x<(int)dx; x++) { int mm1; if (!avih) { typename _mm::integer2_t val; _mm::store2(&val,noisenext64=_mm::add_pi16(_mm::madd_pi16(noisenext64,Tnoise<_mm>::noiseConst()),Tnoise<_mm>::noiseConst())); mm1=(char)val; } else { mm1=(char)noiseMask[x]; } int mm0,mm7=src[x]; if (uniform) { mm0=mm1; } else { mm0=mm7; if (chroma) { mm0-=128; } mm0=(mm0*mm1)>>8; } if (!avih) { noiseMask[x]=(short)(mm0=(mm0*noiseStrength)>>8); } dst[x]=limit_uint8(mm0+mm7); } }
LRESULT TlevelsPage::TwidgetCurves::onLbuttonDown(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { if (curpoint==-1 && pt.size()<10) { int x=GET_X_LPARAM(lParam),y=GET_Y_LPARAM(lParam); x=limit_uint8(256*x/dxy); CPoints::iterator p=pt.begin(); for (pt.begin(); p!=pt.end()-1; p++) if ((p+1)->x>x) { break; } p=pt.insert(p+1,CPoint(x,limit_uint8(255-256*y/dxy))); save(); curpoint=int(p-pt.begin()); levelsPage->map2dlg();//InvalidateRect(hwnd,NULL,FALSE); } SetCapture(hwnd); SetCursor(LoadCursor(NULL,IDC_SIZEALL)); dragpoint=curpoint; print(); return 0; }
void TlevelsPage::onCurveLoad(void) { if (dlgGetFile(false,m_hwnd,_(-IDD_LEVELS,_l("Select curve file")),_l("Adobe Photoshop Curves (*.acv)\0*.acv\0All files (*.*)\0*.*\0"),_l("acv"),curvesflnm,_l("."),0)) { FILE *f=fopen(curvesflnm,_l("rb")); if (!f) { return; } int16_t w; if (fread(&w,1,2,f)==2 && av_be2ne16(w)==4) if (fread(&w,1,2,f)==2 && av_be2ne16(w)==5) { int16_t cnt; if (fread(&cnt,1,2,f)==2 && (cnt=av_be2ne16(cnt))>0) { cnt=std::min(cnt,int16_t(10)); cfgSet(IDFF_levelsNumPoints,cnt); std::pair<uint8_t,uint8_t> pts[10]; int numpoints=0; for (int i=0; i<cnt; i++) { int16_t x,y; if (fread(&y,1,2,f)!=2 || fread(&x,1,2,f)!=2) { break; } pts[numpoints].first=limit_uint8(av_be2ne16(x)); pts[numpoints].second=limit_uint8(av_be2ne16(y)); numpoints++; } std::sort(pts,pts+numpoints); for (int i=0; i<numpoints; i++) { cfgSet(TwidgetCurves::idffs[2*i+0],pts[i].first); cfgSet(TwidgetCurves::idffs[2*i+1],pts[i].second); } wCurves->reset(); map2dlg(); } } fclose(f); } }
LRESULT TlevelsPage::TwidgetCurves::onMouseMove(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { if (dragpoint!=-1) { int x=256*GET_X_LPARAM(lParam)/dxy; int y=255-256*GET_Y_LPARAM(lParam)/dxy; static const int border=40; if (pt.size()>2 && (!isIn(x,0-border,255+border) || !isIn(y,0-border,255+border))) { pt.erase(pt.begin()+curpoint); curpoint=-1; onLbuttonUp(hwnd,uMsg,wParam,lParam); } else { pt[dragpoint].x=limit(x,int(dragpoint==0?0:pt[dragpoint-1].x),int(dragpoint==(int)pt.size()-1?255:pt[dragpoint+1].x)); pt[dragpoint].y=limit_uint8(y); } save(); levelsPage->map2dlg(); return 0; } return TwindowWidget::onMouseMove(hwnd,uMsg,wParam,lParam); }
void TlevelsSettings::plot_curve(int p1, int p2, int p3, int p4, unsigned int curve[256]) { typedef double CRMatrix[4][4]; static const CRMatrix CR_basis = { { -0.5, 1.5, -1.5, 0.5 }, { 1.0, -2.5, 2.0, -0.5 }, { -0.5, 0.0, 0.5, 0.0 }, { 0.0, 1.0, 0.0, 0.0 }, }; struct curves_CR_compose { void operator()(const CRMatrix &a, const CRMatrix &b, CRMatrix &ab) { for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) ab[i][j] = (a[i][0] * b[0][j] + a[i][1] * b[1][j] + a[i][2] * b[2][j] + a[i][3] * b[3][j]); } }; CRMatrix geometry; CRMatrix tmp1, tmp2; CRMatrix deltas; double x, dx, dx2, dx3; double y, dy, dy2, dy3; double d, d2, d3; int lastx, lasty; int newx, newy; int i; /* construct the geometry matrix from the segment */ for (i = 0; i < 4; i++) { geometry[i][2] = 0; geometry[i][3] = 0; } for (i = 0; i < 2; i++) { geometry[0][i] = this->*points[p1][i]; geometry[1][i] = this->*points[p2][i]; geometry[2][i] = this->*points[p3][i]; geometry[3][i] = this->*points[p4][i]; } /* subdivide the curve */ static const int CURVES_SUBDIVIDE = 1000; d = 1.0 / CURVES_SUBDIVIDE; d2 = d * d; d3 = d * d * d; /* construct a temporary matrix for determining the forward * differencing deltas */ tmp2[0][0] = 0; tmp2[0][1] = 0; tmp2[0][2] = 0; tmp2[0][3] = 1; tmp2[1][0] = d3; tmp2[1][1] = d2; tmp2[1][2] = d; tmp2[1][3] = 0; tmp2[2][0] = 6 * d3; tmp2[2][1] = 2 * d2; tmp2[2][2] = 0; tmp2[2][3] = 0; tmp2[3][0] = 6 * d3; tmp2[3][1] = 0; tmp2[3][2] = 0; tmp2[3][3] = 0; /* compose the basis and geometry matrices */ curves_CR_compose()(CR_basis, geometry, tmp1); /* compose the above results to get the deltas matrix */ curves_CR_compose()(tmp2, tmp1, deltas); /* extract the x deltas */ x = deltas[0][0]; dx = deltas[1][0]; dx2 = deltas[2][0]; dx3 = deltas[3][0]; /* extract the y deltas */ y = deltas[0][1]; dy = deltas[1][1]; dy2 = deltas[2][1]; dy3 = deltas[3][1]; lastx = limit_uint8((int)x); lasty = limit_uint8((int)y); curve[lastx] = lasty; /* loop over the curve */ for (i = 0; i < CURVES_SUBDIVIDE; i++) { /* increment the x values */ x += dx; dx += dx2; dx2 += dx3; /* increment the y values */ y += dy; dy += dy2; dy2 += dy3; newx = limit_uint8(int (x)); newy = limit_uint8(int (y)); /* if this point is different than the last one...then draw it */ if ((lastx != newx) || (lasty != newy)) { curve[newx] = newy; } lastx = newx; lasty = newy; } }