1.å¦ä½ä½¿ç¨libjpeg
2.音视频探索(5):JPEG格式与Libjpeg库编译移植
å¦ä½ä½¿ç¨libjpeg
æ¬æåªä»ç»jpegå缩çç¸å ³å 容ï¼åå¼å§æè´ªå¾çäºï¼éç¨å¾® 软 çGDI Plusæä¾çåè½ï¼å¾æ¯æ¹ä¾¿ï¼å è·åjpgå¾åçç¼ç ï¼ç¶åæ ¹æ®å¾åçä½å¾æ°æ®å建ä¸ä¸ªBitmapç±»ç对象ï¼åä¿åå¾å为jpgæ ¼å¼å°±è¡äºãä½æ¯æ对 GDI+è¿æ¯å¾ä¿¡ä»»ï¼æ»æè§ä¸è¸å®ï¼æ²¡æçç±çï¼ï¼æ们çç³»ç»ä¸æ¦å®è£ å°±è¦é¿æè¿è¡ï¼æå°±æ¯æ å¿é¿æè¿è¡ä¸æ®µæ¶é´åGDI+ä¼åºé®é¢ï¼ç»æä¹è¯å®äºæçæ å¿ï¼æ们å®é 使ç¨çå¥ç³»ç»ä¸æä¸å¥ï¼è¿ç»è¿è¡3ï¼5天åï¼GDI+å°±ä¼å´©æºï¼äºæ¯æå³å¿éç¨IJG JPEG Libraryãæ¨å¯ä»¥å°
ç«ä¸è½½libjpegçæºç ï¼ IJG JPEG Libraryå°±æ¯jpegå缩åºï¼æ¯ä»¥æºç çå½¢å¼æä¾ç»è½¯ä»¶å¼å人åçï¼å½ç¶å¨è½¯ä»¶å éä¹æç¼è¯å¥½çåºæ件ï¼æ们è¿éå°±åªç¨å°å ¶ä¸ç libjpeg.libï¼jconfig.hï¼jmorecfg.hï¼jpeglib.hè¿å 个æ件ï¼ä¸é¢æå°±ä»ç»ä¸ä¸ææ ·å¨èªå·±çç¨åºéåµå ¥å¾åå缩å è½ã
ããä¸ã建ç«ç¼è¯ç¯å¢
ããæè°å»ºç«ç¼è¯ç¯å¢ï¼å ¶å®é常ç®åï¼å°±æ¯æä¸é¢æå°ç4个æä»¶æ· è´å°ä½ ç项ç®æ件夹ä¸ï¼ælibjpeg.libæ·»å å°ä½ ç项ç®ä¸ï¼ç¶åå¨ä½ å®æå缩åè½çé£ä¸ªæ件éå å ¥#include "jpeglib.h"ï¼éè¦æ³¨æçæ¯ï¼libjpeg.libæ¯ç¨cè¯è¨å¼åçï¼å¦æè¦ç¨å¨ä½ çC++ç¨åºéï¼éè¦ç¨å°extern "C"ï¼å¦ä¸ï¼
// TestLibjpeg.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "memory.h"
extern "C" {
#include "jpeglib.h"
}
ããäºãå缩æ¥éª¤
ãã1ãç³è¯·å¹¶åå§åjpegå缩对象ï¼åæ¶è¦æå®é误å¤çå¨
struct jpeg_compress_struct jcs;
// 声æé误å¤çå¨ï¼å¹¶èµå¼ç»jcs.errå
struct jpeg_error_mgr jem;
jcs.err = jpeg_std_error(&jem);
jpeg_create_compress(&jcs);
ãã2ãæå®å缩åçå¾åæåæ¾çç®æ æ件ï¼æ³¨æï¼ç®æ æ件åºä»¥äºè¿å¶æ¨¡å¼æå¼
f=fopen(".jpg",源码"wb");
if (f==NULL)
{
delete [] data;
delete [] pDataConv;
return 0;
}
jpeg_stdio_dest(&jcs, f);
ãã3ã设置å缩åæ°ï¼ä¸»è¦åæ°æå¾å宽ãé«ãè²å½©ééæ°ï¼1ï¼ç´¢å¼å¾åï¼3ï¼å ¶ä»ï¼ï¼è²å½©ç©ºé´ï¼JCS_GRAYSCALE表示ç°åº¦å¾ï¼JCS_RGB表示彩è²å¾åï¼ï¼å缩质éçï¼å¦ä¸ï¼
jcs.image_width = nWidth; // 为å¾ç宽åé«ï¼åä½ä¸ºåç´
jcs.image_height = nHeight;
jcs.input_components = 1; // å¨æ¤ä¸º1,表示ç°åº¦å¾ï¼ å¦ææ¯å½©è²ä½å¾ï¼å为3
jcs.in_color_space = JCS_GRAYSCALE; //JCS_GRAYSCALE表示ç°åº¦å¾ï¼JCS_RGB表示彩è²å¾å
jpeg_set_defaults(&jcs);
jpeg_set_quality (&jcs, , true);
éè¦æ³¨æçæ¯ï¼jpeg_set_defaultså½æ°ä¸å®è¦ç设 置好å¾å宽ãé«ãè²å½©ééæ°è®¡è²å½©ç©ºé´å个åæ°åæè½è°ç¨ï¼å 为è¿ä¸ªå½æ°è¦ç¨å°è¿å个å¼ï¼è°ç¨jpeg_set_defaultså½æ°åï¼jpeglib åºéç¨é»è®¤ç设置对å¾åè¿è¡å缩ï¼å¦æéè¦æ¹å设置ï¼å¦å缩质éï¼è°ç¨è¿ä¸ªå½æ°åï¼å¯ä»¥è°ç¨å ¶å®è®¾ç½®å½æ°ï¼å¦jpeg_set_qualityå½æ°ãå ¶å® å¾åå缩æ¶æ好å¤åæ°å¯ä»¥è®¾ç½®ï¼ä½å¤§é¨åæ们é½ç¨ä¸ç设置ï¼åªéè°ç¨jpeg_set_defaultså½æ°å¼ä¸ºé»è®¤å¼å³å¯ã
ãã4ãä¸é¢çå·¥ä½åå¤å®æåï¼å°±å¯ä»¥å缩äºï¼å缩è¿ç¨é常ç®åï¼ é¦å è°ç¨jpeg_start_compressï¼ç¶åå¯ä»¥å¯¹æ¯ä¸è¡è¿è¡å缩ï¼ä¹å¯ä»¥å¯¹è¥å¹²è¡è¿è¡å缩ï¼çè³å¯ä»¥å¯¹æ´ä¸ªçå¾åè¿è¡ä¸æ¬¡å缩ï¼å缩å®æåï¼ è®°å¾è¦è°ç¨jpeg_finish_compresså½æ°ï¼å¦ä¸ï¼
jpeg_start_compress(&jcs, TRUE);
JSAMPROW row_pointer[1]; // ä¸è¡ä½å¾
int row_stride; // æ¯ä¸è¡çåèæ°
row_stride = jcs.image_width; // å¦æä¸æ¯ç´¢å¼å¾,æ¤å¤éè¦ä¹ä»¥3
// 对æ¯ä¸è¡è¿è¡å缩
while (jcs.next_scanline < jcs.image_height) {
row_pointer[0] = & pDataConv[jcs.next_scanline * row_stride];
jpeg_write_scanlines(&jcs, row_pointer, 1);
}
jpeg_finish_compress(&jcs);
ãã5ãæåå°±æ¯éæ¾å缩工ä½è¿ç¨ä¸æç³è¯·çèµæºäºï¼ä¸»è¦å°±æ¯jpegå缩对象ï¼ç±äºå¨æ¬ä¾ä¸ææ¯ç´æ¥ç¨çå±é¨åéï¼æ以åªéè°ç¨jpeg_destroy_compressè¿ä¸ªå½æ°å³å¯ï¼å¦ä¸ï¼
jpeg_destroy_compress(&jcs);
ããä¸ã解å缩æ¥éª¤
ãã解å缩æ¥éª¤ä¸å缩æ¥éª¤é常ç¸ä¼¼ï¼åªæ¯è§£å缩对象为jpeg_decompress_structç±»åï¼æ¥éª¤å¦ä¸ï¼
ãã1ã声æ并åå§å解å缩对象ï¼åæ¶å¶å®é误信æ¯ç®¡çå¨
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
ãã2ãæå¼jpgå¾åæ件ï¼å¹¶æå®ä¸ºè§£å缩对象çæºæ件
FILE *f = fopen(strSourceFileName,"rb");
if (f==NULL)
{
printf("Open file error!\n");
return;
}
//
jpeg_stdio_src(&cinfo, f);
ãã3ã读åå¾åä¿¡æ¯
jpeg_read_header(&cinfo, TRUE);
ãã4ãæ ¹æ®å¾åä¿¡æ¯ç³è¯·ä¸ä¸ªå¾åç¼å²åº
data = new BYTE cinfo.image_width*cinfo.image_height*cinfo.num_components];
ãã5ãå¼å§è§£å缩
jpeg_start_decompress(&cinfo);
JSAMPROW row_pointer[1];
while (cinfo.output_scanline < cinfo.output_height)
{
row_pointer[0] = &data[(cinfo.output_height - cinfo.output_scanline-1)*cinfo.image_width*cinfo.num_components];
jpeg_read_scanlines(&cinfo,row_pointer ,
1);
}
jpeg_finish_decompress(&cinfo);
ãã6ãéæ¾èµæº
jpeg_destroy_decompress(&cinfo);
fclose(f);
ãã好äºï¼å©ç¨IJG JPEG Libraryè¿è¡å¾åå缩就ä»ç»å°è¿éï¼å¸æ对大家ææ帮å©ï¼å®ä¾ä»£ç å·²ç»å®ç°äºå¾åçå缩å解å缩çå ¨é¨åè½ï¼å½ä»¤æ ¼å¼ 为ï¼âTestLibjpeg.exe j|j|b æºæ件å ç®æ æ件åâï¼å ¶ä¸ï¼jé项å°æºæ件å缩为jpgæ ¼å¼ï¼ä¸æ¹åè²å½©æ¨¡å¼ï¼jé项å°æºæ件å缩为为jpgæ ¼å¼ï¼bé项å°æºæ件解å缩为bmpæ ¼å¼ï¼ 该å®ä¾å¹¶æ²¡ææä¾æ件æææ§çéªè¯ï¼å¦æè¦å¼å ¥èªå·±ç代ç ï¼è¯·èªå·±å®ç°æ件æææ§çéªè¯ã
音视频探索(5):JPEG格式与Libjpeg库编译移植
libJPEG-turbo是一款强大的JPEG图像处理库,尤其适用于Android系统,源码其内建的源码压缩算法在低版本设备上可能存在性能瓶颈。为提升Android中压缩的源码质量,本文将采用AS的源码挖钻石源码Cmake工具编译优化过的libJPEG-turbo源码,并结合JNI/NDK技术,源码dnf源码精灵定制化使用哈夫曼编码进行压缩。源码
哈夫曼编码,源码由Huffman在年提出,源码是源码一种根据字符出现频率定制的无损压缩方法。编码过程中,源码频率高的源码字符会得到较短的编码,反之则较长。源码flutter点播源码在图像压缩中,源码首先统计像素频率,源码构建赫夫曼树,然后以特定路径的failover源码分析0和1序列作为编码。例如,对“BADCADFEED”编码,根据字符频率构建的赫夫曼树会生成特定的编码规则。
libJPEG库的java防雷源码压缩过程包括初始化JPEG压缩对象,设置输出、参数,按行处理数据(如x RGB图像每行字节),最后结束并释放资源。解码过程则涉及分配初始化解压对象,指定数据源,读取头部参数,设置解压参数并读取数据到缓存区,最后结束并释放资源。
源码分析中,关键结构体如jpeg_compress_struct负责存储图像信息和压缩参数,而jpeg_error_mgr用于处理错误。编码和解码的核心函数如jpeg_write_scanlines和jpeg_read_scanlines,负责数据的读取和写入。编译与移植阶段,通过Cmake在Android工程中配置和编译libjpeg-turbo,以便在Java应用中使用其压缩功能。