参考程序:https://github.com/rogeriorps/ipu-examples/tree/master/mx6
目前imx6系列是支持IPU的缩放功能的。准备好所需的库libipu.so、libipu.so.0和头文件ipu.h、mxcfb.h,在Qt下编写该程序,使用ycoto编译器交叉编译到开发板运行。
pro文件:
LIBS += "$$PWD/libs/libipu.so" "$$PWD/libs/libipu.so.0"
调用方法:
scale_image( "/media/sd-mmcblk2p1/ipu_main/images/img.jpg", 640, 480, "/media/sd-mmcblk2p1/ipu_main/images/img_320_24.jpg", 320, 240 );//缩小图片至320*240大小
scale_image( "/media/sd-mmcblk2p1/ipu_main/images/img.jpg", 640, 480, "/media/sd-mmcblk2p1/ipu_main/images/img_1000_1000.jpg", 1000, 1000 );//放大图片至1000*1000大小
方法实现:
int IPUScale::scale_image( QString s_src_file, unsigned int n_src_width, unsigned int n_src_height,
QString s_des_file, unsigned int n_des_width, unsigned int n_des_height )
{
struct ipu_task task;
struct timeval begin, end;
int sec, usec, run_time = 0;
int fd_ipu = 0; // IPU file descriptor
int isize = 0, osize = 0, ret = 0; // input size output size
void *inbuf = NULL;
void *outbuf = NULL;
memset(&task, 0, sizeof(task));
// Input image size and format
task.input.width = n_src_width;
task.input.height = n_src_height;
task.input.format = v4l2_fourcc('R', 'G', 'B', 'A');
// Output image size and format
task.output.width = n_des_width;
task.output.height = n_des_height;
task.output.format = v4l2_fourcc('R', 'G', 'B', 'A');
QImage src_img = QImage( n_src_width, n_src_height, QImage::Format_RGB32 );
QImage des_img;
bool b_save_status;
src_img.load( s_src_file );
int img_size = src_img.byteCount();
unsigned char *buf = src_img.bits();
qDebug()<<"img_size: "<<img_size<<src_img.size();
qDebug()<<"open IPU device!";
fd_ipu = open("/dev/mxc_ipu", O_RDWR, 0);
if (fd_ipu < 0) {
printf("open ipu dev fail\n");
ret = -1;
goto done;
}
qDebug()<<"according to format: "<<task.input.width<<task.input.height<<fmt_to_bpp(task.input.format);
// isize = task.input.paddr = task.input.width * task.input.height* fmt_to_bpp(task.input.format)/8;
isize = task.input.paddr = img_size;
// Allocate contingous physical memory for input image
// input.paddr contains the amount needed
// this value will be replaced with physical address on success
ret = ioctl(fd_ipu, IPU_ALLOC, &task.input.paddr);
if (ret < 0) {
printf("ioctl IPU_ALLOC fail: (errno = %d)\n", errno);
goto done;
}
// Create memory map and obtain the allocated memory virtual address
inbuf = mmap(0, isize, PROT_READ | PROT_WRITE, MAP_SHARED, fd_ipu, task.input.paddr);
if (!inbuf) {
printf("mmap fail\n");
ret = -1;
goto done;
}
// Allocate memory for output image
osize = task.output.paddr = task.output.width * task.output.height * fmt_to_bpp(task.output.format)/8;
ret = ioctl(fd_ipu, IPU_ALLOC, &task.output.paddr);
if (ret < 0) {
printf("ioctl IPU_ALLOC fail\n");
goto done;
}
// Create memory map for output image
outbuf = mmap(0, osize, PROT_READ | PROT_WRITE,
MAP_SHARED, fd_ipu, task.output.paddr);
if (!outbuf) {
printf("mmap fail\n");
ret = -1;
goto done;
}
memcpy( inbuf, buf, isize );
gettimeofday(&begin, NULL);
// Perform the rotation
ret = ioctl(fd_ipu, IPU_QUEUE_TASK, &task);
if (ret < 0) {
printf("ioct IPU_QUEUE_TASK fail\n");
goto done;
}
gettimeofday(&end, NULL);
sec = end.tv_sec - begin.tv_sec;
usec = end.tv_usec - begin.tv_usec;
if (usec < 0) {
sec--;
usec = usec + 1000000;
}
run_time = (sec * 1000000) + usec;
// Write resized image to output file
des_img = QImage( (const uchar*)outbuf, n_des_width, n_des_height, QImage::Format_RGB32 );
qDebug()<<des_img.byteCount()<<des_img.size()<<osize;
b_save_status = des_img.save( s_des_file );
qDebug()<<"save status: "<<b_save_status;
printf("Resize time: %d usecs\n", run_time);
done:
if (outbuf)
munmap(outbuf, osize);
if (task.output.paddr)
ioctl(fd_ipu, IPU_FREE, &task.output.paddr);
if (inbuf)
munmap(inbuf, isize);
if (task.input.paddr)
ioctl(fd_ipu, IPU_FREE, &task.input.paddr);
if (fd_ipu)
close(fd_ipu);
return ret;
}