.读取量化表,全局参数,霍夫曼表,恢复表编码,现在只是实现思路。
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <string.h>
#include <unistd.h>
#include <linux/fb.h>
#include <stdlib.h>
static unsigned char h0[100];
int main(void) {
FILE *f = fopen("/home/wjs/Pictures/1.jpg", "rb");
if (f == NULL) {
puts("file_in error");
exit(-1);
}
fseek(f, 0, SEEK_END);
int len = ftell(f);
fseek(f, 0, SEEK_SET);
int fd = fileno(f);
unsigned char *p = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
puts("-----------量化表---------------------");
for (int t = 0; t < len; t++) {
if ((*(p + t) == 0xff) && (*(p + t + 1) == 0xdb)) {
// printf("ffdb:%d\n", t);
}
}
puts("-----------帧全局---------------------");
for (int t = 0; t < len; t++) {
if ((*(p + t) == 0xff) && (*(p + t + 1) == 0xc0)) {
// printf("ffc0:%d\n", t);
}
}
puts("------------霍夫曼表--------------------");
for (int t = 0; t < len; t++) {
if ((*(p + t) == 0xff) && (*(p + t + 1) == 0xc4)) {
// printf("ffc4:%d\n",t); //ff c4 (固定)0 1f(长度-2)0(表id)
int cd = (*(p + t + 2)) * 256 + *(p + t + 3) - 3;
unsigned char *hp = malloc(cd * (sizeof(char)));
for (int n = 0; n < cd; n++) {
*(hp + n) = *(p + t + 5 + n);
// printf("%d ",*(hp+n));
}
if (*(p + t + 4) == 0) { //表1
unsigned char hfm0[cd];
// memcpy(&h0, hp, cd);
}
if (*(p + t + 4) == 16) { //2
unsigned char hfm1[cd];
// memcpy(&h0,hp,cd);
}
if (*(p + t + 4) == 1) { //3
unsigned char hfm2[cd];
// memcpy(&h0,hp,cd);
}
if (*(p + t + 4) == 17) { //4
unsigned char hfm3[cd];
memcpy(&h0,hp,cd);
}
printf("\n");
free(hp);
}
}
puts("------------差分数据--------------------");
for (int t = 0; t < len; t++) {
if ((*(p + t) == 0xff) && (*(p + t + 1) == 0xdd)) {
// printf("ffdd:%d\n", t);
}
}
puts("------------扫描数据--------------------");
for (int t = 0; t < len; t++) {
if ((*(p + t) == 0xff) && (*(p + t + 1) == 0xda)) {
// printf("ffda:%d\n", t);
}
}
//----------------------------------------------------------------------
//h0[26]
// 0 1 2 3 4 5 6 7 8 9 10 15
//0 1 5 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 4 5 6 7 3 2 8 9
int bm[100];
int t = 0; //输出数组递增数
int n = 1; //内存递增数
if (h0[n] == 1) {
bm[t] = 0;
} else if (h0[n] == 2) {
bm[t] = 0; //生成2 位 0,1
t = t + 1;
bm[t] = 1;
}
for(int q=0;q<15;q++){
n = n + 1;
if (h0[n] != 0) { //3 2,3,4,5,6
t = t + 1;
bm[t] = 2 * (bm[t - 1] + 1);
for (int z = 0; z < (h0[n] - 1); z++) {
t = t + 1;
bm[t] = bm[t - 1] + 1;
}
}
}
/* n = n + 1;
if (h0[n] != 0) { //4 (6+1)*2=14
t = t + 1;
bm[t] = 2 * (bm[t - 1] + 1);
for (int z = 0; z < (h0[n] - 1); z++) {
t = t + 1;
bm[t] = bm[t - 1] + 1;
}
}
n = n + 1;
if (h0[n] != 0) { //5 (14+1)*2=30
t = t + 1;
bm[t] = 2 * (bm[t - 1] + 1);
for (int z = 0; z < (h0[n] - 1); z++) {
t = t + 1;
bm[t] = bm[t - 1] + 1;
}
}
n = n + 1;
if (h0[n] != 0) { //6 (30+1)*2=62
t = t + 1;
bm[t] = 2 * (bm[t - 1] + 1);
for (int z = 0; z < (h0[n] - 1); z++) {
t = t + 1;
bm[t] = bm[t - 1] + 1;
}
}
n = n + 1;
if (h0[n] != 0) { //7位 (62+1)*2=126
t = t + 1;
bm[t] = 2 * (bm[t - 1] + 1);
for (int z = 0; z < (h0[n] - 1); z++) {
t = t + 1;
bm[t] = bm[t - 1] + 1;
}
}
n = n + 1;
if (h0[n] != 0) { //8
t = t + 1;
bm[t] = 2 * (bm[t - 1] + 1);
for (int z = 0; z < (h0[n] - 1); z++) {
t = t + 1;
bm[t] = bm[t - 1] + 1;
}
}
n = n + 1;
if (h0[n] != 0) { //9
t = t + 1;
bm[t] = 2 * (bm[t - 1] + 1);
for (int z = 0; z < (h0[n] - 1); z++) {
t = t + 1;
bm[t] = bm[t - 1] + 1;
}
}
n = n + 1;
if (h0[n] != 0) { //10
t = t + 1;
bm[t] = 2 * (bm[t - 1] + 1);
for (int z = 0; z < (h0[n] - 1); z++) {
t = t + 1;
bm[t] = bm[t - 1] + 1;
}
}
n = n + 1;
if (h0[n] != 0) { //11
t = t + 1;
bm[t] = 2 * (bm[t - 1] + 1);
for (int z = 0; z < (h0[n] - 1); z++) {
t = t + 1;
bm[t] = bm[t - 1] + 1;
}
}
n = n + 1;
if (h0[n] != 0) { //12
t = t + 1;
bm[t] = 2 * (bm[t - 1] + 1);
for (int z = 0; z < (h0[n] - 1); z++) {
t = t + 1;
bm[t] = bm[t - 1] + 1;
}
}
n = n + 1;
if (h0[n] != 0) { //13
t = t + 1;
bm[t] = 2 * (bm[t - 1] + 1);
for (int z = 0; z < (h0[n] - 1); z++) {
t = t + 1;
bm[t] = bm[t - 1] + 1;
}
}
n = n + 1;
if (h0[n] != 0) { //14
t = t + 1;
bm[t] = 2 * (bm[t - 1] + 1);
for (int z = 0; z < (h0[n] - 1); z++) {
t = t + 1;
bm[t] = bm[t - 1] + 1;
}
}
n = n + 1;
if (h0[n] != 0) { //15
t = t + 1;
bm[t] = 2 * (bm[t - 1] + 1);
for (int z = 0; z < (h0[n] - 1); z++) {
t = t + 1;
bm[t] = bm[t - 1] + 1;
}
}
*/
for (int t = 0; t < 100; t++) {
printf("%d ", bm[t]);
}
return 0;
}
Jpeg 用的是范式霍夫曼,可以00 开始推算出码表。
7现在又有一问题,ffda的扫描流中含有Y 和UV两种的交流与直流4个部分,怎样才能区分开这4部分。
搞清楚了码流结构才能试着用上面的码表解码。
一个正常的JPEG码流以SOI(FFD8)标记开始,以EOI(FFD9)标记结束,中间是一帧的图像信息,包括各种数据(如 huffman表FFC4部分,量化表FFC0部分,以及APP和COM等部分)和SCAN部分(FFDA部分)等。JPEG图像包含一个或者多个SCAN(progressive模式包含多个SCAN),一个SCAN下面有一个或者多个RST(Restart Interval),一个RST里有一个或者多个MCU,一个MCU里有一个或者多个Block。
细读rfc2435 jpeg定义标准
主要找SOS段的详细资料信息