// pad A by [pt,pb,pl,pr] and store result in B template<class T> void imPad( T *A, T *B, int h, int w, int d, int pt, int pb, int pl, int pr, int flag, T val ) { int h1=h+pt, hb=h1+pb, w1=w+pl, wb=w1+pr, x, y, z, mPad; int ct=0, cb=0, cl=0, cr=0; if(pt<0) { ct=-pt; pt=0; } if(pb<0) { h1+=pb; cb=-pb; pb=0; } if(pl<0) { cl=-pl; pl=0; } if(pr<0) { w1+=pr; cr=-pr; pr=0; } int *xs, *ys; x=pr>pl?pr:pl; y=pt>pb?pt:pb; mPad=x>y?x:y; bool useLookup = ((flag==2 || flag==3) && (mPad>h || mPad>w)) || (flag==3 && (ct || cb || cl || cr )); // helper macro for padding #define PAD(XL,XM,XR,YT,YM,YB) \ for(x=0; x<pl; x++) for(y=0; y<pt; y++) B[x*hb+y]=A[(XL+cl)*h+YT+ct]; \ for(x=0; x<pl; x++) for(y=pt; y<h1; y++) B[x*hb+y]=A[(XL+cl)*h+YM+ct]; \ for(x=0; x<pl; x++) for(y=h1; y<hb; y++) B[x*hb+y]=A[(XL+cl)*h+YB-cb]; \ for(x=pl; x<w1; x++) for(y=0; y<pt; y++) B[x*hb+y]=A[(XM+cl)*h+YT+ct]; \ for(x=pl; x<w1; x++) for(y=h1; y<hb; y++) B[x*hb+y]=A[(XM+cl)*h+YB-cb]; \ for(x=w1; x<wb; x++) for(y=0; y<pt; y++) B[x*hb+y]=A[(XR-cr)*h+YT+ct]; \ for(x=w1; x<wb; x++) for(y=pt; y<h1; y++) B[x*hb+y]=A[(XR-cr)*h+YM+ct]; \ for(x=w1; x<wb; x++) for(y=h1; y<hb; y++) B[x*hb+y]=A[(XR-cr)*h+YB-cb]; // build lookup table for xs and ys if necessary if( useLookup ) { xs = (int*) wrMalloc(wb*sizeof(int)); int h2=(pt+1)*2*h; ys = (int*) wrMalloc(hb*sizeof(int)); int w2=(pl+1)*2*w; if( flag==2 ) { for(x=0; x<wb; x++) { z=(x-pl+w2)%(w*2); xs[x]=z<w ? z : w*2-z-1; } for(y=0; y<hb; y++) { z=(y-pt+h2)%(h*2); ys[y]=z<h ? z : h*2-z-1; } } else if( flag==3 ) { for(x=0; x<wb; x++) xs[x]=(x-pl+w2)%w; for(y=0; y<hb; y++) ys[y]=(y-pt+h2)%h; } } // pad by appropriate value for( z=0; z<d; z++ ) { // copy over A to relevant region in B for( x=0; x<w-cr-cl; x++ ) memcpy(B+(x+pl)*hb+pt,A+(x+cl)*h+ct,sizeof(T)*(h-ct-cb)); // set boundaries of B to appropriate values if( flag==0 && val!=0 ) { // "constant" for(x=0; x<pl; x++) for(y=0; y<hb; y++) B[x*hb+y]=val; for(x=pl; x<w1; x++) for(y=0; y<pt; y++) B[x*hb+y]=val; for(x=pl; x<w1; x++) for(y=h1; y<hb; y++) B[x*hb+y]=val; for(x=w1; x<wb; x++) for(y=0; y<hb; y++) B[x*hb+y]=val; } else if( useLookup ) { // "lookup" PAD( xs[x], xs[x], xs[x], ys[y], ys[y], ys[y] ); } else if( flag==1 ) { // "replicate" PAD( 0, x-pl, w-1, 0, y-pt, h-1 ); } else if( flag==2 ) { // "symmetric" PAD( pl-x-1, x-pl, w+w1-1-x, pt-y-1, y-pt, h+h1-1-y ); } else if( flag==3 ) { // "circular" PAD( x-pl+w, x-pl, x-pl-w, y-pt+h, y-pt, y-pt-h ); } A += h*w; B += hb*wb; } if( useLookup ) { wrFree(xs); wrFree(ys); } #undef PAD }
// platform independent aligned memory allocation (see also alFree) void* alMalloc( size_t size, int alignment ) { const size_t pSize = sizeof(void*), a = alignment-1; void *raw = wrMalloc(size + a + pSize); void *aligned = (void*) (((size_t) raw + pSize + a) & ~a); *(void**) ((size_t) aligned-pSize) = raw; return aligned; }
oT* rgbConvert(iT* I, int n, int d, int flag, oT nrm) { oT* J = (oT*)wrMalloc(n * (flag == 0 ? (d == 1 ? 1 : d / 3) : d) * sizeof(oT)); int i, n1 = d * (n < 1000 ? n / 10 : 100); oT thr = oT(1.001); if (flag > 1 && nrm == 1) for (i = 0; i < n1; i++) if (I[i] > thr) wrError("For floats all values in I must be smaller than 1."); bool useSse = n % 4 == 0 && typeid(oT) == typeid(float); if (flag == 2 && useSse) for (i = 0; i < d / 3; i++) rgb2luv_sse(I + i * n * 3, (float*)(J + i * n * 3), n, (float)nrm); else if ((flag == 0 && d == 1) || flag == 1) normalize(I, J, n * d, nrm); else if (flag == 0) for (i = 0; i < d / 3; i++) rgb2gray(I + i * n * 3, J + i * n * 1, n, nrm); else if (flag == 2) for (i = 0; i < d / 3; i++) rgb2luv(I + i * n * 3, J + i * n * 3, n, nrm); else if (flag == 3) for (i = 0; i < d / 3; i++) rgb2hsv(I + i * n * 3, J + i * n * 3, n, nrm); else wrError("Unknown flag."); return J; }