S3C2416裸机开发系列二十_Libjpeg的移植
扫描二维码
随时随地手机看文章
jpeg格式是一种针对相片影像而广泛使用的一种失真压缩标准,其压缩技术十分先进,用有损压缩方式去除冗余的图像数据,在获得极高压缩率的同时,能展现十分丰富生动的图像,能用最少的磁盘空间得到较好的图像品质。由于其尺寸较小,能够较快地在网络上传输,因此在数码相机、网页等领域均广泛应用到jpeg图像格式。笔者此处就移植libjpeg开源库来应用jpeg作一个简单的介绍。
1. 代码准备libjpeg源码,libjpeg是一个完全用c语言编写的库,包含了被广泛使用的jpeg编码、jpeg解码和其它的jpeg功能的实现,这个库由独立的jpeg工作组维护。请读者自行到官网下载最新的源码。
s3c2416启动代码工程,启动代码是s3c2416/50/51这系列arm9芯片在运行用户c代码main函数之前必须先运行的代码,启动代码支持sd、Nand启动,为用户设置系统时钟,初始化内存,自动识别启动设备并搬移代码到RAM,MMU映射,中断管理等,支持x、ymodem文件传输协议,代码可直接通过串口下载进RAM执行,用户只需专注于用c开发其它功能函数即可。关于启动代码以及启动代码的实现过程,笔者前面章节有非常详细的介绍。此处在MDK下开发,下载”MDK启动代码工程应用实例”中的启动代码源码。
用户代码,用c开发的所有功能代码,其中,用户代码入口为main()函数,在这里用libjpeg库实现在屏上显示jpeg图像以及屏幕截图保存成jpeg图片。
2. 标准io库函数libjpeg由于其开源免费,对桌面操作系统均有良好的支持,因此在linux、windows操作系统下均常用libjpeg来编解码jpeg图片。libjpeg以及例程使用了标准io库函数,如文件操作fopen、fread、fwrite等;输入、输出、错误流函数printf、fprintf等。对于嵌入式开发来说,所有的io操作均是面对特定设备,编译器的标准c库是无法统一实现的,应由用户去实现。在arm编译器中,是使用一种半主机的模式,当用户使用了标准io库函数时,默认情况下,编译器是通过一组定义好的软中断来把io应用请求传送至运行调试器的主机,如用printf和scanf来使用主机的屏幕以及键盘,需要jtag的支持。一旦目标板脱离主机,需单独运行时,在半主机模式下是无法运行,因为io软中断请求无法得到处理。因此对于libjpeg移植,我们必须先对所使用到的io库函数进行重定向,如把输入、输出、错误流重定向到串口,把文件操作重定向到对sd卡的文件操作。此处我们在sd卡中采用的是fatfs文件系统,关于fatfs的移植,笔者在前面的章节有详细的介绍,此处不再详述。在MDK中,标准io库函数最终是通过系统调用接口来完成实质的io请求,我们必须在这些系统调用接口上重定向为目标板上特定设备的请求操作。对于linux操作系统,标准io库函数最终也是通过系统调用,从用户态转到内核态,通过系统api完成实质的io请求操作。在Retarget.c中我们实现所有的标准io库函数的重定向,该部分的代码如下:
#include
#include
#include
#include
#include
#include "ff.h"
#include "diskio.h"
#include "UART0.h"
#pragma import (__use_no_semihosting_swi)
#defineSTDIO 1
/* Standard IO device handles. */
#define STDIN 0x1
#define STDOUT 0x2
#define STDERR 0x3
/* Standard IO device name defines. */
const char __stdin_name[] = "STDIN";
const char __stdout_name[] = "STDOUT";
const char __stderr_name[] = "STDERR";
struct __FILE {int handle; /* Add whatever you need here */ };
#ifdef STDIO
/*-----------------------------------------------------------------------------
Write character to the Serial Port
*----------------------------------------------------------------------------*/
int sendchar(int c) {
if (c == 'n') {
Uart0_SendByte('r');
}
Uart0_SendByte(c);
return (c);
}
/*-----------------------------------------------------------------------------
Read character from the Serial Port
*----------------------------------------------------------------------------*/
int getkey(void) {
int ch = Uart0_ReceiveByte();
if (ch < 0) {
return 0;
}
return ch;
}
#endif
/*---------------------------_ttywrch ---------------------------------------*/
void _ttywrch(int ch) {
#ifdef STDIO
sendchar (ch);
#endif
}
/*---------------------------_sys_open --------------------------------------*/
FILEHANDLE _sys_open (const char *name, int openmode) {
FRESULT Res;
FILEHANDLE fh;
BYTE Mode = FA_READ;
/* Register standard Input Output devices. */
if (strcmp(name, "STDIN") == 0) {
return (STDIN);
}
if (strcmp(name, "STDOUT") == 0) {
return (STDOUT);
}
if (strcmp(name, "STDERR") == 0) {
return (STDERR);
}
if (openmode& OPEN_W) {
Mode|= FA_WRITE | FA_OPEN_ALWAYS;
Mode&= ~FA_READ;
}
if (openmode& OPEN_PLUS) {
Mode|= FA_WRITE | FA_READ;
}
if (openmode & OPEN_A) {
Mode|= FA_OPEN_ALWAYS;
}
fh = (FILEHANDLE)malloc(sizeof(FIL));
if (fh == NULL) {
return -1;
}
Res =f_open((FIL *)fh, name, Mode);
if (Res == RES_OK) {
return fh;
} else {
free((FIL *)fh);
return -1;
}
}
/*---------------------------_sys_close -------------------------------------*/
int _sys_close(FILEHANDLE fh) {
FRESULT Res;
if (fh > 0 && fh < 4) {
return (0);
}
Res = f_close((FIL *)fh);
free((FIL *)fh);
if (Res == RES_OK) {
return 0;
}
return -1;
}
/*---------------------------_sys_write -------------------------------------*/
int _sys_write(FILEHANDLE fh, const uint8_t *buf, uint32_t len, int32_t mode) {
FRESULT Res;
UINT ByteWrite;
#ifdef STDIO
if (fh > 0 && fh < 4) {
if (fh == STDOUT) {
/* Standard Output device. */
for (; len; len--) {
sendchar (*buf++);
}
return (0);
} else {
return (-1);
}
}
#endif
#if!(_FS_READONLY)
Res = f_write((FIL *)fh, buf, len,&ByteWrite);
if (Res == RES_OK) {
if(ByteWrite < len) {
return (len-ByteWrite);
}
return 0;
}
#endif
return -1;
}
/*---------------------------_sys_read --------------------------------------*/
int _sys_read(FILEHANDLE fh, uint8_t *buf, uint32_t len, int32_t mode) {
FRESULT Res;
UINT ByteRead;
#ifdef STDIO
if (fh > 0 && fh < 4) {
if (fh == STDIN) {
/* Standard Input device. */
for (; len; len--) {
*buf++ = getkey ();
}
return (0);
} else {
return (-1);
}
}
#endif
Res = f_read((FIL *)fh, buf, len,&ByteRead);
if (Res == RES_OK) {
if(ByteRead < len) {
return (len-ByteRead);
}
return 0;
}
return -1;
}
/*---------------------------_sys_istty -------------------------------------*/
int _sys_istty(FILEHANDLE fh) {
if (fh > 0 && fh < 4) {
return (1);
}
return (0);
}
/*---------------------------_sys_seek --------------------------------------*/
int _sys_seek(FILEHANDLE fh, long pos) {
FRESULT Res;
if (fh > 0 && fh < 4) {
return (-1);
}
#if_FS_MINIMIZE < 3
Res = f_lseek((FIL *)fh, pos);
if (Res == RES_OK) {
return 0;
}
#endif
return (-1);
}
/*---------------------------_sys_ensure ------------------------------------*/
int _sys_ensure(FILEHANDLE fh) {
FRESULT Res;
if (fh > 0 && fh < 4) {
return (-1);
}
#if!(_FS_READONLY)
Res = f_sync((FIL *)fh);
if (Res == RES_OK) {
return 0;
}
#endif
return -1;
}
/*---------------------------_sys_flen --------------------------------------*/
long _sys_flen(FILEHANDLE fh) {
if (fh > 0 && fh < 4) {
return (0);
}
return f_tell((FIL *)fh);
}
/*---------------------------_sys_tmpnam ------------------------------------*/
int _sys_tmpnam(char *name, int sig, unsigned maxlen) {
return (1);
}
/*----------------