最近在做点阵屏的显示,程序需要从图片文件中读取像素数据,于是研究了一下libjpeg库的使用。
下载
http://www.ijg.org/
https://sourceforge.net/projects/libpng/files/libpng16/1.6.34/
交叉编译
1.解压jpegsrc.v9b.tar.gz
tar -xvf jpegsrc.v9b.tar.gz
2. cd jpeg-9b
3. ./configure --host=KaTeX parse error: Expected 'EOF', got '&' at position 76: …static 4. make &̲& make install …PWD/install --prefix=aarch64-linux --enable-shared --enable-static
7. make && make install
编译完成后在install文件夹下得到库文件
将include的头文件拷到编译器的头文件目录,然后链接对应的库即可。
编写程序
我写了一个类
#ifndef BMAT_H
#define BMAT_H
#include <jpeg/jpeglib.h>
#include <jpeg/jerror.h>
#include <png/png.h>
#include <setjmp.h>
#include <stdio.h>
#include <cstring>
struct Color {
Color() : r(0), g(0), b(0) {}
Color(uint8_t rr, uint8_t gg, uint8_t bb) : r(rr), g(gg), b(bb) {}
uint8_t r;
uint8_t g;
uint8_t b;
};
template <class T>
class BMat {
public:
BMat() : with(0), hight(0), mat(NULL) {
}
BMat(unsigned int w_, unsigned int h_) : with(w_), hight(h_) {
mat = new T*[with];
for (int i = 0; i < with; i++)
mat[i] = new T[hight];
}
virtual ~BMat() {
for (int i = 0; i < with; i++) {
delete mat[i];
}
delete mat;
}
T* operator[](int x) {
if (x < with)
return mat[x];
}
/*
* Returns the number of rows of the matrix.
* If the matrix saves an image, it returns the height of the image.
*/
unsigned int rows(){
return hight;
}
unsigned int cols(){
return with;
}
/*
* Loading image data from the image file is saved in the matrix.
* Currently, only RGB color system is supported,
* and JPEG and PNG file formats are supported.
*/
bool imread(const char *file) {
char *p = strstr(file, ".");
if (strncmp(p, ".jpg", 4) == 0) {
return readjpeg(file);
} else if (strncmp(p, ".png", 4) == 0) {
unsigned char checkheader[8];
FILE *fp = fopen(file, "rb");
if(fp == NULL){
fprintf(stderr, "%s open failed\n", file);
return false;
}
if(fread(checkheader, 1, PNG_BYTES_TO_CHECK, fp) != PNG_BYTES_TO_CHECK){
fprintf(stderr, "checkheader failed\n");
fclose(fp);
return false;
}
if(readpng(&fp)){
fclose(fp);
return true;
}else{
fclose(fp);
return false;
}
}
return false;
}
protected:
struct error_mgr {
struct jpeg_error_mgr pub;
jmp_buf setjmp_buffer;
};
METHODDEF(void) my_error_exit(j_common_ptr cinfo) {
struct error_mgr *myerr = (struct error_mgr *) cinfo->err;
(*cinfo->err->output_message) (cinfo);
longjmp(myerr->setjmp_buffer, 1);
}
/*Reading image data from JPG image file*/
bool readjpeg(const char *file) {
struct jpeg_decompress_struct cinfo;
struct error_mgr jerr;
FILE *infile;
JSAMPARRAY buffer;
int row_stride;
if ((infile = fopen(file, "rb")) == NULL) {
fprintf(stderr, "can't open %s\n", file);
return false;
}
cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = my_error_exit;
if (setjmp(jerr.setjmp_buffer)) {
jpeg_destroy_decompress(&cinfo);
fclose(infile);
return false;
}
jpeg_create_decompress(&cinfo);
jpeg_stdio_src(&cinfo, infile);
(void) jpeg_read_header(&cinfo, TRUE);
if (!mat) {
with = cinfo.image_width;
hight = cinfo.image_height;
mat = new Color*[with];
for (int i = 0; i < with; i++)
mat[i] = new Color[hight];
} else {
for (int i = 0; i < with; i++) {
delete mat[i];
}
delete mat;
with = cinfo.image_width;
hight = cinfo.image_height;
mat = new Color*[with];
for (int i = 0; i < with; i++)
mat[i] = new Color[hight];
}
(void) jpeg_start_decompress(&cinfo);
row_stride = cinfo.output_width * cinfo.output_components;
buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) & cinfo, JPOOL_IMAGE, row_stride, 1);
for (int j = 0; j < hight; j++) {
(void) jpeg_read_scanlines(&cinfo, buffer, 1);
for (int i = 0; i < with; i++) {
mat[i][j].r = buffer[0][(i+1) * 3 + 0];
mat[i][j].g = buffer[0][(i+1) * 3 + 1];
mat[i][j].b = buffer[0][(i+1) * 3 + 2];
}
}
(void) jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
fclose(infile);
return true;
}
/*Reading image data from PNG image file*/
bool readpng(FILE **fpp) {
png_structp png_ptr;
png_infop info_ptr;
png_ptr = png_create_read_struct(
PNG_LIBPNG_VER_STRING,
NULL, NULL, NULL);
info_ptr = png_create_info_struct(png_ptr);
setjmp(png_jmpbuf(png_ptr));
rewind(*fpp);
png_init_io(png_ptr, *fpp);
png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND, 0);
int channels, color_type;
png_byte bit_depth;
channels = png_get_channels(png_ptr, info_ptr);
color_type = png_get_color_type(png_ptr, info_ptr);
bit_depth = png_get_bit_depth(png_ptr, info_ptr);
with = png_get_image_width(png_ptr, info_ptr);
hight = png_get_image_height(png_ptr, info_ptr);
if (!mat) {
mat = new Color*[with];
for (int i = 0; i < with; i++)
mat[i] = new Color[hight];
} else {
for (int i = 0; i < with; i++) {
delete mat[i];
}
delete mat;
mat = new Color*[with];
for (int i = 0; i < with; i++)
mat[i] = new Color[hight];
}
png_bytepp row_pointers;
row_pointers = png_get_rows(png_ptr, info_ptr);
if(channels == 4 ||
color_type == PNG_COLOR_TYPE_RGB_ALPHA){
for(int i = 0; i < hight; i++)
for(int j = 0; j < with * 4; j += 4){
mat[j/4][i].b = row_pointers[i][j+2];
mat[j/4][i].g = row_pointers[i][j+1];
mat[j/4][i].r = row_pointers[i][j+0];
}
}else if(channels == 3 ||
color_type == PNG_COLOR_TYPE_RGB){
for(int i = 0; i < hight; i++)
for(int j = 0; j < with * 3; j += 3){
mat[j/3][i].b = row_pointers[i][j+2];
mat[j/3][i].g = row_pointers[i][j+1];
mat[j/3][i].r = row_pointers[i][j+0];
}
}else{
png_destroy_read_struct(&png_ptr, &info_ptr, 0);
return false;
}
png_destroy_read_struct(&png_ptr, &info_ptr, 0);
return true;
}
private:
unsigned int with;
unsigned int hight;
T **mat;
};
#endif /* BMAT_H */