![]()
JPEG格式的图片是最常见的图片格式. 它使用有损压缩算法,该算法可处理图片量与质量之间的关系,并且更有利于传播. 因此,JPEG也是最常见的网络标准文件格式. . 使用JPEG格式压缩的图像文件通常也称为JPEG文件,最常用的扩展名格式是.jpg. 但是JEPG标准只是一些压缩方法的描述. 它没有指定文件格式. 为了保存和传输文件,发明了一些文件格式标准. 最常见的文件格式是JPEG / Exif和JPEG / JFIF. JPEG和JIFF / Exif之间的关系类似于unicode和utf-8,一种用于编码,另一种用于存储.

JPEG文件通常使用有损压缩. 所谓有损压缩是指JPEG使用破坏性数据压缩来减小图片大小并促进传输. 我们最常使用Photoshop选择图片质量. 质量越低,图片量越小,质量越高jpeg格式压缩,图片量越大. 在Web应用程序中,经常需要压缩图片以达到减少宽带使用和加快页面显示的目的. 一些测试软件还经常提供有关网页图片大小的建议,例如thinkwithgoogle. 人们经常告诉我们,最简单的方法是使用phototop将图片调整为相应的尺寸(“另存为网络”格式),然后选择适当的质量. 因此,使用Photoshop压缩后,您可以真正坐下来放松一下,并且图片没有其他优化的余地. 要了解此问题,我们需要分析JPEG文件的存储格式.

JPEG文件包含多个数据段(段),每个段包含不同类型的数据,数据段由两个字节分开,称为标记,标记以0xff开头,后跟一个字节以表示不同的类型标记. 一些标记只有一个两个字节,其他的则包括数据长度和数据. 具体结构如下:

JEPG的元数据存储在APPn部分中jpeg格式压缩,注释数据存储在com部分中. 一些制造商可能会在APPn部分中添加自己的数据,例如相机型号和GPS信息.

com是图片的注释信息,APPn是应用程序存储的相关信息. 这些信息对图片本身没有影响,可以将其全部删除. 经过PS处理后,我们使用二进制Open拍了一张照片,发现了以下内容:
显然,此信息对图像无用,可以删除,删除后不会影响图像质量.
PHP
<?php
class JPEG{
//JPEG Metadata Structure
private $markerkey=array("soi"=>0xd8,"sof0"=>0xc0,"sof2"=>0xc2,"dht"=>0x,"dqt"=>0xdb,"dri"=>0xdd,"sos"=>0xda,"rst"=>array(0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7),"app"=>array(0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef),"com"=>0xfe,"eoi"=>0xd9);
private $markerdata=array();
private $ImageScan;
private $Image;
private $PosPointer;
private $ImageSize;
public function __construct($argument){
if(file_exists($argument)){
$this->Image = fopen($argument,"rb+");
$this->ImageSize= filesize($argument);
}else{
die("File Not Exists");
}
if($this->GetByte(2)!==0xd8ff){
die("Not a JPEG Image");
}
$this->Parse();
}
public function GetByte($len){
if(feof($this->Image)) return NULL;
$tmp = fread($this->Image,$len);
$tmp2=array();
$this->PosPointer=ftell($this->Image);
if($len==1){
$tmp2=unpack("C",$tmp);
}else if($len==2){
$tmp2=unpack("S",$tmp);
}else if($len==4){
$tmp2=unpack("L",$tmp);
}else{
$tmp2[1]=$tmp;
}
return $tmp2[1];
}
public function GetMarkerData(){
$buffer="";
foreach($this->markerdata as $d){
foreach($d as $c){
$buffer.=$c;
}
}
return $buffer;
}
public function get_marker($byte){
foreach($this->markerkey as $meta=>$bit){
if(is_array($bit)){
foreach($bit as $b){
if($byte == $b) return $meta;
}
}
if($byte == $bit) return $meta;
}
return NULL;
}
public function compress(){
//Remove Com Marker
$this->markerdata['com']=array();
//Remove App Marker
$this->markerdata['app']=array();
}
public function Parse(){
while(($byte=$this->GetByte(1))!==NULL){
$nxtbyte = @$this->GetByte(1);
if($byte == 0xff){
$marker = $this->get_marker($nxtbyte);
//Variable Size Marker
if($marker == "sof" || $marker == "sof2" || $marker == "dht" || $marker == "dqt" || $marker == "sof0" || $marker == "app" || $marker == "com"){
$offset1= $this->GetByte(1);
$offset2 = $this->GetByte(1);
$len = $offset1*256+$offset2;
$data = $this->GetByte($len-2);
//full data include marker and length
$fulldata = pack("C",0xff).pack("C",$nxtbyte).pack("C",$offset1).pack("C",$offset2).$data;
$this->markerdata[$marker][]= $fulldata;
}else if($marker=="dri"){
//pass
}else if($marker=="rst"){
//pass
}else if($marker=="sos"){
//SOS Segment
$len = $this->ImageSize-$this->PosPointer-1;
$this->ImageScan = pack("C",0xff). pack("C",0xda).$this->GetByte($len);
}
}
}
}
public function GetImageBin(){
return pack("S",0xd8ff).$this->GetMarkerData().$this->ImageScan.pack("S",0xd9ff);
}
public function Storage(){
fseek($this->Image,0);
fwrite($this->Image,$this->GetImageBin());
}
public function __destruct(){
fclose($this->Image);
}
}
$image = new JPEG("test.jpg");
$image->compress();
$image->Storage();
JPEG文件中的元数据Exif文件格式的说明文件布局
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/tongxinshuyu/article-206931-1.html
另一半利息在国内开家公司
再个地方政府保护当地企业也很正常
如果连自己的领海都能让人随便入侵