简单实现, 仅限单通道图像
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video { margin: 0; padding: 0; border: 0 }
body { font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 1.6; color: #333; background-color: #fff; padding: 20px; max-width: 960px; margin: 0 auto }
body>*:first-child { margin-top: 0 !important }
body>*:last-child { margin-bottom: 0 !important }
p,blockquote,ul,ol,dl,table,pre { margin: 15px 0 }
h1,h2,h3,h4,h5,h6 { margin: 20px 0 10px; padding: 0; font-weight: bold }
h1 tt,h1 code,h2 tt,h2 code,h3 tt,h3 code,h4 tt,h4 code,h5 tt,h5 code,h6 tt,h6 code { font-size: inherit }
h1 { font-size: 28px; color: #000 }
h2 { font-size: 24px; border-bottom: 1px solid #ccc; color: #000 }
h3 { font-size: 18px }
h4 { font-size: 16px }
h5 { font-size: 14px }
h6 { color: #777; font-size: 14px }
body>h2:first-child,body>h1:first-child,body>h1:first-child+h2,body>h3:first-child,body>h4:first-child,body>h5:first-child,body>h6:first-child { margin-top: 0; padding-top: 0 }
a:first-child h1,a:first-child h2,a:first-child h3,a:first-child h4,a:first-child h5,a:first-child h6 { margin-top: 0; padding-top: 0 }
h1+p,h2+p,h3+p,h4+p,h5+p,h6+p { margin-top: 10px }
a { color: #4183C4; text-decoration: none }
a:hover { text-decoration: underline }
ul,ol { padding-left: 30px }
ul li>:first-child,ol li>:first-child,ul li ul:first-of-type,ol li ol:first-of-type,ul li ol:first-of-type,ol li ul:first-of-type { margin-top: 0px }
ul ul,ul ol,ol ol,ol ul { margin-bottom: 0 }
dl { padding: 0 }
dl dt { font-size: 14px; font-weight: bold; font-style: italic; padding: 0; margin: 15px 0 5px }
dl dt:first-child { padding: 0 }
dl dt>:first-child { margin-top: 0px }
dl dt>:last-child { margin-bottom: 0px }
dl dd { margin: 0 0 15px; padding: 0 15px }
dl dd>:first-child { margin-top: 0px }
dl dd>:last-child { margin-bottom: 0px }
pre,code,tt { font-size: 12px; font-family: Consolas, "Liberation Mono", Courier, monospace }
code,tt { margin: 0 0px; padding: 0px 0px; white-space: nowrap; border: 1px solid #eaeaea; background-color: #f8f8f8 }
pre>code { margin: 0; padding: 0; white-space: pre; border: none; background: transparent }
pre { background-color: #f8f8f8; border: 1px solid #ccc; font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px }
pre code,pre tt { background-color: transparent; border: none }
kbd { background-color: #DDDDDD; background-image: linear-gradient(#F1F1F1, #DDDDDD); background-repeat: repeat-x; border-color: #DDDDDD #CCCCCC #CCCCCC #DDDDDD; border-style: solid; border-width: 1px; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; line-height: 10px; padding: 1px 4px }
blockquote { border-left: 4px solid #DDD; padding: 0 15px; color: #777 }
blockquote>:first-child { margin-top: 0px }
blockquote>:last-child { margin-bottom: 0px }
hr { clear: both; margin: 15px 0; height: 0px; overflow: hidden; border: none; background: transparent; border-bottom: 4px solid #ddd; padding: 0 }
table th { font-weight: bold }
table th,table td { border: 1px solid #ccc; padding: 6px 13px }
table tr { border-top: 1px solid #ccc; background-color: #fff }
table tr:nth-child(2n) { background-color: #f8f8f8 }
img { max-width: 100% }
双线性插值
双向性差值中,缩放图像(以下称目标图像)的像素的点 P 的强度值取决于相邻4个像素点的加权和。
假设缩放因子为 s, 那么目标图像的像素点可以通过 r, c 来映射源图像,如下所示
那么从感兴趣像素点到原图像像素的距离可如下表示
因此相邻4个像素点可表示为
然后利用上述信息,可以计算出感兴趣像素点值的加权和
代码如下所示:
1 void resize_zoom(unsigned char *pSrc, unsigned char *pDst, int src_stride, int src_height, float zoom_x, float zoom_y) 2 { 3 #define CHECK_BOUNDARY(a, v) ((a) > (v) ? (v):( (a) <0 ? (0):(a) )) 4 if (!(zoom_x > 0 && zoom_y > 0 && src_stride > 0 && src_height > 0 && pSrc != NULL && pDst != NULL)) { 5 printf("input param error..\n"); 6 pDst = NULL; 7 return; 8 } 9 int dst_w = floor(zoom_x * src_stride); 10 int dst_h = floor(zoom_y * src_height); 11 12 for (int h = 0; h < dst_h; h++) { 13 int y1 = CHECK_BOUNDARY(floor(h / zoom_y), src_height); 14 int y2 = CHECK_BOUNDARY(ceil(h / zoom_y), src_height); 15 float y = fmod((h/zoom_y), 1); 16 for (int w = 0; w < dst_w; w++) { 17 int x1 = CHECK_BOUNDARY(floor(w / zoom_x), src_stride); 18 int x2 = CHECK_BOUNDARY(ceil(w / zoom_x), src_stride); 19 float x = fmod((w / zoom_x), 1); 20 unsigned char topLeft = pSrc[y1 * src_stride + x1]; 21 unsigned char botLeft = pSrc[y1 * src_stride + x2]; 22 unsigned char topRight = pSrc[y2 * src_stride + x1]; 23 unsigned char botRight = pSrc[y2 * src_stride + x2]; 24 unsigned int tr = (topRight * y) + (topLeft * (1 - y)); 25 unsigned int br = (botRight * y) + (botLeft * (1 - y)); 26 unsigned int c = (br * x) + (tr * (1 - x)); 27 pDst[h * dst_w + w] = CHECK_BOUNDARY(c, 255); 28 } 29 } 30 #undef CHECK_BOUNDARY 31 }
最近邻插值
最近邻插值算法中,像素点 v(x, y) 的强度取决于该点映射到源图像素点 f(x, y) 相邻像素的强度值。
具体实现逻辑如下
1 void nnbr(unsigned char *pSrc, unsigned char *pDst, int src_stride, int src_height, float zoom_x, float zoom_y) 2 { 3 #define CHECK_BOUNDARY(a, v) ((a) > (v) ? (v):( (a) <0 ? (0):(a) )) 4 if (!(zoom_x > 0 && zoom_y > 0 && src_stride > 0 && src_height > 0 && pSrc != NULL && pDst != NULL)) { 5 printf("input param error..\n"); 6 pDst = NULL; 7 return; 8 } 9 int dst_w = floor(zoom_x * src_stride); 10 int dst_h = floor(zoom_y * src_height); 11 12 for (int h = 0; h < dst_h; h++) { 13 int near_h = CHECK_BOUNDARY(floor(h / zoom_y), src_height); 14 for (int w = 0; w < dst_w; w++) { 15 int near_w = CHECK_BOUNDARY(floor(w / zoom_x), src_stride); 16 unsigned int c = pSrc[near_h * src_stride + near_w]; 17 pDst[h * dst_w + w] = CHECK_BOUNDARY(c, 255); 18 } 19 } 20 #undef CHECK_BOUNDARY 21 }