Resive world

Come world to Record life


  • Home

  • Tags

  • Categories

  • Archives

  • Sitemap

  • Search

Linux中桌面环境配置与tweak工具

Posted on 2015-12-25 | In Linux

因为Linux是高度自制的,所以几乎任何的设置都可以自行调节,包括主题和桌面效果。

事实上,主题特效是可以调节为任意效果的,甚至可以调节成Mac的样子(当然这样有点二)。

Ubuntu中调节桌面效果的文件路径为:/usr/share/themes/,路径下是这样的:

1
2
3
myths@myths-X450LD:/usr/share/themes$ ls
AgingGorilla Atlanta Crux Emacs HighContrast Radiance Simple
Ambiance Bright Default Esco Metabox Raleigh

每个文件夹就是每个主题了。如果我们想修改主题,我们只需要查询相关文档进行修改即可。

比如如果想调节Ambiance主题下窗口标题的透明度,可以打开/usr/share/themes/Ambiance/gtk-3.0/apps/unity.css文件:

将 UnityDecoration.top 的 background-image 设置由:

1
2
from (shade (@dark_bg_color, 1.5)),
to (shade (@dark_bg_color, 1.04)));

修改为:

1
2
from (shade (alpha (@dark_bg_color, 0.4), 1.5)),
to (shade (alpha (@dark_bg_color, 0.4), 1.04)));

将UnityDecoration.top:backdrop 的 background-image 设置由:

1
2
from (shade (#474642, 0.92)),
to (@dark_bg_color));

修改为:

1
2
from (shade (alpha (#474642, 0.4), 0.92)),
to (alpha (@dark_bg_color, 0.4)));

保存后,重新载入主题即可生效。

事实上事情还可以简单点,Ubuntu下有修改桌面效果的现成的软件包:tweak,用这个可以更加方便的修改主题。

安装:$ sudo apt-get install unity-tweak-tool

界面:

简单易懂,用起来更加方便了。

苏大Mooc系统的刷课脚本的制作(2/3)

Posted on 2015-12-24 | In Web

我们知道了通过发送get请求来进行手动刷课的原理,但是这显然还是不够方便。而且虽然我们知道了发送的包,但是我们并不知道这些数据从何而来。这是一个问题。

继续查看源码,终于在头信息里发现他引用了一个叫StudentLearning.js文件,介绍了整个系统运行的逻辑。其中有一个非常重要的函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
//视频学习表
function GetStudentstudy() {
if (Isfull != true) {
if ($(".item_odd1").attr("kid") != "") {
noteTime = parseInt(jwplayer("div_play").getPosition());
$.ajax({ url: 'StudentLearning.ashx?action=GetG2SSetStageLearnPartStudent&fPlanID=' + $(".item_odd1").attr("FBI") + '&fPartID=' + $(".item_odd1").attr("kid") + "&fSecond=" + noteTime, cache: false,
success: function(data) {

}
});
}
}
}

看到了我们之前用的地址了,这里他用ajax技术向后台传输那些数据,fPlanID、fPartID、fSecond这些东西就来自于这里了。

其中的fPlanID的值很明显就是课程的URL:http://kczx.suda.edu.cn/G2S/Learning/Learning.htm?Part=&Plan=34&type=2里的Plan值了。那么fPartID该怎么得到呢?

在StudentLearning.js中找了一下,又发现了一个函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
function GetList(type) {
var flagqimokaoshi = 1;
var locktiaozhuan = 0;
var fPlanID = request("Plan");
var flagPartID = request("Part");
var flagisLmitNum = 0;
$.ajax({ url: 'StudentLearning.ashx?action=GetG2SStageLearnGetChapter&fPlanID=' + fPlanID, cache: false, async: false,
success: function(data) {
if (data != "False") {
data = data.replace(/[\r\n]/g, "\\r\\n");
var json = eval("(" + data + ")");
var strHtml = "";
var flagParent = 0;
var flagPart = 1;
if (json.Rows.length > 0) {
strHtml += " <ul class='catalogue_ul1' id='chapterList'>";
for (var i = 0; i < json.Rows.length; i++) {
var rows = json.Rows[i];
var fPartID = rows.fPartID;
var fPartName = rows.fPartName;
var fParentID = rows.fParentID;
var fVideoURL = rows.fVideoURL;
var zhuangtai = 0;
var fpartvideourl = rows.fpartvideourl;
var fCCPWebSiteID = rows.fCCPWebSiteID;
var fSchoolWork_ExamID = "";
fSchoolWork_ExamID = rows.fSchoolWork_ExamID;
var fVideoFileID = rows.fVideoFileID;
var fIsCrossChapter = rows.fIsCrossChapter; //是否跨章
var fStatus = rows.fStatus; //测试状态
var fSecond = rows.fSecond; //已读视频(秒)
var fContent = rows.fContent;
var fstudyStatus = rows.fstudyStatus; //学习状态
var fBuildMode = rows.fBuildMode; //作业状态 1 指定试卷 2 题库选题 3 直接出题
var fvideoSecond = rows.fvideoSecond; //视频总时长(秒)
var fxuexi = rows.fxuexi;
var qimokaishi = rows.qimokaishi; //期末考试
var qimofBuildMode = rows.qimofBuildMode;
var qimofCCPWebSiteID = rows.qimofCCPWebSiteID;
var weixuexi = rows.weixuexi; //是否学习 1已学 2 未学
var fisTest = rows.fisTest;
var fTaskID = rows.fTaskIDs;
var fisLmitNum = rows.fisLmitNum;
var MustFileIsFinish=rows.MustFileIsFinish;//资料学习情况 1:已完成学习 0:未完成
var flagyangshi = "time_ico1 unPlay ";
var icoTest = "";
var ficoTestTitle = "";
if (weixuexi == 1) {
zhuangtai = 1;
} else {
zhuangtai = 0;
}
......

名字叫GetList,那么意图也就很明显了,就是得到课程列表的所有信息。用ajax向后台传入课程名,然后就会得到一大串的关于整个课程信息的回复。尝试了发送下,得到如下类似json格式的反馈:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
{
RowCount: 34,
Rows: [
{
"fPartID": "264",
"fPartName": " 大学文化——大学的内涵与使命",
"fParentID": "0",
"fPlanID": "34",
"fBrief": "",
"fVideoFileID": "0",
"fSchoolWork_ExamID": "3172",
"fCCPWebSiteID": "27745",
"fBuildMode": "3",
"fpartvideourl": "",
"fStatus": "20",
"fSecond": "5953",
"fvideoSecond": "5953",
"fVideoURL": "",
"fContent": "",
"fOrder": "100",
"fIsCrossChapter": "1",
"qimokaishi": "5919",
"qimofBuildMode": "3",
"qimofCCPWebSiteID": "27745",
"qimoStatus": "1",
"fstudyStatus": "1",
"fxuexi": "0",
"weixuexi": "1",
"fisTest": "1",
"MustFileIsFinish": "0",
"fTaskID": "0",
"fisLmitNum": "-1"
},
{
"fPartID": "265",
"fPartName": " 大学文化——大学的内涵与使命(一)",
"fParentID": "264",
"fPlanID": "34",
"fBrief": "%u5185%u5BB9%u63CF%u8FF0%uFF08%u6700%u591A200%u5B57%uFF09",
"fVideoFileID": "651",
"fSchoolWork_ExamID": "",
"fCCPWebSiteID": "",
"fBuildMode": "-1",
"fpartvideourl": "http://42.244.42.193:1221/download/38d2e715-2044-429d-b29d-89b964863a81.mp4",
"fStatus": "",
"fSecond": "1756",
"fvideoSecond": "1756",
"fVideoURL": "",
"fContent": "",
"fOrder": "101",
"fIsCrossChapter": "1",
"qimokaishi": "5919",
"qimofBuildMode": "3",
"qimofCCPWebSiteID": "27745",
"qimoStatus": "1",
"fstudyStatus": "1",
"fxuexi": "0",
"weixuexi": "1",
"fisTest": "1",
"MustFileIsFinish": "1",
"fTaskID": "0",
"fisLmitNum": "-1"
},
.......

说他是类json格式,是因为他的RowCount和Rows没有加引号。。。。也是无语。。。

我们发现想要得到的信息几乎全在这里,通过他的命名也很容易看懂其表示的含义。

OK,到现在我们已经知道了所有想要的信息和业务的逻辑了,剩下的就是将这个思想付诸实现了。

苏大Mooc系统的刷课脚本的制作(1/3)

Posted on 2015-12-22 | In Web

闲话不说,其实写这个目的大家都懂,懒得看那些无聊的网路课。但是由于课程的要求,这些课程必须要看,而且由于技术原因,又不能跳着看,视频的播放条不能拖动,只能硬着头皮的刷时间。很多同学都是开着视频开着静音做其他的事,想想也是悲哀。

当然,我写这个程序的初衷并不是为了偷懒,而是纯粹的学习。用技术手段做出一些别人难以实现的事情可是很有成就感的。为了实现这样一个简单的目的其实也不是那么简单的(至少对我这个前几天刚接触web的人而言)。。。

课程首页

从右边点击课程名字就会打开视频,学习完的视频前面会有绿色的钩钩;每个视频下面有播放条,播放条只能在已经看过的部分任意拖动,不能向前拖动。

这就是课程首页的情况,接下来就是想查看源码。结果发现网页是动态生成的,而不是之前学习的静态网页。这两者最直观的感受就是源代码和审查元素得到的代码不一样,也就是用javascript之类的语言根据即时的情况生成的网页。这时候就需要细致的分析js代码了。

 

封包分析

很自然的想法就是查看下封包,弄清楚在观看视频的时候到底是发送了什么东西给后台让后台标记当前视频为已看。经过一番查找(需要细心的找),在用chrome找到了这样的一个包:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
General:

Request URL:http://kczx.suda.edu.cn/G2S/Learning/StudentLearning.ashx?action=GetG2SSetStageLearnPartStudent&fPlanID=34&fPartID=359&fSecond=550&_=1451308953409
Request Method:GET
Status Code:200 OK
Remote Address:42.244.42.191:80

Request Headers:

Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:zh-CN,zh;q=0.8
Connection:keep-alive
Cookie:ASP.NET_SessionId=zh4ifl55q521xx45bmbjwa45; amlbcookie=01; iPlanetDirectoryPro=AQIC5wM2LY4SfcxX1vREajjp5zIi4s9GtkPT1Ivxjw%2BJfo4%3D%40AAJTSQACMDE%3D%23
Host:kczx.suda.edu.cn
Referer:http://kczx.suda.edu.cn/G2S/Learning/Learning.htm?Part=&Plan=34&type=2
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36
X-Requested-With:XMLHttpRequest

Query String Parameters:

action:GetG2SSetStageLearnPartStudent
fPlanID:34
fPartID:359
fSecond:550
_:1451308953409

看到了顿时就豁然开朗了,原来每隔一段时间,网页会通过一个get请求,将当前看的视频的名称、看到的时间发送给后台,让后台加以记录,确认已经看到的地方。fPlanID很明显是课程的编号,fPartID应该是视频的编号,而fSecond应该是当前看到的时间了(最后哪个_:的值,可能是token值,然而翻遍代码,并没有找到对应的值,我想应该是一个随机数,暂时不去管他,应该也无妨)。所以,“作弊”的方法也就很简单了,就是根据这个信息,将描述视频的信息和当前看到(伪造)的时间发送给后台就可以了。

经过一番尝试,这样做果断是合理的。那么,通过这个手段,我们就可以手动的通过输入地址发送get请求来“刷课”了。虽然这显然不够帅,然而对那些没有编程基础的人来说,这种方法倒也是简单快捷的(总比挂着视频方便)。

 

python下解析json格式文件

Posted on 2015-12-21 | In Python

解析json文件无非编码和解码,这里我们用了python下自带的json模块。当然还要结合python本身特有的dict类型的操作。

编码

编码用到的是json.dumps()函数,将字典转化为json对象。

1
2
3
4
5
import json
data = [{'a':"A",'b':(2,4),'c':3.0}] #list对象
print "DATA:",repr(data)
data_string = json.dumps(data)#dumps函数
print "JSON:",data_string

输出的结果是:

1
2
DATA: [{'a':'A','c':3.0,'b':(2,4)}] #python的dict类型的数据是没有顺序存储的
JSON: [{"a":"A","c":3.0,"b":[2,4]}]

解码

解码用json.loads()函数,将json格式转化为dict。

1
2
3
4
5
import json
data = '{"a":"A","b":[2,4],"c":3.0}' #json格式

decoded = json.loads(data)
print "DECODED:",decoded

输出的结果是

1
DECODED: [{u'a': u'A', u'c': 3.0, u'b': [2, 4]}]

编码和解码的过程中,元组会被变成无次序的列表,而字典的次序也并不能保证不变。

现在,处理json格式的重点便成了正确处理dict类型数据了。

常见错误

python的json模块不支持单引号,所以类似"{'a':'A','b':[2,4],'c':3.0}"的字符串是会报以下错误的:

1
ValueError: Expecting property name: line 1 column 2 (char 1)

这时候我们只需要把他单双引号互换即可:

1
'{"a":"A","b":[2,4],"c":3.0}'

Vim基本命令

Posted on 2015-12-20 | In Linux

很久不用vim了,发现什么命令都忘光了,敲起代码来连复制粘贴都不会了,还得用gedit去搞,真的相当蛋疼。这里把常用的命令汇总一下,趁机好好系统的记一下。不看不知道,看了才晓得原来vim还有很多非常炫的特性。

帮助文档

首先,我们得晓得vim的帮助文档。当然man vim 是一个不错的选择,不过他主要是基于在bash中使用,而不是在vim界面中的使用。非常感人的是,vim有一个自带的中文教程(中文!),讲的非常清楚(不过我没耐心看完)。
myths@myths-X450LD:~$ vimtutor

vim的模式

指令模式(任意模式下按Esc或Ctrl+[进入) 用来正常情况下的快捷指令,是各个模式之间切换的桥梁

插入模式(指令模式下按i进入) 左下角显示–INSERT– 实际上就是普通的文本编辑器

可视模式(指令模式下按v进入) 左下角显示–VISUAL–

末行模式(指令模式下按: 或 / 进入,在屏幕最下面可以输入命令)

命令历史

所有以 行末模式输入的命令都有历史,键入 :  / 或?后然后按上下方向键即可翻阅之前的命令。

文件命令

其实vim可以在bash中一次打开多个文件:

1
myths@myths-X450LD:~$ vim file1 file2 file3

也可以在vim中打开新的文件:

1
open foo.txt

也可以用拆分的试图打开新的文件:(不太会用)

1
split foo.txt

如果一次性打开了多个文件,那么可以用以下命令来切换文件:(上下切换)

1
:bn
1
:bp

如果忘记了当前的文件叫啥,可以用如下命令查看当前的文件名:

1
:arg

(其实在用:w 保存的时候也会在左下角显示文件名)

插入命令

命令 用法
i 在当前位置生前插入
a 在当前位置后插入
I 在当前行首插入
A 在当前行尾插入
o 在当前行之后插入一行
O 在当前行之前插入一行

一般是灵活使用 i o 即可。

查找命令

这个非常简单实用!

1
/text

text是你要查找的内容。。。然后查找下一个只需要按n,查找上一个按N。

或者是?text反向查找(可以不去管他了)

替换命令

替换光标所在字符可以在指令模式下按r 再按替换的字符即可。

替换字符串:

1
:s/old/new/

这里表示在当前行用new来替换old字符第一个匹配到的字符

如果需要全局替换,需要输入:

1
:s/old/new/g

g表示全局替换

匹配的串可以用正则来表示,而且s可以替换为一个区间,比如:

1
:10,20 s/^/haha/g

表示在10到20行的行首添加haha,非常好理解。

!注意,Vim默认的替换方式是单行替换,也就是说上面的所有替换方法都是对于单行,是指定行的替换,/g也是指在选定行下进行的全局替换,如果是要在全文中进行替换,则需要用%s参数,比如:

1
:%s/old/new/g

表示在全文中将old 替换成new 。

移动命令

h 左移 ;l 右移 ;k 上移 ;j 下移;

w 前移一个单词 ;b 后移一个单词;

当然,所有的移动都可以在前面加数字表示移动的距离。

<home> 行首;<end>行尾;

gg 文件头;G 文件尾;

Ctrl + e 向下滚动一行

Ctrl + y 向上滚动一行

Ctrl + d 向下滚动半屏

Ctrl + u 向上滚动半屏

Ctrl + f 向下滚动一屏

Ctrl + b 向上滚动一屏

撤销和重做:

实用!

u 撤销

Ctrl + r 重做

删除操作:

命令 功能
x 删除当前字符用
dd 删除当前行用
dj 删除上一行
dk 删除下一行
10d 删除当前行开始的10行.
D 删除当前字符至行尾
:1,10d 删除1-10行

拷贝粘贴

命令 功能
yy 拷贝当前行
10yy 拷贝当前后开始的10行
p 在当前光标后粘贴,如果之前使用了yy命令来复制一行,那么就在当前行的下一行粘贴。
:1,10 co 20 将1-10行插入到第20行之后。
ddp 交换当前行和其下一行,实际上就是删除当前行然后放在下一行的后面

在可视模式下,用jklh命令移动即可选择某些行或字符,再按y即可复制。

剪切命令

1
:1, 10 m 20

将第1-10行移动到第20行之后

退出命令

命令 功能
:x或  :wq 保存并退出
:q! 强制退出并忽略所有更改
:e! 放弃所有修改,并打开原来文件。

宏

vim竟然可以实现宏功能,微醺。

在指令模式下按p再按一个字母比如a,然后输入想要的指令最后再按q即可录制出宏,保存在的@a里。下次想用的时候只需要在指令模式下按@a即可使用宏。

 

执行shell

在行末模式下输入!再输入命令即可:

1
:!g++ test.cpp

Json文件格式概述

Posted on 2015-12-19 | In Others

我们知道现如今,json格式很多网页在前端和后端交互的过程中都会用到的一种文件格式,尤其是在使用ajax进行交互的场合。他的语法简单,而且条理十分清晰,适合处理大量的有着逻辑关系的数据。

定义

什么是 JSON ?

  1. JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation)
  2. JSON 是轻量级的文本数据交换格式
  3. JSON 独立于语言
  4. JSON 具有自我描述性,更易理解
  5. JSON 使用 JavaScript 语法来描述数据对象,但是 JSON 仍然独立于语言和平台。JSON 解析器和 JSON 库支持许多不同的编程语言。

w3c的标准说明如下:
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。 易于人阅读和编写。同时也易于机器解析和生成。 它基于JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。 这些特性使json成为理想的数据交换语言。

所以几乎所有的语言都会有支持json格式转化的库。

格式

json的格式只有两种!所以非常简单方便:

1.键值对

对象是一个无序的“‘名称/值’对”集合。一个对象以“{”开始,“}”结束。每个“名称”后跟一个“:”;“键值对”之间使用“,”分隔。

2.数组

数组是值(value)的有序集合。一个数组以“[”开始,“]”结束。值之间使用“,”分隔。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"employees": [
{
"firstName": "Bill",
"lastName": "Gates"
},
{
"firstName": "George",
"lastName": "Bush"
},
{
"firstName": "Thomas",
"lastName": "Carter"
}
]
}

要注意的是,每一个非数值的字符串都应当带引号,否则标准的解析库是无法解析的。

网上也有很多json的在线格式化的网站,在遇到json无法解析的时候可以去那里找找错。

Ubuntu下卸载多余的Ubuntu系统

Posted on 2015-12-16 | In Linux

之前由于种种原因,折腾了很多个Ubuntu系统,也换了好多个,重新安装了很多次系统,终于找到了当前这个能用的了。本以为万事大吉了,然而最近突然发现之前安装的没用的Ubuntu系统竟然还在我的磁盘中!不说了,接下来我们的任务肯定得把这个删干净了。

然而百度了一下发现并没有这样的教程,有的很多都是在win+ubuntu双系统下删除ubuntu以及grub。显然我们不需要删除grub,而且万一我们没有windows系统呢?学Linux肯定得在Linux下解决问题了。

本打算用fdisk命令之类的进行操作,然而命令还是太烦了点,对于我这种第一次接触磁盘分区的人来说有点吃力,还好我在网上找到了一个图形化控制磁盘分区的小软件—-gparted。

安装命令:

1
root@myths-X450LD:~# apt-get install gparted

这个软件就像windows下自带的那个磁盘操作界面一样,把磁盘的层次显示的非常清楚。运行起来界面是这样的(当然,这种操作磁盘的动作是需要root权限的):

这样我们就非常清楚的掌握了分区的情况了。ntfs是windows的文件系统,ext是Linux的文件系统。分区从sda1到sda11,其中少了sda3和sda4,这是因为约定sda1到sda4为主分区,而我这里只有两个主分区所以剩下的就不显示了。sda1就是我们windows的c盘了,可见其特殊性。sda5到sda11都是扩展分区,可供我们调节使用的。

现在,如果要删除多余的ubuntu系统,我们只要搞清楚他的分区,然后格式化即可。最后在格式化之后,用update-grub命令更新下grub列表就好了。

(这个工具要小心使用。。。不解释,分区中加锁的几项表示是已经加载的分区,这是无法修改的,或者必须卸载后才能修改的)

格式化结束后,我们可以选择删除区号,前提是不能有比他数字更大的分区,比如我删除了sda9,然而我的sda11是我当前的系统,显然不能删。那我就不能删除这个已格式化的分区了。

那么这些分区留着有什么用呢?其实我们完全可以当做一个磁盘来用。在系统重启后,这两个分区会被自动装载到/media文件夹下,并且在桌面的文件夹下显示,我们可以方便的使用。

DIY百度首页

Posted on 2015-12-15 | In Web

花了一天时间DIY了一个百度首页,学习了好多东西,特别是关于页面的dom布局,和css的属性设置,还有关于图片的使用和jquery等等的知识,算是web前端入了个门。贴下代码纪念下,效果页面我觉得差不多能以假乱真了。。。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html" charset="utf-8" >
<style type="text/css" >
#header{
color:white;
position:absolute;
right:0;
top:0;
margin:19px 0 5px 0;
padding:0 20px 0 0;

}
#header div{
text-align:center;
position:relative;
float:right;
}
.b{
color:#333;
font-weight:bold;
line-height:24px;
margin-left:21px;
font-size:13px;
text-decoration:underline;
}
.b:hover{
color:blue;
}
#setting{
font-weight:normal;
margin-top:6px;
display:none;
position:relative;
left:24px;
margin-left:-100px;
border:1px solid #d1d1d1;
width:70px;
-webkit-box-shadow: 1px 1px 5px #d1d1d1;
}
.clear{
clear:both;
}
#setting a{
color:black;
margin:1px 2px 1px 2px;
height:22px;
padding:1px;
display:block;
font-size:12px;
text-decoration:none;
}
#setting a:hover{
background-color:#6495ED;
color:white;
}
*{
margin:0 0 0 0;
padding:0 0 0 0;
}
#logo{
width:270px;
height:129px;
border:0;
}
#mid{
position:center;
margin-top:70px;
text-align:center;

}
#input{
margin-top:20px;
width:539px;
height:34px;
font-size:16px;
border: 1px solid #3385ff;
}
#submit{
width:95px;
height:34px;
border:0px;
color:white;
font-size:15px;
background-color:#3385ff;
}
.more{
float:right;
line-height:24px;
margin-left:21px;
background-color:#38f;
color:white;
padding:0 4px 0 4px;
margin-left:25px;
margin-right:-8px;
font-size:13px;
text-decoration:none;
}
#right{
border-left:solid 1px #f0f0f0;
position:absolute;
display:none;
top:0;
right:0;
bottom:0;
background-color:#f9f9f9;
width:85px;
}
.cover{
padding-top:10px;
text-decoration:none;
height:
}
.r{
margin-top:10px;
text-align:center;
border-bottom:solid 1px #f0f0f0;
height:75px;
font-size:11px;
color:#666;
cursor:pointer;
}
.pic{
background:url("icon.png") no-repeat;
width:36px;
height:36px;
margin:0 auto;
margin-bottom:10px;
}
.pic1{
background-position:-72px 0;
width:40px;
}
.pic2{
background-position:-112px 0;

}
.pic3{
background-position:-36px 0;
}
.pic4{
background-position:-148px 0;
}
.pic5{
background-position:-184px 0;
}
.pic6{
background-position:-220px 0;
}
.clear{
clear:both;
}
.footer{
margin:280px 0 0 0 ;
text-align:center;
}
.wrapper{
margin:0 auto;
padding:0 0 0 0;
position:center;
width:660px;
}
.mobile{
background:url("mobile.png") no-repeat;
width:60px;
height:60px;
margin:0 auto;
}
.nuomi{
background:url("nuomi.png") no-repeat;
width:60px;
height:60px;
margin:0 auto;
}
.bt{
float:left;
text-align:left;
}
#btn{
background:url("btn.png") no-repeat;
float:left;
background-position:-600px -96px;
width:14px;
height:17px;
}
</style>
<script src="jquery.js"></script>
<script>
$(document).ready(function(){
$("#m").mouseover(function(){
$("#setting").show();
});
$("#m").mouseout(function(){
$("#setting").hide();
});
$(".more").mouseover(function(){
$("#right").show();
});
$("#right").mouseover(function(){
$("#right").show();
})
$("#right").mouseout(function(){
$("#right").hide();
});
$(".r").hover(function(){
$(this).css("text-decoration","underline");
},function(){
$(this).css("text-decoration","none");
})
});
</script>
</head>
<body>
<div id="header">
<div><a class="more" >更多产品</a></div>
<div id="m">
<div>
<a class="b" id='set' href="javascript:;">设置</a>
</div>
<div class="clear"></div>
<div id="setting">
<a href="#">搜索设置</a>
<a href="#">高级搜索</a>
<a href="#">关闭预测</a>
<a href="#">搜索历史</a>
</div>
</div>
<div><a class="b" href="https://passport.baidu.com/">登录</a></div>
<div><a class="b" href="http://tieba.baidu.com">贴吧</a></div>
<div><a class="b" href="http://v.baidu.com">视频</a></div>
<div><a class="b" href="http://map.baidu.com">地图</a></div>
<div><a class="b" href="http://www.hao123.com">hao123</a></div>
<div><a class="b" href="http://news.baidu.com">新闻</a></div>
<div><a class="b" href="http://www.nuomi.com/?cid=002540">糯米</a></div>
</div>
<div class="clear"></div>
<div id="right">
<div class="r cover" style="height:50px;">更多产品</div >
<div class="r" onclick=window.open("http://music.baidu.com")><div class="pic pic1"></div>音乐</div>
<div class="r" onclick=window.open("http://image.baidu.com")><div class="pic pic2"></div>图片</div>
<div class="r" onclick=window.open("http://zhidao.baidu.com")><div class="pic pic3"></div>知道</div>
<div class="r" onclick=window.open("http://wenku.baidu.com")><div class="pic pic4"></div>文库</div>
<div class="r" onclick=window.open("http://top.baidu.com")><div class="pic pic5"></div>风云榜</div>
<div class="r" onclick=window.open("http://e.baidu.com/?refer=888")><div class="pic pic6"></div>百度推广</div>
<div class="r" onclick=window.open("http://www.baidu.com/more/")>全部产品>></div>
</div>
<div id="mid">
<div>
<img src="logo.png" id="logo">
</div>
<div>
<form method='get' action="https://www.baidu.com/s" id="form">
<input id='input' type="text" name='wd'><input id='submit' type='submit' value="百度一下">
</form>
</div>
</div>
<div class="footer">
<div class="wrapper">
<div class="mobile bt"></div>
<div class="bt" style="width:90px">
<span style="font-size:12px;padding-top:10px;">&nbsp;&nbsp;手机百度</span>
<br><br>
<span style="font-size:12px;color:gray;">&nbsp;&nbsp;快人一步</span>
</div>
<div class="nuomi bt"></div>
<div class="bt" style="width:90px">
<span style="font-size:12px;">&nbsp;&nbsp;百度糯米</span>
<br><br>
<span style="font-size:12px;color:gray;">&nbsp;&nbsp;一毛大餐</span>
</div>
<div class="bt">
<div style="float:left;">
<span style="font-size:12px;text-decoration:underline;cursor:pointer;" onclick=window.open("https://www.baidu.com/cache/sethelp/help.html")>把百度设为首页</span>&nbsp;&nbsp;&nbsp;
<span style="font-size:12px;text-decoration:underline;cursor:pointer;" onclick=window.open("http://home.baidu.com/")>关于百度</span>&nbsp;&nbsp;&nbsp;
<span style="font-size:12px;text-decoration:underline;cursor:pointer;" onclick=window.open("http://ir.baidu.com/")>About Baidu</span>
</div>
<br>
<br>
<div style="float:left">
<span style="font-size:12px;color:gray;">@2015&nbsp;baidu</span>
<span style="font-size:12px;color:gray;text-decoration:underline;cursor:pointer;" onclick=window.open("http://www.baidu.com/duty/")>使用百度前必读</span>
<span style="font-size:12px;color:gray;text-decoration:underline;cursor:pointer;" onclick=window.open("http://jianyi.baidu.com/")>意见反馈</span>
<span style="font-size:12px;color:gray;">京ICP证030173号</span>
</div>
<div id="btn"></div>
</div>
</div>
<div class="clear"></div>
</div>
</body>
</html>

远程挂载服务器命令sshfs

Posted on 2015-12-14 | In SSH

一直以为免密码登陆远程服务器已经是非常方便了,但是最近发现了一个更加方便的方法——-远程服务器居然可以挂载到本地!利用sshfs工具,使用基于ssh协议的ssh文件系统,我们可以像操作本地文件一样的执行、传输服务器的文件了。

当然,GNU的标准并没有包含sshfs,所以我们需要下载一下:

1
myths@myths-X450LD:~$ sudo apt-get install sshfs

下载好以后,我们只需要像ssh登陆一样的挂载远程服务器:

(当然我们需要管理员权限)

1
$ sshfs [username]@[remotehost]:[targetpath]  [localpath]

当然我们需要在本地的/mnt文件夹下mkdir创建一个挂载点文件夹,然后再执行挂载命令:

1
2
root@myths-X450LD:~$ mkdir /mnt/server
root@myths-X450LD:~$ sshfs root@mythsman.com:/ /mnt/server

这样就挂载好了,我们就可以完全的把/mnt/server文件夹看作是我的服务器的根目录了。

最后如果需要卸载,只需正常的步骤:

1
root@myths-X450LD:~# umount /mnt/server

当然,仅仅用上述的方法就会发现这个sshfs的链接总是会断,而且一断就会卡在那里动也动不了,只能强行kill这个ssh进程。因此通常情况下,我们会开启一个reconnect参数,即:

1
$ sshfs [username]@[remotehost]:[targetpath]  [localpath] -o reconnect

PNG文件格式详解

Posted on 2015-12-08 | In Others

最近在看隐写术的时候经常需要研究图片文件的二进制文档格式,那么这就很有必要了解我们的图片文件究竟是如何保存的了,今天找了个时间看了下png文件的文档格式。总体还是挺麻烦的,不过毕竟不需要有什么要求,能了解即可。

概述

PNG是20世纪90年代中期开始开发的图像文件存储格式,其目的是替代GIF和TIFF文件格式,同时增加一些GIF文件格式所不具备的特性。流式网络图形格式(Portable Network Graphic Format,PNG)名称来源于非官方的“PNG’s Not GIF”,是一种位图文件(bitmap file)存储格式,读成“ping”。PNG用来存储灰度图像时,灰度图像的深度可多到16位,存储彩色图像时,彩色图像的深度可多到48位,并且还可存储多到16位的α通道数据。PNG使用从LZ77派生的无损数据压缩算法。(说白了这就是一种方便的、适于网络传播的轻便图片文件格式)

特性

  1. 使用调色板技术可支持256种颜色的彩色图像。(必须的)
  2. 流式读/写性(streamability):图像文件格式允许连续读出和写入图像数据。(因此适于网络传播)
  3. 逐次逼近显示(progressive display):这种特性可使在通信链路上传输图像文件的同时就在终端上显示图像,把整个轮廓显示出来之后逐步显示图像的细节,也就是先用低分辨率显示图像,然后逐步提高它的分辨率。(类似马赛克逐渐消除的过程)
  4. 透明性(transparency):这个性能可使图像中某些部分不显示出来,用来创建一些有特色的图像。
  5. 辅助信息(ancillary information):这个特性可用来在图像文件中存储一些文本注释信息。(就是可以说一些废话)
  6. 独立于计算机软硬件环境。
  7. 使用无损压缩。(无损!)
  8. 可在一个文件中存储多幅图像。

文件结构

PNG图像格式文件由文件署名和数据块(chunk)组成。

文件署名域

8字节的PNG文件署名域用来识别该文件是不是PNG文件。该域的值是:

十进制数 十六进制数
137 89
80 50
78 4e
71 47
13 0d
10 0a
26 1a
10 0a

这个文件署名就是在《利用文件头标志判断文件类型》中提到的文件头标志了,很简单。

数据块

这里有两种类型的数据块,一种是称为关键数据块(critical chunk),就是必须要有的块;另一种叫做辅助数据块(ancillary chunks)。

每个数据块都由下表所示的的4个域组成。

|名称|字节数|说明|
|-|-|
|Length(长度)|4字节|指定数据块中数据域的长度,其长度不超过$(2^{31}-1)$字节|
|Chunk Type Code(数据块类型码)|4字节|数据块类型码由ASCII字母(A-Z和a-z)组成|
|Chunk Data(数据块实际内容|可变长度|存储按照Chunk Type Code指定的数据|
|CRC(循环冗余检测|4字节|存储用来检测是否有错误的循环冗余码|

其中CRC(cyclic redundancy check)域中的值是对Chunk Type Code域和Chunk Data域中的数据进行计算得到的,可以看做一种校验码。

关键数据块

关键数据块中的4个标准数据块是:

(1) 文件头数据块IHDR(header chunk):

它包含有PNG文件中存储的图像数据的基本信息,并要作为第一个数据块出现在PNG数据流中,而且一个PNG数据流中只能有一个文件头数据块。

文件头数据块由13字节,组成结构如下:

域的名称 字节数 说明
Width 4 bytes 图像宽度,以像素为单位
Height 4 bytes 图像高度,以像素为单位
Bit depth 1 byte 图像深度:索引彩色图像:1,2,4或8 ;灰度图像:1,2,4,8或16 ;真彩色图像:8或16
ColorType 1 byte 颜色类型:0:灰度图像, 1,2,4,8或16;2:真彩色图像,8或16;3:索引彩色图像,1,2,4或84:带α通道数据的灰度图像,8或16;6:带α通道数据的真彩色图像,8或16
Compression method 1 byte 压缩方法(LZ77派生算法)
Filter method 1 byte 滤波器方法
Interlace method 1 byte 隔行扫描方法:0:非隔行扫描;1: Adam7(由Adam M. Costello开发的7遍隔行扫描方法)

(2) 调色板数据块PLTE(palette chunk):

它包含有与索引彩色图像((indexed-color image))相关的彩色变换数据,它仅与索引彩色图像有关,而且要放在图像数据块(image data chunk)之前。真彩色的PNG数据流也可以有调色板数据块,目的是便于非真彩色显示程序用它来量化图像数据,从而显示该图像。结构如下:

|颜色|字节|意义|
|Red|1 byte||0 = 黑色, 255 = 红|
|Green|1 byte||0 = 黑色, 255 = 绿色|
|Blue|1 byte||0 = 黑色, 255 = 蓝色|

PLTE数据块是定义图像的调色板信息,PLTE可以包含1~256个调色板信息,每一个调色板信息由3个字节组成,因此调色板数据块所包含的最大字节数为768,调色板的长度应该是3的倍数,否则,这将是一个非法的调色板。

对于索引图像,调色板信息是必须的,调色板的颜色索引从0开始编号,然后是1、2……,调色板的颜色数不能超过色深中规定的颜色数(如图像色深为4的时候,调色板中的颜色数不可以超过2^4=16),否则,这将导致PNG图像不合法。

(3) 图像数据块IDAT(image data chunk):

它存储实际的数据,在数据流中可包含多个连续顺序的图像数据块。

IDAT存放着图像真正的数据信息,因此,如果能够了解IDAT的结构,我们就可以很方便的生成PNG图像。

(4) 图像结束数据IEND(image trailer chunk):

它用来标记PNG文件或者数据流已经结束,并且必须要放在文件的尾部。

如果我们仔细观察PNG文件,我们会发现,文件的结尾12个字符看起来总应该是这样的:

00 00 00 00 49 45 4E 44 AE 42 60 82

不难明白,由于数据块结构的定义,IEND数据块的长度总是0(00 00 00 00,除非人为加入信息),数据标识总是IEND(49 45 4E 44),因此,CRC码也总是AE 42 60 82。

最后,除了表示数据块开始的IHDR必须放在最前面, 表示PNG文件结束的IEND数据块放在最后面之外,其他数据块的存放顺序没有限制。

辅助数据块

(比较杂,不需要全部了解透)

PNG文件格式规范制定的10个辅助数据块是:

  1. 背景颜色数据块bKGD(background color)。
  2. 基色和白色度数据块cHRM(primary chromaticities and white point)。所谓白色度是指当R=G=B=最大值时在显示器上产生的白色度。
  3. 图像γ数据块gAMA(image gamma)。
  4. 图像直方图数据块hIST(image histogram)。
  5. 物理像素尺寸数据块pHYs(physical pixel dimensions)。
  6. 样本有效位数据块sBIT(significant bits)。
  7. 文本信息数据块tEXt(textual data)。
  8. 图像最后修改时间数据块tIME (image last-modification time)。
  9. 图像透明数据块tRNS (transparency)。
  10. 压缩文本数据块zTXt (compressed textual data)。

数据块摘要

关键数据块、辅助数据块和专用公共数据块(special-purpose public chunks)综合下表中:

数据块符号 数据块名称 多数据块 可选否 位置限制
IHDR 文件头数据块 否 否 第一块
cHRM 基色和白色点数据块 否 是 在PLTE和IDAT之前
gAMA 图像γ数据块 否 是 在PLTE和IDAT之前
sBIT 样本有效位数据块 否 是 在PLTE和IDAT之前
PLTE 调色板数据块 否 是 在IDAT之前
bKGD 背景颜色数据块 否 是 在PLTE之后IDAT之前
hIST 图像直方图数据块 否 是 在PLTE之后IDAT之前
tRNS 图像透明数据块 否 是 在PLTE之后IDAT之前
oFFs (专用公共数据块) 否 是 在IDAT之前
pHYs 物理像素尺寸数据块 否 是 在IDAT之前
sCAL (专用公共数据块) 否 是 在IDAT之前
IDAT 图像数据块 是 否 与其他IDAT连续
tIME 图像最后修改时间数据块 否 是 无限制
tEXt 文本信息数据块 是 是 无限制
zTXt 压缩文本数据块 是 是 无限制
fRAc (专用公共数据块) 是 是 无限制
gIFg (专用公共数据块) 是 是 无限制
gIFt (专用公共数据块) 是 是 无限制
gIFx (专用公共数据块) 是 是 无限制
IEND 图像结束数据 否 否 最后一个数据块

tEXt和zTXt数据块中的标准关键字:

关键字 说明
Title 图像名称或者标题
Author 图像作者名
Description 图像说明
Copyright 版权声明
CreationTime 原图创作时间
Software 创作图像使用的软件
Disclaimer 弃权
Warning 图像内容警告
Source 创作图像使用的设备
Comment 各种注释

一个例子

为了便于研究,我在本地找了个24x24像素的图片:

用十六进制打开后是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
0000000: 8950 4e47 0d0a 1a0a 0000 000d 4948 4452  .PNG........IHDR
0000010: 0000 0018 0000 0018 0806 0000 00e0 773d ..............w=
0000020: f800 0000 1974 4558 7453 6f66 7477 6172 .....tEXtSoftwar
0000030: 6500 4164 6f62 6520 496d 6167 6552 6561 e.Adobe ImageRea
0000040: 6479 71c9 653c 0000 0344 4944 4154 78da dyq.e<...DIDATx.
0000050: b454 4b48 5b51 10bd 792f 2646 a346 7411 .TKH[Q..y/&F.Ft.
0000060: 450b cac3 6840 8c14 0242 8542 e9aa ab42 E...h@...B.B...B
0000070: 5785 8614 c428 b4d0 5569 b108 5dbb 29b4 W....(..Ui..].).
0000080: 1b05 a5ab 6cb3 2a14 0ab5 8b42 75a3 d188 ....l.*....Bu...
0000090: 82c6 0ff1 4320 a2e2 2f7e 12ed 9c47 e671 ....C ../~...G.q
00000a0: 8d2f 8950 3a30 dcc7 bb33 67e6 cee7 5826 ./.P:0...3g...X&
00000b0: 2626 8499 288a a2ab d56a d555 55d5 57d7 &&..(....j.UU.W.
00000c0: d7d7 be6c 36fb fef2 f232 45a7 b8ba ba12 ...l6....2E.....
00000d0: c160 5014 13ab d94f 8bc5 72e3 24e0 1e9f .`P....O..r.$...
00000e0: cff7 b9ae ae4e 4c4e 4eda 3299 4c00 777c .....NLNN.2.L.w|
00000f0: 5f4c 1472 16f9 9a07 2e6a 6b6b 875a 5b5b _L.r.....jkk.Z[[
0000100: 454d 4d8d e8ea ea7a 4eff 3ce2 8ea2 3018 EMM....zN.<...0.
0000110: 94cb c28a 7f04 765f d3b4 27ec d0d8 d8a8 ......v_..'.....
0000120: 5655 55bd 639b 9201 a8b6 a8af 516b 9bcd VUU.c.......Qk..
0000130: 26ca caca f46f 0020 7bb7 db6d 38d8 ed76 &....o. {..m8..v
0000140: d1d1 d1f1 82ee 34d8 940c 0023 00c2 11e0 ......4....#....
0000150: 1c20 975d 2781 3d75 381c 379c 9a9b 9b55 . .]'.=u8.7....U
0000160: 2ad7 1012 bb73 0028 c073 1373 8f02 3c68 *....s.(.s.s..<h
0000170: 6b6b fb44 25b9 e554 5e5e 2eba bbbb f18a kk.D%..T^^......
0000180: c791 4844 2b16 c012 0e87 fd04 faac bebe ..HD+...........
0000190: be85 cad1 e272 b97c 04a0 e245 4ea7 530f .....r.|...EN.S.
00001a0: 5c48 8e8f 8f45 3a9d d6f5 f0f0 7091 747b \H...E:.....p.t{
00001b0: 7777 779d feff a649 0b07 0281 acb5 baba www....I........
00001c0: fa97 dfef 7710 7041 309e 2c79 ba20 4800 ....w.pA0.,y. H.
00001d0: 9a13 2f81 7a11 7479 79b9 3f16 8ba1 ae63 ../.z.tyy.?....c
00001e0: caf9 f979 120b 83c5 81e6 03e3 8e4f 59e5 ...y.........OY.
00001f0: a010 5e3c f405 2705 dbd6 7b90 4aa5 1ecd ..^<..'...{.J...
0000200: cdcd 250e 0e0e c4c5 c585 a080 fa49 0686 ..%..........I..
0000210: 1303 ca81 7007 1bf6 c1f7 d9d9 9958 5b5b ....p........X[[
0000220: 1384 f73a 140a 7de3 3d58 27e9 8d46 a371 ...:..}.=X'..F.q
0000230: 0491 c14a 89fc 1204 01f8 d4d4 1461 87be ...J.........a..
0000240: e46f 7262 6363 a377 6666 6671 6f6f cfc8 .orbcc.wfffqoo..
0000250: dc6c cb65 651b 3439 1e8f 03bc 8fc0 c70a .l.ee.49........
0000260: 5145 3291 483c 5c58 5888 a251 a5c0 5989 QE2.H<\XX..Q..Y.
0000270: f8c4 d6d6 5676 7a7a fae5 c0c0 c0f8 ad3d ....Vvzz.......=
0000280: c823 ac14 3df3 c3d1 d191 d1e4 620a 5f94 .#..=.......b._.
0000290: 6673 7333 3238 38f8 b520 9be6 3887 ff79 fss3288.. ..8..y
00002a0: 989b f85f 7e3f e4a4 b0f1 74af 1525 3b36 ..._~?....t..%;6
00002b0: 8423 ed45 6745 4585 012c 4f92 3c41 fc02 .#.EgEE..,O.<A..
00002c0: d008 ed90 7774 74d4 5694 4df9 248e f182 ....wtt.V.M.$...
00002d0: 3278 4ccd 9aca 8161 039f caca 4a80 9b52 2xL....a....J..R
00002e0: b855 1e49 3a55 32f6 c209 60bc 4068 3aa6 .U.I:U2...`.@h:.
00002f0: 8b1a 9aa6 041c 4429 3a6f 7150 3000 9d9d ......D):oqP0...
0000300: 641e 33ed 8114 a485 0238 4178 703c 3939 d.3......8Axp<99
0000310: 11c9 6452 acac acfc 248e 798b 9d21 b0e1 ..dR....$.y..!..
0000320: f6f6 f6fe a6a6 2683 5ec0 5b94 948f eec3 ......&.^.[.....
0000330: 055f c001 3015 5838 64bc baba 1add d9d9 ._..0.X8d.......
0000340: 01f0 0f76 a0cd 7d33 3f3f 3f42 73ff d1e3 ...v..}3???Bs...
0000350: f104 1b1a 1a54 f890 6805 a748 9a92 3fb4 .....T..h..H..?.
0000360: e6df 691f dcfb fbfb 2366 19e5 64fb f4f4 ..i.....#f..d...
0000370: b46f 7676 7664 6969 6998 5ed1 43fd 1837 .ovvvdiii.^.C..7
0000380: a5eb bb50 c2bf 8822 feb3 fc15 6000 74fe ...P..."....`.t.
0000390: 7622 c159 82da 0000 0000 4945 4e44 ae42 v".Y......IEND.B
00003a0: 6082 0a `..

接下来我们试着分析一下:

首先是八个字节的文件头标志,标识着png文件:

1
8950 4e47 0d0a 1a0a

接下来的地方就是IHDR数据块了:

0000 000d说明IHDR头块长为13

4948 4452 IHDR标识(ascii码为IHDR)

下面是IHDR数据块的实际内容

0000 0018图像的宽,24像素

0000 0018图像的高,24像素

08 表示色深,这里是2^8=256,即这是一个256色的图像

06 颜色类型,查表可知这是带α通道数据的真彩色图像

00  PNG Spec规定此处总为0(非0值为将来使用更好的压缩方法预留),表示使压缩方法(LZ77派生算法)

00  同上

00 非隔行扫描

e0 773d f8 CRC校验

以上分析了第一个IHDR块的内容,其他块的分析方法类似,比如接下来的就是tEXt块了,很简单,不做分析了。(当然这里还有重要的IDAT块,这是图像的实际内容)

最后得有个IEND数据块,这部分正如上所说,通常都应该是

00 00 00 00 49 45 4E 44 AE 42 60 82

由于我用的是vim打开,vim在文件最后都会恶心的自己加上0a换行,当然这并没有什么坏的影响。不过这也提醒了我们一个问题,既然在IEND块后面添加任何的字符都对文件的打开造成不了影响,那我们就可以在这里藏一些数据了(当然这种藏法很low)。。。

OK,这就是png文件的基本构造了。

1…505152…58

574 posts
69 categories
286 tags
© 2024 Companyd
Powered by Hexo
|
Theme — NexT.Muse v5.1.4