1. 使用了 freeImage 圖像庫進行圖像讀取,保存(如何將圖片轉為矩陣,如何處理圖片的顏色(rgb),透明等信息)
2. 圖像旋轉
3. 高斯圖像濾波
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include "FreeImage.h"
#include <math.h>
#include <time.h>
#pragma comment(lib, "FreeImage.lib")
#define PI 3.141592645
// 自定義一個4字節的結構體
class byte4
{
public:
BYTE r; // 用於存放 red
BYTE g; // 用於存放 green
BYTE b; // 用於存放 blue
BYTE a; // 用於存放 alpha
};
static int maskHeight = 3; // 掩模高度
static int maskWidth = 3; // 掩模寬度
//高斯濾波掩模
float mask[3][3] =
{
{0.0751 , 0.1238 , 0.0751},
{0.1238 , 0.2042 , 0.1238},
{0.0751 , 0.1238 , 0.0751}};
//串行圖像濾波
void cpu_filter(byte4** inbuf, byte4** outbuf, int w, int h)
{
for(int row = 1; row < h - 1; row ++)
{
for(int col = 1; col < w - 1; col ++)
{
outbuf[row][col].r = 0;
outbuf[row][col].g = 0;
outbuf[row][col].b = 0;
outbuf[row][col].a = 0;
float t1 = 0, t2 = 0, t3 = 0, t4 = 0;
for(int i = 0; i < maskHeight; i ++)
for(int j = 0; j < maskWidth; j++)
{
t1 += inbuf[row + i - 1][col + j - 1].r * mask[i][j];
t2 += inbuf[row + i - 1][col + j - 1].g * mask[i][j];
t3 += inbuf[row + i - 1][col + j - 1].b * mask[i][j];
t4 += inbuf[row + i - 1][col + j - 1].a * mask[i][j];
}
outbuf[row][col].r = (int)t1;
outbuf[row][col].g = (int)t2;
outbuf[row][col].b = (int)t3;
outbuf[row][col].a = (int)t4;
}
}
}
//CPU旋轉圖像
void cpu_rotate(byte4** inbuf, byte4** outbuf, int w, int h, float angle)
{
if(w % 2 == 0) w --;
if(h % 2 == 0) h --;
int i, j;
int xc = w/2;
int yc = h/2;
float cosTheta = cos(PI * angle/180);
float sinTheta = sin(PI * angle/180);
for(i = 0; i < h; i++)
{
for(j=0; j< w; j++)
{
int xpos = (int)( (i-xc)*cosTheta + (j-yc)*sinTheta + xc );
int ypos = (int)( -(i-xc)*sinTheta + (j-yc)*cosTheta + yc );
if(xpos>=0 && ypos>=0 && xpos<h && ypos < w )
outbuf[xpos][ypos] = inbuf[i][j];
}
}
}
void main(int argc, char* argv)
{
char * imageFile = "lenna.PNG";
// 初始化
FreeImage_Initialise(TRUE);
// 讀取圖像
FIBITMAP * bitmap = FreeImage_Load(FIF_PNG, imageFile, PNG_DEFAULT);
if(bitmap) printf("Image Load successfully!\n");
// 獲得圖像的寬和高(像素)
int width = FreeImage_GetWidth(bitmap);
int height = FreeImage_GetHeight(bitmap);
// 計算每個像素的字節數
/************************************************************************/
/* 已經測試有JPEG格式:每像素字節數3 */
/* 已經測試有JPEG格式:每像素字節數4 */
/************************************************************************/
int bytespp = FreeImage_GetLine(bitmap)/ width;
printf("Width:%d\t Height:%d\t 每像素字節數:%d\n", width, height, bytespp);
// 測試 int, float, byte4的各自的字節數
printf("int: %d \nfloat: %d\nbyte4: %d\n", sizeof(int), sizeof(float), sizeof(byte4));
// 用於存放像素值得矩陣
byte4 **matrix;
// 動態開辟2維數組
matrix = (byte4 **)calloc(height, sizeof(byte4*));
for(int i = 0; i < height; i++)
{
matrix[i] = (byte4*)calloc(width, sizeof(byte4));
}
// 用於存放輸出像素值矩陣
byte4 ** matrix_dst;
// 動態開辟2維數組
matrix_dst = (byte4 **)calloc(height, sizeof(byte4*));
for(int i = 0; i < height; i++)
{
matrix_dst[i] = (byte4*)calloc(width, sizeof(byte4));
}
if(matrix && matrix_dst)
printf("內存申請成功!\n");
for(unsigned y = 0; y < height; y++)
{
BYTE *bitsLine = FreeImage_GetScanLine(bitmap, y);
for(unsigned x = 0; x < width; x++)
{
// 設置像素顏色
matrix[y][x].r = bitsLine[FI_RGBA_RED] ;
matrix[y][x].g = bitsLine[FI_RGBA_GREEN] ;
matrix[y][x].b = bitsLine[FI_RGBA_BLUE] ;
matrix[y][x].a = bitsLine[FI_RGBA_ALPHA] ;
bitsLine += bytespp;
}
}
// 執行旋轉, 濾波
int start = clock();
// cpu_rotate(matrix, matrix_dst, width, height, 90); cpu_filter(matrix, matrix_dst, width, height); printf("Time elapsed: %d ms\n", (clock() - start)); // 輸出FreeImage 圖像
FIBITMAP * dst = bitmap;
for(unsigned y = 0; y < height; y++)
{
BYTE *bitsLine = FreeImage_GetScanLine(dst, y);
for(unsigned x = 0; x < width; x++)
{
// 設置像素顏色
bitsLine[FI_RGBA_RED] = matrix_dst[y][x].r ;
bitsLine[FI_RGBA_GREEN] = matrix_dst[y][x].g ;
bitsLine[FI_RGBA_BLUE] = matrix_dst[y][x].b ;
bitsLine[FI_RGBA_ALPHA] = matrix_dst[y][x].a ;
bitsLine += bytespp;
}
}
// 存儲圖像
FreeImage_Save(FIF_PNG, dst, "dst.png", PNG_DEFAULT);
getchar();
}