QRCODE介绍与编码简介

初涉二维码编码原理


基础常识

二维码发源于日本
有四种规范(参考ISO/IEC 18004:2006(E))

QRCode Model 1,QRCode Model 2,QRCode 2005,The Micro QRCode

Model1是最早的版本,数据量小而且在图像变形的时候无法读取

Model2是增强版本,增加了对齐位

model1 model2

QRCode 2005 和Model2完全兼容,只是增加了一些其他特性.(实在不知道怎么翻译).Model2可以被本规格译码器直接译码.,有1-40号的版本.是主流二维码标准
The Micro QRCode 只需要左上角一个寻象图形(1:1:3:1:1)和2码元的留白

micro MICRO QR

当然时代在发展,而且有不属于规范中的二维码,根据QRCODE官网 如果将MODEL 1 2分开,有共计6种规格,(温馨提示,请不要选择中文版本,中文版本不全,选择英日韩均可).分别是MODEL 1/2,Micro QR,IQR,SQRC,logoQ.

下面简单说说QRCode 2005的新特性

  1. 版本16以上的QRCODE支持结构链接,也就是一个数据文件拆分成多个QR码序列
  2. 支持更多的字符集,例如Arabic,Cyrillic, Greek
  3. 支持颜色反转,将黑白反转依然可以读取,例如b(经测试,不少二维码读取软件都不支持这样的读取)
  4. 支持图像水平反转,例如下图的c

Imgur

颜色反转这种功能非常有用,例如你的电池,你的充电器,不少都是黑色的,上面有印着白色二维码(例如骚尼的充电器),请不要吐槽为什么不贴张白色贴纸然后用黑色二维码,或者是原本那塑料和包装纸就是白色的(不是所有的充电器都是水果牌

ac battery

基本结构


若无特殊说明,一切基于QRCODE 2005说明(除了特殊说明,Model 2一般和QRCODE 2005相同)
QRCode版本1的码元数目为21 21(码元就是一个bit,黑点为1,白点为0,不考虑颜色反转).版本N的码元边长为17+4N.也就是说每增加一个版本,边长增加4.

QR_Character_Placement.png

寻象图形 Finder Pattern

寻象图形比例为1:1:3:1:1.无论何种规格,均为7个码元,颜色分别是黑白黑白黑,另外,寻象图形周围有1个码元宽度的分隔符Separator,全部为白色,如下图

finder_pattern.png

定位图形 Timing pattern

水平和垂直定位图形均宽1个码元(one module wide),黑白相间,在两个寻象图形之间,与其中一边对齐.定位图形的意义在于二维码初次检测的时候便于确定两个寻象图形的距离,以计算该二维码的版本号.

校正图形 Alignment patterns

一个5*5的方块,外围的一圈黑色加上中心的一个黑色码元.版本2以上均有.(所以上方的图没有校正图形)

preview

编码


  1. 数据分析 分析数据类型确定编码方式,可以进行混编,同时确定数据量,如果没有指定版本,那么按照当前纠正等级所匹配的最小版本来填充数据.
  2. 数据编码 数据转换成8bit流,并且在模式段前加入模式指示符(如果模式混编需要加入指定模式符)
  3. 纠错编码 按照标准将数据流分块,通过RS码进行校验编码.生成纠错码字(一般为系统码)
  4. 构造最终信息 按照标准将bit流放入数据块中,未填充完全则加入剩余位
  5. 布置模块 放入寻象图形,分隔符,校正图形,定位图形和码字(8bit)
  6. 掩模 根据4个罚分标准评价结果取掩模
  7. 放入格式信息(掩模,纠错级别).一些版本(>=7)还需要放入版本信息.

p.s. 系统码指信息位和校验位分别存放,还有对应的非系统码,均可以在QRCode中使用,非系统码的意义在于重新调整区域信息,以达到自己想要的图形,相信说道这里已经有人知道非系统码可以用来做什么了

~~6.4.2.1 ECI Designator 暂时没有全看懂,先说一下懂的东西,ECI扩展和ECI指定符暂时不会= = ~~

ECI可以简单认为是后续数据的编码模式,不过包含着其他数据.如果一个数据流最开始不是缺省ECI(0111)那么随后每一段(segment)最前端都需要有ECI标头,如果以缺省的ECI开始,位流的开头为第一个模式的指示符。

最终的位串由模式指示符(4位),字符计数指示符(Character Count Indicator),数据位流组成.

ECI    0111
数字    0001
字母数字    0010
8位字节    0100
日本汉字    1000
中国汉字    1101
结构链接    0011
FNC1 0101 (第一位置)1001 (第二位置)(不懂FNC1,别问我= =)
终止符 0000

字符计数指示符用来表明随后的字符有多少位,字符计数指示符的长度可以查表得出.

character count indicator

注:中文汉字和日文汉字相同

数字模式

十进制数字,3个一组编码成10bit.

例如1-H版本.01234567分组012 345 67.那么

012->0000001100
345->0101011001
67->1000011

可以看到,如果数字只剩下3个,则用7bit编码,如果只剩下一个,则用4位编码.2^10=1024,可以表示0-999,2^7=128,用于表示0-99,2^4=16,用于表示0-9.
使用率将近97%,所以储存的数据量相比其他的二维码要大不少.

好,然后继续编码.数字的模式指示符为0001,01234567一共8个,根据查表字符计数指示符,1-9版本的数字,字符计数指示符都是10,对8进行编码,得到0000001000.

所以增加了ECI标头的最终数据为0001 0000001000 0000001100 0101011001 1000011

数字字母模式

两位一组编码成11bit

alphanumeric

本模式拥有0-9,A-Z的 大写 和少数符号组成,一共45种.因此对于一个字符串AB,其结果为45A+B的二进制,最大恰好11位.2025种组合对应2048,利用率将近99%.以下为示例

AC-42

AC-42→(10,12,41,4,2)
(10,12)10*45+12→462→00111001110
(41,4)41*45+4→1849→11100111001
(2)→2→000010

模式指示符:0010
字符数字:5 --->查表得9位-->5->000000101
结果:0010 000000101 00111001110 11100111001 000010

字节流

直接8bit一个码字

汉字

中文汉字的编码,需要由日文编码JIS X 0208的值转换而来,太繁琐了,只能请参见各种论文了.

补足余位

当然,最终完成编码的时候还需要在后面补上0000这个终止符,这个终止符如果剩余位数不足4位,可以截短,如果大于等于4位,均补0000.补全结束以后,如果该编码不足长度能整除8,那么继续补0,补齐8位.随后会放上 thonky的例子.

补全以后如果编码还是太短未到当前版本要求容量,那就增加11101100 00010001直到填满容量.十进制是236和17,至此编码数据结束,可以开始编码纠错模块.

在1-Q版本中编码 HELLO WORLD这11个字母.
查表可知,1-Q一共有13个码字,总容量13*8=104bit.
模式指示符: 0010
字符位数指示符(9位): 00001011(十进制数字是11)
数据编码: 01100001011 01111000110 10001011100 10110111000 10011010100 001101
以上编码总计74位.由于未达到总容量,所以补全0000终止符(如果以上编码102位,那么就只需要补00)
终止符: 0000

以上编码结束后,需要分成8bit一个码字
00100000 01011011 00001011 01111000 11010001 01110010 11011100 01001101 01000011      010000
发现最后一个码字只有6位,那么补全到8位0100000
由于容量目前是74+4+2=80,那么需要补全到104还需要24bit.填充11101100 00010001.
00100000 01011011 00001011 01111000 11010001 01110010 11011100 01001101 01000011 01000000  11101100 00010001 11101100

编码结束.

纠错编码


纠错一共有4个等级,恢复容量分别是L 7% M 15% Q 25 % H 30%

恢复容量的计算:如果初始有100个bit,我们希望能够恢复其中50个bit,那么这50个bit需要2倍的bit才能够纠错(具体请查阅有关论文!),所以现在一共有100+50*2=200bit.恢复容量=50/200=25%.也就是Q级.

纠错码字可以纠正两种类型的错误,拒读错误(错误码字的位置已知,既无法扫描到或者无法译码,例如缺失了某一角)和替代错误(错误码字位置未知,既读取到了该模块,但是由于奇奇怪怪的问题导导致黑读成了白,白读成了黑)。

首先,你要知道什么是多项式除法,例如3x^2+x-1被x+1除,相信学过高中数学的都会.
然后,你要知道什么是The Galois Field伽罗瓦域,也叫有限域.这里取GF(2^8),将数字运算限定在8位数里面.
伽罗瓦域需要模二取余(也就是XOR),并且以绝对值进行运算
例如1+1=2%2=0,1 ^1=0(这个是抑或XOR).0+1=1;1 ^0=1;

加罗瓦域2^8以100011101 ( 285)表示主模块多项式x^8+x^4+x^3+x^2+1,用这个数字对超出255的数字进行XOR. 2^8=256^285=29

好了= =,如果连续两个星期熬夜到三四点的我还能活多几个星期的话,我会把这一段补完,重开一篇新的文章的…不然直接看原文error-correction-coding

跳过如果RS编码那一块,接着就是如何排列这一些数据块.又是查表,例如查询版本5-H.

5    H    88    2    (33,11,11)
                     2    (33,12,11)

(c, k, r): c =码字总数 k =数据码字数 r =纠错容量

计算公式:c=k+2r.这里也就是之前所说的纠错一个bit需要2bit.

5-H版本纠错码字数为88(这个数字可以由r和块数计算出来,这里是4*2r=88),纠错块数为4,分成前2个和后2个.分成不同大小的块数是因为总码字无法直接整除12.

块1 D1 D2 D3 … D11 E1 E2 … E22

块2 D12 D13 D14 … D22 E23 E24 … E44

块3 D23 D24 D25 … D33 D34 E45 E46 … E66

块4 D35 D36 D37 … D45 D46 E67 E68 … E88

版本5-H符号的最终码字序列为D1, D12, D23, D35, D2, D13, D24, D36, … D11, D22, D33, D45, D34, D46, E1, E23, E45, E67, E2, E24, E46, E68, … E22, E44, E66, E88。如果需要,在最后的码字后面加上剩余位(0)。

由于找不到5-H的编码图形,用GIMP自己画会死的= =,只好用其他版本的了.下面这个图形,对于码字,排列顺序是从左到右,以蛇行方式排列,对于bit,实际上是以z字形不断扩展的.

掩模


掩模要事先除去功能图形,但是评分却是对整个图形进行的.一共有8种掩模,掩模的编号对二维码解码来说可以说是最重要的,如果无法正确识别掩模就无法读取整个图形的信息.

罚分标准:不仅仅是使整个图形黑白比例接近1:1,还有其余的判分标准.

行/列中相临的模块的颜色相同
模块块的颜色相同--模块数 = (5 + i)                                         罚分:N1 + i
颜色相同的模块组成*块-块尺寸 = m×n                                  罚分:N2× (m - 1)×(n - 1)
在行/纵列中出现1:1:3:1:1图形                                                 罚分:N3
整个符号中深色模块的比率-50±(5×k)%50±(5×(k + 1))%   罚分:N4×k

N1到N4为对符合以上特征所罚分数的权重(N1=3,N2=3,N3=40,N4=10)

选择掩模结果中罚分最低的掩模图形用于符号掩模

xor

格式信息

格式信息为15位,其中有5个数据位,10个是用BCH(15,5)编码计算得到的纠错位。

格式信息一共有两份,一份排布在左上角的寻象图形外围(需要去掉timing pattern交叉的两个点,恰好15位),另外一份拆分成两个部分,一部分在左下角寻象图形右侧,从低到高为0-7,另一部分在右上角寻象图形下方,有后7位,从右至左8-15

纠错等级指示符(1-2位):

L:01 M:00 Q:11 H:10

掩模图形指示符(3-5位):
000-111

将15位格式信息与掩模图形101010000010010进行XOR运算

L:11 M:10 Q:01 H:00

这个就是我们肉眼所见的能直观判断该图的纠错级别的符号.

版本信息

版本信息为18位,其中,6位数据位,通过BCH(18,6)编码计算出12个纠错位,放置在版本信息位.

只有版本7~40的符号包含版本信息


至此整个编码过程结束.各种个性化的二维码生成有机会再慢慢讲,当然前提是我看懂了那些论文和算法们.


部分图片,资料取自维基百科

部分图片,资料取自专利书ISO/IEC 18004:2006(E)

部分来源 thonky

魔法少女小圆

魔法少女小圆

madoka

如果说我用什么来判断时间的流逝,那就是每年必来的新番季.历经春夏秋冬两个轮回之后,我终于把小圆补完了.其实当我还在高三挣扎的时候,已经从宿友口中得知小圆,并且看了学姐被吃掉,身体掉下来的那一瞬间.在那以后,每当听见别人赞扬小圆的时候,我当时以为学姐的死就是小圆的全部,并且对小圆很不屑,就像我们都惊异于皇冠的神转折但是还是坚定的人为皇冠只是个渣番一样.我一直以为小圆是不值得补的.(当时错杀的还有石头门)

一年以后,我补完了石头门,被okarin一次一次的无力所震撼,又一年,我补完了小圆,又一次被这种无力的抗争所打动.

homura为了能够拯救madoka不断的倒退时间,去到平行世界的另外一端,一次一次的陪伴小圆,一次一次的绝望,最后变得冷漠,但是依然想去让小圆摆脱必死的命运,对,这里的homura可以替换成okarin,madoka换成mayuri和助手.又或者应该说这一幕更加像未来日记?应该说,能让我感动的,一个是勇往之前,无论什么艰难险阻都克服的热血意外,另外一个就是无论如何都无法摆脱的无力但是却又依然坚持的那份精神(baka)了吧.不过,在这样不停的往复当中,真的不会后悔么,如果当初没有这样做就好了这样的感觉.虽然后悔本身就很不负责任,选择了却不去承担,本来就是很狡猾的事情(觉得这句句子很奇怪的自觉替换成日语来读,然后就很顺口了).也许穿越时空改变世界线本身就是很自私的行为也说不定,为了自己能够让世界照着自己所想象的发展,所以要跨越世界线去寻找自己所期待的世界,遗弃自己所存在的世界线,而去到另外的世界线,如果抱着失败也没有关系最后再换一条线的感觉,那就太糟糕了,世界并不是可以自由选择的东西,而是选择了无论怎样都只能接受的世界.所以自由才成了这个时代的最强音吧,厌恶专政,厌恶独裁,期待民主,期待自由.尽管自由可能会带来好的坏的东西,最后承担这些的都是选择了他的我们而已,如果不好的东西就要再去改变他们,杨威利当初这么说的时候我也没能理解,不过慢慢的总算能理解为什么了.

在一次一次的重复当中最后应该是会失去自我的吧,看到最后的时候我差点以为那只是过去的回忆而已,直到小圆最后站在homura的身前决定再一次称为魔法少女的时候,我才意识到这里是世界的主线.如果这次小圆没有站出来,homura的循环也会到此结束了,即使说了”何度でも缲り返す”,但是最后还是要接受命运的无奈真是让人热血沸腾呢.”就是因为这个我才这么喜欢人类的说”.

既然要实现他人的愿望,就更应该搞清楚自己追求的是什么,你是希望他能实现你的梦想,还是想借实现他的梦想施恩于他呢。要是没弄清楚这一点,迟早有一天你会后悔的。

如果说魔法少女是从希望中诞生的话,魔女就是绝望的叹息.魔法少女的诞生存在这巨大的不合理,能够完成一个超乎世界规律的愿望,以此来换取灵魂,将灵魂独立出来.但是世界始终是公平的,希望的诞生也伴随着绝望.一面期待着拯救世人,另外一面确是杀戮的化身.用性命来换取的愿望,不知道有多少人有呢?至少我没有什么牺牲自己也要完成的愿望,我只想就这样活下去而已,虽然没有目标,虽然有很多不满,但是也找不出不合理的地方,已经成为日常的东西连打破也需要很大的勇气才行.如果说这个愿望是为了别人的话,在我看来真的是很不值得吧,为了自己还能说是without compunction.为了别人的话,如果被别人背叛的话,那就会堕落到比任何人都要深的黑暗中去的,鹰之团团长,还有很多很多这样被背叛的人.

嘛,一定是因为我们两个是笨蛋啦.对,幸福的笨蛋。其实也没什么稀奇的啦,那种就算拼上性命也想要实现的愿望,这个世上也一定有很多人怀抱着这些东西吧,所以找不到这种目标的我们,正好说明了我们不知道那样的痛苦,因为受到了太多的恩泽,所以变成了笨蛋啊

越是重复,就越是偏离你和我生活过的时间。心意也相互偏离,言语也渐渐无法相通,我想我大概早已迷路了。“要拯救你”这是我最初的心意,而到如今,这是最后留下的唯一路标了

印象比较深刻的还有生命之树,魔女们,到处都洋溢着一阵EF+EVA的风格,小圆真是一部很值得称赞的作品呢.

impress.js使用小记

前言

在偶然的机会下,接触到prezi这样一种展示工具,但是因为庞大的开发套件&收费让我止步,幸运的是,找到了impress.js这样一种替代品,如此精简而又优秀的展示工具.impress.js需要搭配html+Css实现,尽管已经有两三个visual design tool,但是效果差强人意,唯一一个比较满意的就是markdown2impress.不过由于需要实现自己的网页风格,还是决定全部自己写.下面就介绍一个如何设计一个基于impress.js的网页/展示.


首先还是先放官方demo以及我制作的presentation.

demo-slixurd 对内容感兴趣的一样可以进入OpenSource查看以及下载

demo-official


然后..一个JS如何实现一个网页呢?妈妈告诉我们,程序员们最重要的能力就是看源代码,所以当你下意识的点开查看源代码的时候,你已经开始迈出第一步了.原本想翻译作者的源代码的(因为作者把基本步骤都写在源代码里面了),不过看到已经有人翻译了,那二次劳动就免了,点击这里阅读eyehere的翻译 .鉴于网上的教程都是从一份英文教程翻译而来并且翻译的不知道如何评价.不过由于大体正确,我也没必要继续重复写,我就从另外的角度来讲好了.

就如同作者所说的一样

So if you want to build great presentation take a pencil and piece of paper. And turn off the computer.
Sketch, draw and write. Brainstorm your ideas on a paper. Try to build a mind-map of what you’d liketo present. It will get you closer and closer to the layout you’ll build later with impress.js.

布局

impress

这是官方demo的布局.首先我们需要知道座标定位所需要的变量,impress.js一共提供了4个主要定位的参数(3d变换不算).

data-x="3500" //只要学过数学的都应该知道.这是直角座标系(装B的说法是-笛卡儿座标系)

data-y="2100" //但是方向不一样,y是以下为正方向的

data-rotate="180" //这个是旋转角度

data-scale="6"//这个是放大倍数

定位点均为该子页面未缩放及旋转前的左上角,所以我们可以在图上看到座标系的原点.(不是(0,0)标示的位置,而是黑色x轴那里.)我们需要为每一个页面做定位.所以设计在这里就显得很重要了.
倍数可以带小数,例如0.001,旋转角度可以是负数,也可以超过360(表示多次旋转),善用缩放和旋转是让presentation出彩的重要一环.所以,离开电脑,好好画一下布局,好好设计才是正道,像我这种做完以后都不敢放overview的千万不要学.

基本结构

我们直接看全局结构吧,以下是最小结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<head>
<link href="css/impress-demo.css" rel="stylesheet" />
</head>

<body>
<div id="impress">
<!--content start tag -->
<div id="first" class="step" data-x="0" data-y="0" data-rotate="180" data-scale="3">
<p>the first try</p>
</div>
<!--end tag -->
</div>
<script src="js/impress.js"></script>
<script>impress().init();</script>
</body>
</html>

作为一个网页必须的元素当然都是必须有的,例如最外层的<html>标签,然后其中的<head><body>两个标签.谈谈impress.js需要的东西.

第一个:<script src="js/impress.js"></script>//链接js脚本

第二个:<script>impress().init();</script>//这个也可以用他自带的其他api,不过一般init就足够了

选择可有:<link href="css/impress-demo.css" rel="stylesheet" />

script最好就是直接放在body结束标签前,否则有机率无法载入.css样式表根据自己需要修改,删除,增加.
其实实际上,如果想偷懒的话,直接在我所标示的content tag中间加内容就可以了.

鉴于impress.js只支持chrome,safari,ff.所以做不支持的提示是很重要的,因此可以这么写<body class="impress-not-supported"> 在能够支持的情况下,js会自动替换掉这个class(不信的话用chrome打开网页查看源代码,查看和直接阅读html的区别),无须担心.

最重要的就是#impress这个id,只有查找到这个标签的时候,才会执行impress.js.所以在body标签之后就是一个<div id="impress"></div>的标签,所有的内容都在里面.

然后就进入了子页面,每一个页面都是div,必须有的元素是:.step,x,y.例如上述例子
<div id="first" class="step" data-x="0" data-y="0" data-rotate="180" data-scale="3">
id是这个子页面的名称,最后仅仅只在地址栏有显示,是页面的唯一标识,所以不能够相同.然后是class=”step”同时我们也可以用class=”step slide”这种滑动页面,不过step是必须的,slide是可选的,同时如果自己有编写css,一样可以用自己的class.随后必需的是data-x,data-y.如果没有scale,默认为1,没有角度,默认为0;

另外,作者提供了data-z这个参数,也就是所谓的3d-transform,标示在z轴的位置.效果如同一开始的概览图的12号.另外还有data-rotate-x data-rotate-y data-rotate-z 这些参数,唯一不同的是,这些的参数的单位是度数.而x,y,z使用的是px.此外还有一些参数感觉没有什么用的就没有解释了,都可以在源代码的注释里找到.

推荐源代码注释和本文都一起读,否则会觉得不知所以.关于css的部分我就不讲解了.我自己的presentation中最主要用的两个类是blurBG和pic.只是简单的圆角+背景+透明度+阴影的组合而已.可以自己尝试搭配,实在不会的话可以搭配各种代码审查(主流浏览器下按F12)查看css并做修改.

Open Source展示&impress.js

展示地址:click here

下载地址:click here(github) 该目录下所有文件都是需要的

注意:包括本站点在内,仅在chrome下测试过,其他浏览器不能保证效果.应该说= =,IE肯定是不行的,国产webkit的壳(例如愚蠢的高速模式还是什么来着也是不行的).

KeyPoint

  • copyright&&copyleft

    Open source and copyrights
    Anything that is not public domain has a copyright, the copyright does not have to be explicit. That is, the authors of a work hold copyright even if there is no copyright notice.

  • 在人们认为有价值的诸多价值之中,自由是最有价值 的一种价值。

What qualifies as open source

根据许可的目的,我们可以区别许可证赋予你的各种不同权利。复制和再发布的权利,使用的权利,为个人目的修改的权利,发布修改后的作品的权利。一个许可证可能会对这些权利加上一些限制或给出一些附加条件。

无限制的拷贝权
无限制的使用权
无限制的针对个人使用目的而修改的权利

For licensing purposes, we can distinguish several different kinds of rights that a license may convey. Rights to copy and redistribute, rights to use, rights to modify for personal use, and rights to redistribute modified copies. A license may restrict or attach conditions to any of these rights.

The Open Source Initiative is the result of a great deal of thought about what makes software open source or (in older terminology)free. Its constraints on licensing require that:

An unlimited right to copy be granted.

An unlimited right to use be granted.

An unlimited right to modify for personal use be granted.

  “自由软件” 实际上指的是一种自由,而不是价格。

  “自由软件” 中的自由是指用户运行、拷贝、研究、改进软件的自由。

  “自由软件” 使用“copyleft”来合法地保护每个人的自由。

Copyright is a legal concept,giving the creator of an original work exclusive rights to it, usually for a limited time.Generally, it is “the right to copy”, but also gives the copyright holder the right to be credited for the work, to determine who may adapt the work to other forms, who may perform the work, who may financially benefit from it, and other related rights.

Copyright was invented after the advent of the printing press and with wider public literacy. its origins in Britain were from a reaction to printers at the beginning of the 18th century.

YOU CAN NOT :publish without authorized,publish if after modifying,copy

public domain 公有领域

Works in the public domain are those whose intellectual property rights have expired

Public domain works can serve as the foundation for new creative works and can be quoted extensively. They can also be copied and distributed to classes or digitized and placed on course Web pages without permission or paying royalties.

copyleft 反版权

Copyleft: Pragmatic(务实的) Idealism

Every decision a person makes stems from the person’s values and goals. People can have many different goals and values; fame, profit, love, survival, fun, and freedom, are just some of the goals that a good person might have. When the goal is a matter of principle, we call that idealism.If you want to accomplish something in the world, idealism is not enough—you need to choose a method that works to achieve the goal. In other words, you need to be “pragmatic.”

一个程序遵循 Copyleft,我们首先声明它是有版权的;然后,我们给它加上发布的规则,这个规则就是一个法律声明,它赋与所有人有使用、修改和重新发布程序的代码 及其衍生作品 的权力,但要求在这个过程中这个发布规则是不可以改变的。这样的话,代码和自由权力在法律上就不可分割了。

商业软件开发人员通过版权剥夺了用户的自由,我们使用版权来给予他它自由。这就是为什么我们把“版权(Copyright)”改称为“Copyleft”。

GPL

隶属copyleft.应该说是copyleft最初的模式之一.
在每一程式副本上明顯和恰當地宣告版權聲明和不承擔擔保的聲明,可以為轉讓副本的實際行動收取一定費用。您也可以自由決定是否以提供擔保來換取一定的費用。必須在修改過的檔案中附有明顯的說明,可以以目標碼或可執行形式複製或發佈程式 (可以以目標碼或可執行形式複製或發佈程式 ,如果您修改或發佈程式 (或本程式的衍生作品) ,您就表明您接受這一許可證以及它的所有有關複製、發佈和修改程式或基於程式的作品的條款和條件。您不可以增加任何條款來進一步限制本許可證賦予他們的權利。您也沒有強求第三方履行許可證條款的義務。

沒有擔保

Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.

The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software—to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation’s software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too.

MIT

隶属non-copyleft.(copyleft坚持认为在自由软件基础上作修改后的软件,仍旧是自由软件。Non-copyleft许可则不坚持这一点。 proprietary[prə’praiətəri])
最宽松的一种开源协议之一.有权利使用、复制、修改、合并、出版发行、散布、再授权及贩售软件及软件的副本。被授权人可根据程序的需要修改许可协议为适当的内容。而需要履行的义务仅仅是在软件和软件的所有副本中都必须包含版权声明和许可声明

BSD

隶属non-copyleft.
可以自由使用这些代码,包括修改、再分发.使用并修改、再发布BSD授权的源代码时,新的代码需要附带BSD协议

  1. 所有提及该软件特征和使用方法的广告材料必须提示下列的致谢内容:
      “此产品包含有由加利福尼亚大学,柏克利和它的投稿人编制的软件。”

必须保留拷贝权的声明和协议里的软件权利放弃条款。不能使用原作者的商标、名称等用于宣传和市场推广。

Apache协议

这些权利可以应用于拷贝权,也可以用于专利权(scope of work)。
权利永恒。权利无疆界。授权无需付费和支付酬劳。权利不排他。权利不可变更。

story of android

“Google has taken the Linux kernel, and nothing else from a “traditional” Linux system.
Google只用了kernel,别的东西都没用。”

“Android also solves the problem that the phone manufacturers had been having for many years: a free version of Java and a unified application layer that programmers can write to that will work on all phone platforms that integrate it.

它解决了长期令手机制造商头痛不已的问题:业界缺乏一个开源的Java虚拟机,以及统一的应用程序接口。现在,程序员只要写一次程序,就能在各种手机硬件平台之上使用。”

Kernel和Android的许可证不一样,前者是GPL许可证,后者是Apache许可证.Google有意选择了这样做,并且特意修改Kernel,使得原本应该包括在kernel中的某些功能,都被转移到了userspace之中,因此得以避开开源.Google也放弃了构建一个真正开源的手机系统的机会.这就是Android干的事情:它修改了Kernel,但是又不提供修改的细节,自己搞了一个封闭的系统。说得难听一点,它利用了开源社区,要求开源社区为它做贡献,却又不愿提供回报

http://www.ruanyifeng.com/blog/2010/02/revisiting_android_licenses_continued.html

CC

4种基本标识->组成六种核心协议

署名-非商业使用-禁止演绎 (by-nc-nd)

署名-非商业性使用-相同方式共享 (by-nc-sa)

署名-非商业性使用 (by-nc)

署名-禁止演绎 (by-nd)

署名-相同方式共享 (by-sa)

署名 (by)

Hall of Shame

Hall of Shame

This is a list of projects, persons or companies violating Libav’s license. The list is part of an effort to raise awareness of license violations and get violators to comply with the licensing terms in order to eventually move them from this Hall of Shame to our Hall of Fame instead.

部分内容参考自以下网站:

阮一峰 android

GNU

外刊IT评论

aka

CC

MyBoxyBeta 设计模式分析

MyBoxyBeta之架构设计


前言:

这个游戏已经写完很久很久很久了,当时还没有学会用git,版本管理是用最简单的打包src然后标明日期时间,现在看起来真是很幼稚的东西.当时是由两个大二的同学带着刚入大一下学期的我来开始的这个项目,实在是非常感谢.

在简单的设计模式入门以后,才发现他们当时设计的架构已经非常不错了,对于我这样面对对象的新手来说,我当时的任务就是一个码农,由带队的老大设计好整个架构然后分配任务给我,很羞愧的是,我先自己按照功能需求完成细节(具体需求可以看DOC文档),然后再添加接口来匹配上层建筑.拿Mirror_Area,Black_Hole,Exclude_Hole来做例子吧,全部都是派生自Area这一个类的,我写的时候确是将三个具体类先完成,然后看到需要匹配基类,就将写好的类当中的需要独立的功能独立出来放入公共的接口当中.

最后当我们完成整个程序的时候,基本框架的确是对了,但是我们疏忽了一点,性能!对于一个android的机器来说,并没有那么多的性能提供给我们,我们在初始化的时候,每一次的level select都会重新创建对象,最后虽然有释放,但是不管是android的还是java的GC都无法令人满意,我们在接近完成的时候是想修改的,无奈耦合的地方太多,难以修改.然后我们约定,在有限的将来当中,如果还有机会,要重构这个游戏.具体思路很简单,第一次进入游戏的时候就将所有需要用到的对象初始化,以后如果不需要用到,采用隐藏的方式而不是销毁,这样可以避免多次初始化造成的内存爆炸.


基本结构

首先,我们知道android的main入口其实就是Activity,本游戏一共有3个Activity,分别代表3个界面.前两个界面只涉及通过intent的activity的切换,十分简单,不作详解,同时,关于游戏引擎AndEngine也不作讨论,只讨论MyBoxyBetaActivity,即游戏界面.

IMG IMG IMG


游戏操作类

IMG
游戏操作类一共有4个,其中最主要的当然是MyBoxyBetaActivity,控制着其他控制类的的操作,我把它称为controler.下面有3个属于关联关系的操作类,分别是Boxy_GameFinish,Boxy_level,Boxy_refresh.作用一看便知,分别用来结束游戏,初始化关卡,刷新关卡.

IMG

而操作实体我称之为Object.基类Boxy_object拥有接口(interface) CommonFunction. Boxy_object派生3个主要的”实体类型”,分别是区域,板,特殊元件.其中板和特殊元件又是互相关联的.这3个类具体派生的类见UML图.

IMG

为了减少操作类和具体实体类之间的耦合,所以以Boxy_object作为操作类可以直接使用的元素,所有需要生成具体实体都需要依赖Boxy_object这个基类,这样也能强制所有的具体实体都拥有相同的接口以方便初始化,销毁,启用以及休眠.

IMG

Boxy_level类

Boxy_level类以一个数组private final static float[] level来储存所有的游戏关卡数据,每次需要初始化就根据当前关卡读取数组就可以了.读取关卡数据结束以后,就进入public void InitialObject()函数,进行具体实体的初始化,这里采用的是简单工厂模式,因为在组合并不多的情况下,没有必要使用抽象工厂或者其他的模式,

Init object

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public Boxy_Object[] object_array=new Boxy_Object[level_num]
for(i=0;i<level_num;++i)
{
seeker=level_start_index;
switch((int)level[seeker])
{
case 11:
object_array[i]=(Boxy_Object)new Boxy_NormalBoard(..);
break;
case 12:
object_array[i]=(Boxy_Object)new Boxy_WoodBoard(..);
break;
case 13:
object_array[i]=(Boxy_Object)new Boxy_BlackHole(..);
break;
..
}
}

通过这样的工厂类,可以使得MyBoxyBetaActivity本身并不实际与各个具体实体相关联,当需要增加实体个数,种类的时候,只需要在level数据中增加就可以了,虽然并没有做成抽象工厂,但是我们的目的是可以轻松增加游戏关卡,而不是为了模式而作模式.尽管这里违背了开放-封闭原则,但是却依然易于维护,如果盲目增加工厂类,就会造成类数量过多反而不好维护的问题.

Boxy_GameFinish类

Boxy_GameFinish类是负责当一个关卡结束的时候,销毁当前所有的实体的(其实这里希望做到的是隐藏,而不是销毁).当然,这个类本身并没有任何能够销毁实体的函数,他所做的仅仅指示发出消息罢了,通过这个消息,然后通知level类进行public void DestroyLevel()随后object基类调用public void destroy()这个函数而已,通过一个消息而监管所有的元素,这里采用的是观察者模式.

destroy object

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void DestroyLevel()
{

int lv_num=(int)level[level_start_index];
for(int i=0;i<lv_num;++i)
{
if(object_array[i]!=null)
{
if(!object_array[i].isrubbish)
object_array[i].destroy();
else
object_array[i]=null;
}
java.lang.System.gc();
}

Boxy_refresh

Boxy_refresh是在用户并没有通过这一关的时候刷新本关关卡重新开始游戏的,最主要就是其中的三句而已.

1
2
3
parent.level.DestroyLevel();	
parent.level=new Boxy_Level(parent.level_index,parent);
parent.level.InitialObject();