Linux jpeg程式設計
一、編譯移植JPEG庫
獲取JPEG庫
官網連結下載jpeg庫
交叉編譯JPEG庫
- 在linux中,切換到jpeg庫所在的路徑下
- 在linux中解壓jepg庫,一般地解壓到家目錄下–>因為在家目錄下,擁有一切許可權。
tar xzvf jpegsrc.v9c.tar.gz -C ~
tar:解壓/壓縮的linux命令
處理以.gz結尾的壓縮包
x:解壓 c:壓縮
v:以可見的方式進行解壓,這個引數不是必須的。
f:檔案
-C:指定解壓之後的路徑
~:家目錄
如果有v選項,則會列印解壓的過程。
- 回到家目錄下,看看有沒有一個新的目錄叫jpeg-9c/,這個目錄就是jpeg庫解壓出來的目錄
- 在家目錄下建立一個新的目錄,作為安裝之後的目錄,如果沒有寫許可權的話,需要給予許可權
mkidr jpgbuf //建立目錄
chmod 777 jpgbuf //修改目錄許可權
`進入jpeg-9c/目錄,然後ls檢視目錄下的檔案,有一個叫configure的配置檔案
- 配置
./configure --host=arm-none-linux-gnueabi --prefix=/home/gec/jpgbuf
其中:
./configure --> 執行當前目錄下的configure檔案,會生成一個makefile檔案
–host=arm-none-linux-gnueabi -->指定用arm交叉工具鏈進行編譯,這樣生成的檔案才能在arm平臺使用
–prefix=/home/gec/jpgbuf -->指定安裝路徑
- 編譯
make //編譯makefile檔案
`如果結果是下面這樣子:
make all-am
make[1]: Entering directory ‘/home/gec/jpeg-9a’
make[1]: Leaving directory ‘/home/gec/jpeg-9a’ --> 則需要清除連結檔案
```c
make clean //清除連結檔案
清除結束後,重新make編譯makefile檔案
- 安裝
make install
安裝結束後,切換到~/jpgbuf/目錄下,如果看到有bin include lib share這4個目錄,則編譯移植jpeg庫成功
拷貝庫檔案到開發板即可。
二、程式碼編寫
jpeg.h檔案
#ifndef __JPEG_H__
#define __JPEG_H__
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <syslog.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <stdbool.h>
#include <linux/input.h>
#include "jpeglib.h"
#include <linux/fb.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
struct image_info
{
int width;
int height;
int pixel_size;
};
extern void write_lcd(
unsigned char *bmp_buffer,
struct image_info *imageinfo,
unsigned char *FB, struct fb_var_screeninfo *vinfo);
extern unsigned long read_image_from_file(
int fd,
unsigned char *jpg_buffer,
unsigned long jpg_size);
extern int Stat(const char *filename, struct stat *file_info);
extern int Open(const char *filename, int mode);
#endif
jpeg.c檔案
#include "jpeg.h"
// 將 bmp_buffer 中的 24 位的 RGB 資料,寫入 LCD 的 32 位的視訊記憶體中
void write_lcd(
unsigned char *bmp_buffer,
struct image_info *imageinfo,
unsigned char *FB, struct fb_var_screeninfo *vinfo)
{
bzero(FB, vinfo->xres * vinfo->yres * 4);
int x, y;
for(x=0; x<vinfo->yres && x<imageinfo->height; x++)
{
for(y=0; y<vinfo->xres && y<imageinfo->width; y++)
{
unsigned long lcd_offset = (vinfo->xres*x + y) * 4;
unsigned long bmp_offset = (imageinfo->width*x+y) *
imageinfo->pixel_size;
memcpy(FB + lcd_offset + vinfo->red.offset/8,
bmp_buffer + bmp_offset + 0, 1);
memcpy(FB + lcd_offset + vinfo->green.offset/8,
bmp_buffer + bmp_offset + 1, 1);
memcpy(FB + lcd_offset + vinfo->blue.offset/8,
bmp_buffer + bmp_offset + 2, 1);
}
}
}
// 將 jpeg 檔案的壓縮影像資料讀出,放到 jpg_buffer 中去等待解壓
unsigned long read_image_from_file(
int fd,
unsigned char *jpg_buffer,
unsigned long jpg_size)
{
unsigned long nread = 0;
unsigned long total = 0;
while(jpg_size > 0)
{
nread = read(fd, jpg_buffer, jpg_size);
jpg_size -= nread;
jpg_buffer += nread;
total += nread;
}
close(fd);
return total;
}
//獲取圖片檔案的資訊
int Stat(const char *filename, struct stat *file_info)
{
int ret = stat(filename, file_info);
if(ret == -1)
{
fprintf(stderr, "[%d]: stat failed: "
"%s\n", __LINE__, strerror(errno));
exit(1);
}
return ret;
}
//開啟LCD裝置
int Open(const char *filename, int mode)
{
int fd = open(filename, mode);
if(fd == -1)
{
fprintf(stderr, "[%d]: open failed: ""%s\n", __LINE__, strerror(errno));
exit(1);
}
return fd;
}
main.c檔案
#include "jpeg.h"
int main(int argc, char **argv)
{
if(argc != 2)
{
printf("Usage: %s <jpeg image>\n", argv[0]);
exit(1);
}
// 讀取圖片檔案屬性資訊
// 並根據其大小分配記憶體緩衝區 jpg_buffer
struct stat file_info;
Stat(argv[1], &file_info);
int fd = Open(argv[1], O_RDONLY);
unsigned char *jpg_buffer;
jpg_buffer = (unsigned char *)calloc(1, file_info.st_size);
read_image_from_file(fd, jpg_buffer, file_info.st_size);
// 宣告解壓縮結構體,以及錯誤管理結構體
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
// 使用預設的出錯處理來初始化解壓縮結構體
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
// 配置該 cinfo,使其從 jpg_buffer 中讀取 jpg_size 個位元組
// 這些資料必須是完整的 JPEG 資料
jpeg_mem_src(&cinfo, jpg_buffer, file_info.st_size);
int ret = jpeg_read_header(&cinfo, true);
if(ret != 1)
{
fprintf(stderr, "[%d]: jpeg_read_header failed: "
"%s\n", __LINE__, strerror(errno));
exit(1);
}
// 開始解壓
jpeg_start_decompress(&cinfo);
struct image_info imageinfo;
imageinfo.width = cinfo.output_width;
imageinfo.height = cinfo.output_height;
imageinfo.pixel_size = cinfo.output_components;
int row_stride = imageinfo.width * imageinfo.pixel_size;
// 根據圖片的尺寸大小,分配一塊相應的記憶體 bmp_buffer
// 用來存放從 jpg_buffer 解壓出來的影像資料
unsigned long bmp_size;
unsigned char *bmp_buffer;
bmp_size = imageinfo.width *
imageinfo.height * imageinfo.pixel_size;
bmp_buffer = (unsigned char *)calloc(1, bmp_size);
// 迴圈地將圖片的每一行讀出並解壓到 bmp_buffer 中
while(cinfo.output_scanline < cinfo.output_height)
{
unsigned char *buffer_array[1];
buffer_array[0] = bmp_buffer +
(cinfo.output_scanline) * row_stride;
jpeg_read_scanlines(&cinfo, buffer_array, 1);
}
// 解壓完了,將 jpeg 相關的資源釋放掉
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
free(jpg_buffer);
// 準備 LCD 螢幕
int lcd = Open("/dev/fb0", O_RDWR|O_EXCL);
// 獲取 LCD 裝置的當前引數
struct fb_var_screeninfo vinfo;
ioctl(lcd, FBIOGET_VSCREENINFO, &vinfo);
// 根據當前 LCD 裝置引數申請適當大小的 FRAMEBUFFR
unsigned char *FB;
unsigned long bpp = vinfo.bits_per_pixel;
FB = mmap(NULL, vinfo.xres * vinfo.yres * bpp/8,
PROT_READ|PROT_WRITE, MAP_SHARED, lcd, 0);
// 將 bmp_buffer 中的 RGB 影像資料,寫入 FRAMEBUFFER 中
write_lcd(bmp_buffer, &imageinfo, FB, &vinfo);
return 0;
}
通用Makefile
CROSS_COMPILE ?=arm-none-linux-gnueabi-
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
CC = $(CROSS_COMPILE)gcc
CPP = $(CC) -E
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm
STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
export AS LD CC CPP AR NM
export STRIP OBJCOPY OBJDUMP
CFLAGS := -Wall -O2 -g
CFLAGS += -I $(shell pwd)/include
LDFLAGS := -L $(shell pwd)/lib -ljpeg
export CFLAGS LDFLAGS
TOPDIR := $(shell pwd)
export TOPDIR
TARGET := test
obj-y += main.o
obj-y += jpeg.o
all : start_recursive_build $(TARGET)
@echo $(TARGET) has been built!
start_recursive_build:
make -C ./ -f $(TOPDIR)/Makefile.build
$(TARGET) : built-in.o
$(CC) -o $(TARGET) built-in.o $(LDFLAGS)
clean:
rm -f $(shell find -name "*.o")
rm -f $(TARGET)
distclean:
rm -f $(shell find -name "*.o")
rm -f $(shell find -name "*.d")
rm -f $(TARGET)
三、程式碼框架
實驗效果
執行:
[root@GEC6818 /mnt/jpeg]#./test load.jpg
[root@GEC6818 /mnt/jpeg]#
效果:
相關文章
- 【Linux】 Linux網路程式設計Linux程式設計
- Linux Bash程式設計Linux程式設計
- Linux串列埠程式設計Linux串列埠程式設計
- Linux之shell程式設計Linux程式設計
- Linux Shell程式設計(1)Linux程式設計
- Linux Shell程式設計(2)Linux程式設計
- Online PDF to PNG, PDF to JPEG, PDF to WEBP, PDF to TXT - toolfk程式設計師線上工具網Web程式設計師
- 【Linux】Linux系統程式設計入門Linux程式設計
- 【Linux網路程式設計】網路程式設計常見概念Linux程式設計
- Linux網路程式設計(2)Linux程式設計
- Linux網路程式設計(1)Linux程式設計
- Linux程式設計之gdb(二)Linux程式設計
- Linux 伺服器程式設計Linux伺服器程式設計
- (整合)Linux下的多程式程式設計Linux程式設計
- Linux 高效能伺服器程式設計- Linux 網路程式設計基礎 APILinux伺服器程式設計API
- 【Linux系統程式設計】Linux訊號列表Linux程式設計
- Linux系統程式設計之程式介紹Linux程式設計
- linux下使用makefile方式程式設計主程式Linux程式設計
- linux程式全解-3.4.linux應用程式設計和網路程式設計第4部分Linux程式設計
- Linux系統程式設計—有名管道Linux程式設計
- Linux中Libevent程式設計介紹Linux程式設計
- Linux系統程式設計基礎Linux程式設計
- Linux入門---(三)Shell程式設計Linux程式設計
- 前端學習 linux —— shell 程式設計前端Linux程式設計
- Linux系統程式設計入門Linux程式設計
- Linux系統程式設計——特殊程式之孤兒程式Linux程式設計
- JPEG格式研究——(2)JPEG檔案格式
- 【Linux】關於Linux的系統程式設計總結Linux程式設計
- Linux網路程式設計之IO模型Linux程式設計模型
- Linux系統程式設計:mmap使用技巧Linux程式設計
- Linux系統程式設計:訊號捕捉Linux程式設計
- 【Linux網路程式設計】位元組序Linux程式設計
- 【Linux網路程式設計-1】訊號Linux程式設計
- 【Linux網路程式設計-3】多程序Linux程式設計
- Linux系統程式設計之匿名管道Linux程式設計
- Linux系統程式設計—訊號捕捉Linux程式設計
- 【學習】Linux Shell指令碼程式設計Linux指令碼程式設計
- Linux系統程式設計-檔案IOLinux程式設計