硬件准备
ADSP-EDU-BF533:BF533开发板
AD-HP530ICE:ADI DSP仿真器
软件准备
Visual DSP++软件
硬件链接
功能介绍
代码实现了图像的平滑处理(高斯模板),代码运行时,会通过文件系统打开工程文件根目下" …/ImageView"路径中的 testin.bmp 文件,进行图像的平滑处理(高斯模板)后把图片保存到工程文件根目下" …/ImageView"路径中的testout.bmp 文件,并且将处理后的图片显示到液晶屏上。例子中的算法只支持尺寸为 480*272 的 24bit 的 bmp 图片,可以根据自己的需要自行调整。
代码使用说明
funct.c 中的 StenciFilter(BMPIMAGE* img)
该函数是将读取的图像进行平滑处理。
BMPIMAGE * 图像结构体指针
在 main.c 文件中定义了一个#define LCD_VIEW_ENABLE 宏开关,如果不需要将处理后的图片显示在液晶屏上,只需将这个宏开关注释掉。
代码实验步骤
- 将工程文件根目下的 ImageView 文件夹内存放一个名为 testin.bmp 的图像文件,该文件尺寸为 480*272 的24bit 的 bmp 图片(默认已存一幅测试图片)。
- 打开工程文件 BF53x_StenciFilter.dpj,编译并运行代码
- 等待图像处理,处理完成之后会在液晶屏上显示处理后的图片,并在工程文件根目下的 ImageView 文件夹内生成一个处理后名为 testout.bmp 图片。
代码实验结果
1.液晶屏上显示处理后的图片。
2.在工程文件根目下的 ImageView 文件夹中查看处理后名为 testout.bmp 图片。
程序源码
bmp.c
#include<stdio.h>
#include “bmp.h”
/********************************************************
- 函数名 : OpenBmpFile
- 函数功能 : 以二进制形式打开计算机硬盘BMP图像文件
- 函数参数 : const char * 图像文件名称
-
BMPIMAGE * 图像结构体指针
- 函数返回值 :FALSE 打开图像文件失败
-
TRUE 打开图像文件成功
/
int OpenBmpFile(const char filename, BMPIMAGE img) {
if((img->bmpfile = fopen(filename, “rb”)) == NULL)
{
printf(“open file is Failure\n\r”);
return FALSE;
}
return TRUE;
}
/**
- 函数名 : OpenBmpFile
- 函数功能 : 以二进制形式打开计算机硬盘BMP图像文件
- 函数参数 : const char * 图像文件名称
-
BMPIMAGE * 图像结构体指针
- 函数返回值 :FALSE 打开图像文件失败
-
TRUE 打开图像文件成功
******************************************************/
int writeBmpFile(const char filename,const BMPIMAGE img) {
FILE *fp;
unsigned int i,j;
unsigned char tempData, *pData;
unsigned int tempHeight;
unsigned int tempWidth;
tempHeight = img->infohead.BiHeight/2;
tempWidth = img->infohead.BiWidth*3;
pData = img->imgbuf;
for(i = 0; i < img->imagesize; i = i + 3) {
tempData = pData[i];
pData[i] = pData[i + 2];
pData[i + 2] = tempData;
}
for(i=0;i<tempHeight;i++)
{
for(j=0;j<tempWidth;j++)
{
tempData = pData[(img->infohead.BiHeight-1-i)*tempWidth+j];
pData[(img->infohead.BiHeight-1-i)*tempWidth+j] = pData[i*tempWidth+j];
pData[i*tempWidth+j] = tempData;
}
}
if((fp = fopen(filename, "wb")) == NULL)
{
printf("seek file is Failure\n\r");
return FALSE;
}
fwrite(&img->filehead, 1, 2, fp);
fwrite(&img->filehead.bfSize, 1, 12, fp);
fwrite(&img->infohead, 1, 40, fp);
fwrite(img->imgbuf, 1, img->imagesize, fp);
fclose(fp);
fclose(img->bmpfile);
return TRUE;
}
/********************************************************
- 函数名 : GetBmpHeader
- 函数功能 : 读取BMP文件头
- 函数参数 : BMPIMAGE * 图像结构体指针
- 函数返回值 :FALSE 读取BMP文件头失败
-
TRUE 读取BMP文件头成功
*******************************************************/
int GetBmpHeader(BMPIMAGE img) {
unsigned char headbuffer[INFOHEADSIZE];
BMPFILEHEAD filehead = &img->filehead;
BMPINFOHEAD infohead = &img->infohead;
if (fread(headbuffer, 1, FILEHEADSIZE, img->bmpfile) != FILEHEADSIZE) {
return FALSE;
}
img->filehead.bfType[0] = headbuffer[0];
img->filehead.bfType[1] = headbuffer[1];
if ((unsigned short )&filehead->bfType[0] != (0x4D42)) { / ‘BM’ /
printf(“file is not bmp\n\r”);
return FALSE; / not bmp image/
}
memcpy(&filehead->bfSize, &headbuffer[2], 4);
memcpy(&filehead->bfOffBits, &headbuffer[10], 4);
if(fseek(img->bmpfile, FILEHEADSIZE, SEEK_SET)) {
return FALSE;
}
if (fread(headbuffer, 1, INFOHEADSIZE, img->bmpfile) != INFOHEADSIZE) {
return FALSE;
}
memcpy(&infohead->BiSize, &headbuffer[0], 4);
memcpy(&infohead->BiWidth, &headbuffer[4], 4);
memcpy(&infohead->BiHeight, &headbuffer[8], 4);
memcpy(&infohead->BiPlanes, &headbuffer[12], 2);
memcpy(&infohead->BiBitCount, &headbuffer[14], 2);
memcpy(&infohead->BiCompression, &headbuffer[16], 4);
memcpy(&infohead->BiSizeImage, &headbuffer[20], 4);
memcpy(&infohead->BiXpelsPerMeter, &headbuffer[24], 4);
memcpy(&infohead->BiYpelsPerMeter, &headbuffer[28], 4);
memcpy(&infohead->BiClrUsed, &headbuffer[32], 4);
memcpy(&infohead->BiClrImportant, &headbuffer[36], 4);
if(infohead->BiPlanes != 1) {
return FALSE;
}
if(infohead->BiBitCount !=24) {
return FALSE;
}
if(infohead->BiCompression != BI_RGB) {
return FALSE;
}
GetImageSize(img);
return TRUE;
}
/********************************************************
- 函数名 : GetImageSize
- 函数功能 : 获取BMP文件大小
- 函数参数 : BMPIMAGE * 图像结构体指针
- 函数返回值 :void
********************************************************/
void GetImageSize(BMPIMAGE *img) {
img->imagesize = img->infohead.BiHeight * WIDTHBYTES(img->infohead.BiWidth * img->infohead.BiBitCount);
}
/********************************************************
- 函数名 : ReadBMPData
- 函数功能 : 读取BMP数据缓冲区
- 函数参数 : BMPIMAGE * 图像结构体指针
- 函数返回值 :FALSE 读取BMP数据失败
-
TRUE 读取BMP数据成功
*******************************************************/
int ReadBMPData(const BMPIMAGE img) {
unsigned int pitch = WIDTHBYTES(img->infohead.BiWidth * img->infohead.BiBitCount);
unsigned int readnum = 0;
int i, j, k;
unsigned char m_temp;
unsigned char *p_tmp, *p_tmp_cur;
unsigned char tempData, pData;
unsigned int index_data;
pData = img->imgbuf;
if(fseek(img->bmpfile, img->filehead.bfOffBits, SEEK_SET)) {
return FALSE;
}
p_tmp = NULL;
p_tmp = (unsigned char )malloc(pitch * img->infohead.BiHeight);
if(p_tmp != NULL) {
readnum = fread(p_tmp, 1, pitch * img->infohead.BiHeight, img->bmpfile);
p_tmp_cur = p_tmp;
for(i = img->infohead.BiHeight - 1; i >= 0; i–, p_tmp_cur += pitch) {
memcpy(&img->imgbuf[ipitch], p_tmp_cur, pitch);
}
}
else {
for(i = img->infohead.BiHeight - 1; i >= 0; i–) {
readnum += fread(&img->imgbuf[ipitch], 1, pitch, img->bmpfile);
}
}
for(index_data = 0; index_data < img->imagesize; index_data = index_data + 3) {
tempData = pData[index_data];
pData[index_data] = pData[index_data + 2];
pData[index_data + 2] = tempData;
}
if(p_tmp != NULL) {
free(p_tmp);
}
return (readnum == img->imagesize);
}
/********************************************************
- 函数名 : Allocbuf
- 函数功能 : 分配图像缓冲区
- 函数参数 : BMPIMAGE * 图像结构体指针
- 函数返回值 :FALSE 分配图像缓冲区失败
-
TRUE 分配图像缓冲区成功
/
int Allocbuf(BMPIMAGE img) {
if((img->imgbuf = malloc(img->imagesize)) == NULL)
return FALSE;
return TRUE;
}
/*
- 函数名 : Freebuf
- 函数功能 : 释放图像缓冲区
- 函数参数 : BMPIMAGE * 图像结构体指针
- 函数返回值 :void
*******************************************************/
void Freebuf(BMPIMAGE img) {
if(img->imgbuf != NULL)
free(img->imgbuf);
img->imgbuf = NULL;
}
cpu.c
#include <cdefBF533.h>
#include “cpu.h”
void Init_Timers0(int dat)
{
*pTIMER0_CONFIG = 0x0019;
*pTIMER0_WIDTH = dat;
*pTIMER0_PERIOD = 2000;
}
void Enable_Timers0(void)
{
*pTIMER_ENABLE|= 0x0001;
asm(“ssync;”);
}
void Disable_Timers0(void)
{
*pTIMER_DISABLE |= 0x0001;
}
void Set_PLL(int pmsel,int pssel)
{
int new_PLL_CTL;
*pPLL_DIV = pssel;
asm(“ssync;”);
new_PLL_CTL = (pmsel & 0x3f) << 9;
*pSIC_IWR |= 0xffffffff;
if (new_PLL_CTL != *pPLL_CTL)
{
*pPLL_CTL = new_PLL_CTL;
asm(“ssync;”);
asm(“idle;”);
}
}
void Init_SDRAM(void)
{
*pEBIU_SDRRC = 0x00000817;
*pEBIU_SDBCTL = 0x00000013;
*pEBIU_SDGCTL = 0x0091998d;
ssync();
}
void Init_EBIU(void)
{
*pEBIU_AMBCTL0 = 0x7bb07bb0;
*pEBIU_AMBCTL1 = 0x7bb07bb0;
*pEBIU_AMGCTL = 0x000f;
}
fun.c
#include “bmp.h”
/********************************************************
- 函数名 : StenciFilter
- 函数功能 : 图像的平滑处理(高斯模板)
- 函数参数 : BMPIMAGE * 图像结构体指针
- 函数返回值 :FALSE 处理失败
-
TRUE 处理成功
********************************************************/
typedef struct kernel
{
int Element[3][3];
int Divisor;
int Dimention;
}KERNEL, *LPKERNEL;
KERNEL Line_Filter={{1,2,1,2,4,2,1,2,1},16,3}; //高斯算子
int StenciFilter(BMPIMAGE* img)
{
long i , j , k , l;
long R, G, B;
// 指向源图像的指针
unsigned char lpDIBBits;
unsigned char m_temp;
// 源图像的宽度和高度
long lWidth;
long lHeight;
// 图像每行的字节数
long lLineBytes;
unsigned char TR,TG,TB;
LPKERNEL lpKernel;
lpKernel = &Line_Filter;
lpDIBBits = img->imgbuf;
lWidth = img->infohead.BiWidth;
lHeight = img->infohead.BiHeight;
lLineBytes = WIDTHBYTES(lWidth24);
m_temp = (unsigned char)malloc(lLineByteslHeight);
if(m_temp == NULL)
return FALSE;
for(i = 0; i < lHeight; i++)
{
// 针对图像每列进行操作
for(j = 0; j < lLineBytes; j++)
{
(m_temp+lLineBytesi+j) = ((unsigned char)lpDIBBits+lLineBytesi+j);
j++;
(m_temp+lLineBytesi+j) = ((unsigned char)lpDIBBits+lLineBytesi+j);
j++;
(m_temp+lLineBytesi+j) = ((unsigned char)lpDIBBits+lLineBytesi+j);
}
}
for(i = 0; i < lWidth; i++)
{
// 针对图像每列进行操作
for(j = 0; j < lHeight; j++)
{
R=G=B=0;
for(k=i-(int)(lpKernel->Dimention/2);k<i+(int)(lpKernel->Dimention/2)+1;k++)
{
for(l=j-(int)(lpKernel->Dimention/2);l<j+(int)(lpKernel->Dimention/2)+1;l++)
{
if(k>=0 && l>=0 && k<lWidth && l<lHeight)
{
TR=((unsigned char)lpDIBBits+llLineBytes+k3);
R+=lpKernel->Element[k-i+(int)(lpKernel->Dimention/2)][l-j+(int)(lpKernel->Dimention/2)]TR;
TG=((unsigned char*)lpDIBBits+llLineBytes+k3+1);
G+=lpKernel->Element[k-i+(int)(lpKernel->Dimention/2)][l-j+(int)(lpKernel->Dimention/2)]TG;
TB=((unsigned char*)lpDIBBits+llLineBytes+k3+2);
B+=lpKernel->Element[k-i+(int)(lpKernel->Dimention/2)][l-j+(int)(lpKernel->Dimention/2)]TB;
}
}
}
R/=lpKernel->Divisor;
G/=lpKernel->Divisor;
B/=lpKernel->Divisor;
(m_temp+jlLineBytes+i3) = R;
(m_temp+jlLineBytes+i3+1) = G;
(m_temp+jlLineBytes+i3+2) = B;
}
}
for(i = 0; i < lHeight; i++)
{
// 针对图像每列进行操作
for(j = 0; j < lLineBytes; j++)
{
((unsigned char)img->imgbuf+lLineBytesi+j) = (m_temp+lLineBytesi+j);
j++;
((unsigned char)img->imgbuf+lLineBytesi+j) = (m_temp+lLineBytesi+j);
j++;
((unsigned char)img->imgbuf+lLineBytes*i+j) = (m_temp+lLineBytesi+j);
}
}
free(m_temp);
return TRUE;
}
main.c
#include <cdefBF533.h>
#include “cpu.h”
#include “tftlcd.h”
#include “bmp.h”
#include “funct.h”
#define INFILEADDR “…/ImageView/testin.bmp”
#define OUTFILEADDR “…/ImageView/testout.bmp”
#define LCD_VIEW_ENABLE
int main(void)
{
BMPIMAGE bmpimage;
Set_PLL(16,4);
Init_EBIU();
Init_SDRAM();
LCDBK_Disable();
if(!OpenBmpFile(INFILEADDR,&bmpimage))
return FALSE;
if(!GetBmpHeader(&bmpimage))
return FALSE;
if(!Allocbuf(&bmpimage))
return FALSE;
if(!ReadBMPData(&bmpimage))
return FALSE;
/* 图像的平滑处理(高斯模板) */
if(!StenciFilter(&bmpimage))
return FALSE;
#ifdef LCD_VIEW_ENABLE
Enable_Timers0();
RGB888_RGB565(&bmpimage,(void*)DisplayBuffer_565);
#endif
if(!writeBmpFile(OUTFILEADDR,&bmpimage))
return FALSE;
#ifdef LCD_VIEW_ENABLE
InitDMA();
InitPPI();
InitTimer();
PPI_TMR_DMA_Enable();
LCD_Enable();
LCDBK_Enable();
Init_Timers0(1999);//1~1999 控制背光亮度
Enable_Timers0();
while(1);
#endif
}
lcd.c
#include <cdefBF533.h>
#include “tftlcd.h”
#include “cpu.h”
section(“sdram0_bank1”) unsigned char DisplayBuffer_565[272][1440] ;
void InitDMA(void)
{
int addr;
addr = &DisplayBuffer_565;
addr -= 1920;
*pDMA0_START_ADDR = addr;
*pDMA0_X_COUNT = 480;
*pDMA0_X_MODIFY = 2;
*pDMA0_Y_COUNT = 286;
*pDMA0_Y_MODIFY = 2;
*pDMA0_CONFIG = 0x1034;
}
void InitPPI(void)
{
*pPPI_CONTROL = 0x781e;
*pPPI_DELAY = 0;
*pPPI_COUNT = 479;
*pPPI_FRAME = 286;
}
void InitTimer(void)
{
*pTIMER1_PERIOD = 525;
*pTIMER1_WIDTH = 41;
*pTIMER1_CONFIG = 0x00a9;
*pTIMER2_PERIOD = 150150;
*pTIMER2_WIDTH = 5250;
*pTIMER2_CONFIG = 0x00a9;
}
void PPI_TMR_DMA_Enable(void)
{
*pDMA0_CONFIG |= 0x1;
asm(“ssync;”);
InitTimer();
*pPPI_CONTROL |= 0x1;
asm(“ssync;”);
*pTIMER_ENABLE|= 0x0006;
asm(“ssync;”);
}
void PPI_TMR_DMAR_Disable(void)
{
*pDMA0_CONFIG &= (~0x1);
*pPPI_CONTROL &= (~0x1);
}
void RGB888_RGB565( BMPIMAGE* img, unsigned char *dst)
{
int i = 0;
int j = 0;
if (img->imagesize % 3 != 0)
{
return;
}
for (i = 0; i < img->imagesize; i += 3)
{
dst[j+1] = img->imgbuf[i+2] &0xf8; //B
dst[j+1] |= ((img->imgbuf[i+1]>>5) & 0x07); //GH
dst[j] = ((img->imgbuf[i+1]<<3) & 0xe0); //GL
dst[j] |= ((img->imgbuf[i]>>3) &0x1f); //R
j += 2;
}
}