博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
jpg毁损检测思路
阅读量:5052 次
发布时间:2019-06-12

本文共 2726 字,大约阅读时间需要 9 分钟。

基于libjpeg保存jpg图像或者读取图像时,特别是再存储大尺寸图像时,一个问题特别突出。即图像存储明明毁损了,但是调用存储的函数直接再控制台输出警告信息,但是没有返回值或者异常可供捕获。造成毁损的原因不明。只能推测是libjpeg多线程存储问题。其中图像存在 JWRN_JPEG_EOF 问题时特别致命。因为图像从某一个节点之后信息全部无效。以下是最终算法能够捕获的毁损。

JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file")

JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code")

JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines")

JWRN_JPEG_EOF是核心要解决的问题。 后俩者是最后优化代码时剩余部分比较复杂,时间有限,保留代码顺带检测。

动手解决之前思路:基于libjpeg库,屏蔽掉无关代码,将警告改为异常抛出。捕获并产生相应记录信息。因为是提前终止,因此期待直接从文件头获取文件长度和实际文件长度比较,直接得到判定。

实际解决思路:

1.借鉴opencv的库进行libjpeg重新改写。

2.将libjpeg里面一些C代码更改为C++代码,并消除一些与检测无关代码,提高检测效率。

3.跟踪JWRN_JPEG_EOF 出现位置,梳理前后代码。发现动手前的思路存在缺失。并不能直接获取文件长度进行比较。实际jpg判断该问题是基于段,每次循环前判定当前读取字节数 < 该段字节总数。是的话一次读取固定长度(jpg代码有具体数值)。当读取到字节数目<固定长度,就会进行判定 抛出俩种异常其中一种 就是“JWRN_JPEG_EOF”。 原始libjpg代码如下:

1 METHODDEF(boolean) 2     fill_input_buffer (j_decompress_ptr cinfo) 3 { 4     my_src_ptr src = (my_src_ptr) cinfo->src; 5     size_t nbytes; 6  7     nbytes = JFREAD(src->infile, src->buffer, INPUT_BUF_SIZE); 8  9     if (nbytes <= 0) {10         if (src->start_of_file)    /* Treat empty input file as fatal error */11             ERREXIT(cinfo, JERR_INPUT_EMPTY);12         WARNMS(cinfo, JWRN_JPEG_EOF);13         /* Insert a fake EOI marker */14         src->buffer[0] = (JOCTET) 0xFF;15         src->buffer[1] = (JOCTET) JPEG_EOI;16         nbytes = 2;17     }18 19     src->pub.next_input_byte = src->buffer;20     src->pub.bytes_in_buffer = nbytes;21     src->start_of_file = FALSE;22 23     return TRUE;24 }
1 METHODDEF(boolean) 2     fill_mem_input_buffer (j_decompress_ptr cinfo) 3 { 4   static const JOCTET mybuffer[4] = { 5     (JOCTET) 0xFF, (JOCTET) JPEG_EOI, 0, 0 6   }; 7  8   /* The whole JPEG data is expected to reside in the supplied memory 9    * buffer, so any request for more data beyond the given buffer size10    * is treated as an error.11    */12   WARNMS(cinfo, JWRN_JPEG_EOF);13 14   /* Insert a fake EOI marker */15 16   cinfo->src->next_input_byte = mybuffer;17   cinfo->src->bytes_in_buffer = 2;18 19   return TRUE;20 }

4.找到查错代码后更改自定义代码。我理解不够没有重新书写代码,而是通过剥离出来的opencv的jpeg库调用。然后跟踪执行路径,把执行路径中的函数标记出来,重新写成自己的函数,然后调用。

5.最终效果:使用opencv读取图片会报 JWRN_JPEG_EOF,我这边也会报。执行时间:16000*8192彩色图像,用imread执行时间3~5s,用我更改后的libjpeg库只需要0.2~0.3s(这边耗时主要霍夫编解码上面。因为指针遍历有部分再霍夫编解码上,赶时间没有细究。如果消除的话就是 10ms以内级别操作)。

 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

2019-05-10这样直接改某些情况下会触发野指针。暂不清楚引起得原因。因为此时有问题的图片能打开,能看。不确定是真的文件存在问题,还是写的算法有问题。所以最好加异常捕获代码。

转载于:https://www.cnblogs.com/PiaoLingJiLu/p/9145505.html

你可能感兴趣的文章
过点(2,4)作一直线在第一象限与两轴围成三角形,问三角形面积的最小值?...
查看>>
java aes CBC的填充方式发现
查看>>
使用ionic cordova build android --release --prod命令打包报有如下错误及解决方法
查看>>
BZOJ 2338 HNOI2011 数矩形 计算几何
查看>>
关于页面<!DOCTYPE>声明
查看>>
【AS3代码】播放FLV视频流的三步骤!
查看>>
C++标准库vector使用(更新中...)
查看>>
cocos2d-x 2.2.6 之 .xml文件数据读取
查看>>
枚举的使用
查看>>
BZOJ 1531 二进制优化多重背包
查看>>
BZOJ 2324 (有上下界的)费用流
查看>>
python3基础06(随机数的使用)
查看>>
Zookeeper系列(二)特征及应用场景
查看>>
【HTTP】Fiddler(三)- Fiddler命令行和HTTP断点调试
查看>>
Spring Boot使用Druid和监控配置
查看>>
poi 处理空单元格
查看>>
Android 内存泄漏优化总结
查看>>
luogu4849 寻找宝藏 (cdq分治+dp)
查看>>
Spring Cloud微服务笔记(五)Feign
查看>>
C语言键盘按键列表
查看>>