原文地址:https://blog.csdn.net/mcgrady_tracy/article/details/46625367
对于图像缩放算法来说,最近临插值算法是最简单的。最近临插值算法的原理是在原图像中找到最近临的一个点,然后把这个点的像素值插入到目标图像中,最近临插值算法优点是算法简单,易于实现,但是缺点是由于相邻像素点的像素值相同,容易出现色块现象。
那么如何在原图像中找这个目标点呢,算法公式如下:
src_x = dst_x * (src_width / dst_width); src_y = dst_y * (src_height / dst_height);
那么算出来呢,可能会是小数点,需要四舍五入取整,那么下面来看一个例子(一个3*3的矩阵):
234 38 22 67 44 12 89 65 63
这里呢,我们需要将上面的一个3*3矩阵变换成一个4*4的矩阵,我们根据上面的公式来计算一下,首先是目标点为(0,0),那么原图像的坐标点为(0,0),那么这个坐标点的值就应该为234,然后再来看(0,1)这个坐标点,那么纵坐标点还是0,但是横坐标点变成了1*(3/4) = 0.75,四舍五入得1,那么得到的原图像坐标为(0,1),那么这个坐标点值就应该为38,同理,最后得到的矩阵结果如下:
234 38 22 22 67 44 12 12 89 65 63 63 89 65 63 63
这部分测试代码如下:
- #include <stdio.h>
- int main(int argc, char *argv[])
- {
- int i, j, row, col;
- unsigned char mat1[3][3] = {{234, 38, 22},
- {67, 44, 12},
- {89, 65, 63}};
- unsigned char mat2[4][4];
- for (i = 0; i < 4; i++) {
- for (j = 0; j < 4; j++) {
- row = (int)(i * (3.0 / 4.0) + 0.5);
- col = (int)(j * (3.0 / 4.0) + 0.5);
- mat2[i][j] = mat1[row][col];
- printf("%d\t", mat2[i][j]);
- }
- printf("\n");
- }
- return 0;
- }
- #include <stdio.h>
- #include <stdlib.h>
- struct bitmap_fileheader {
- unsigned short type;
- unsigned int size;
- unsigned short reserved1;
- unsigned short reserved2;
- unsigned int off_bits;
- } __attribute__ ((packed));
- struct bitmap_infoheader {
- unsigned int size;
- unsigned int width;
- unsigned int height;
- unsigned short planes;
- unsigned short bit_count;
- unsigned int compression;
- unsigned int size_image;
- unsigned int xpels_per_meter;
- unsigned int ypels_per_meter;
- unsigned int clr_used;
- unsigned int clr_important;
- } __attribute__ ((packed));
- void resize_near(void *dst, void *src, int dst_width, int dst_height, int src_width, int src_height)
- {
- int i, j, x, y;
- float scale_x, scale_y;
- char *buf1 = (char *)src, *buf2 = (char *)dst;
- scale_x = (float)src_width / (float)dst_width;
- scale_y = (float)src_height / (float)dst_height;
- for (i = 0; i < dst_height; i++) {
- for (j = 0; j < dst_width; j++) {
- y = (int)(i * scale_y + 0.5);
- x = (int)(j * scale_x + 0.5);
- buf2[i*dst_width*3 + j*3] = buf1[y*src_width*3 + x*3];
- buf2[i*dst_width*3 + j*3 + 1] = buf1[y*src_width*3 + x*3 + 1];
- buf2[i*dst_width*3 + j*3 + 2] = buf1[y*src_width*3 + x*3 + 2];
- }
- }
- }
- int main(int argc, char *argv[])
- {
- FILE *fp1, *fp2;
- struct bitmap_fileheader fh;
- struct bitmap_infoheader ih;
- void *buf1, *buf2;
- int src_width, src_height, dst_width, dst_height;
- if (argc < 2)
- return -1;
- fp1 = fopen(argv[1], "rb");
- if (fp1 == NULL) {
- printf("open file %s failed!\n", argv[1]);
- return -1;
- }
- fread(&fh, 1, sizeof(struct bitmap_fileheader), fp1);
- fread(&ih, 1, sizeof(struct bitmap_infoheader), fp1);
- src_width = ih.width;
- src_height = ih.height;
- buf1 = malloc(ih.width * ih.height * (ih.bit_count / 8));
- fread(buf1, 1, ih.width * ih.height * (ih.bit_count / 8), fp1);
- fp2 = fopen("resize.bmp", "wb");
- if (fp2 == NULL) {
- printf("open file resize.bmp failed!\n");
- return -1;
- }
- dst_width = src_width * 2;
- dst_height = src_height * 2;
- ih.width = dst_width;
- ih.height = dst_height;
- fh.size = fh.off_bits + ih.width * ih.height * (ih.bit_count / 8);
- fwrite(&fh, 1, sizeof(struct bitmap_fileheader), fp2);
- fwrite(&ih, 1, sizeof(struct bitmap_infoheader), fp2);
- buf2 = malloc(ih.width * ih.height * (ih.bit_count / 8));
- resize_near(buf2, buf1, dst_width, dst_height, src_width, src_height);
- fwrite(buf2, 1, ih.width * ih.height * (ih.bit_count / 8), fp2);
- free(buf1);
- free(buf2);
- fclose(fp1);
- fclose(fp2);
- return 0;
- }
如果用opencv来做,那就很简单了,直接使用opencv提供的cvResize函数,代码如下:
- #include <highgui.h>
- #include <cv.h>
- int main(int argc, char *argv[])
- {
- IplImage *img1, *img2;
- if (argc < 2)
- return -1;
- img1 = cvLoadImage(argv[1]);
- img2 = cvCreateImage(CvSize(img1->width*2, img1->height*2), img1->depth, img1->nChannels);
- cvResize(img1, img2, CV_INTER_LINEAR);
- /* CV_INTER_NN
- CV_INTER_LINEAR
- CV_INTER_AREA
- CV_INTER_CUBIC */
- cvSaveImage("test.jpg", img2);
- cvReleaseImage(&img1);
- cvReleaseImage(&img2);
- return 0;
- }