logo

Shapez Theme

· Home Playground About

08


APRIL

最近上vpn比较多,我自己的网站竟然常常封闭我自己的IP,提示我必须输入验证码才能访问,过分的是,输入只能看一页,第二页还得再输入一遍,这个cloudflare做的也太过分了。于是登录cloudflare后台一探究竟。

首先,最近vpn的流量比较大,所有其他免费的vpn都不够用的,只有mxvpn的一个特定线路可以使用,可能大家都用这个线路,有的人拿他做点坏事也不一定,所以就不停的被cloudflare判做恶意站点或是机器人,所以验证码也就出现了。

之前没使用vpn的时候,偶尔也发生这个问题,着实让我头疼了一番,不过这次一并解决,写出来与大家分享下。

cloudflare中站点管理的最后一项,是个threat-control,这个是威胁控制,就是处理谁攻击你的计算机的一项,点击进去会发现有很多个ip(不同站点不同),这些ip都是它认为发生过有危险的访问,这些ip会被拒绝访问,找到自己的ip,点击Trust,信任该IP就可以了。

而且,即使你被要求输入验证码,当点击了信任以后,并不需求输入验证码,直接刷新就可以进入站点。

logo

Shapez Theme

· Home Playground About

24


MARCH

由于000webhost的空间数据库时常抽风,一直考虑换个数据库的,所以发现了免费的云端数据库Xeround

这个是个好东西,免费的可以提供10M的mysql存储空间,注册申请啥的网上网上都写得蛮详细的了,这里就不做详细介绍了(其实只要英语不是太差,都看得懂的)。

我这里使用遇到了问题,链接数据库时,发现他提供的连接路径有两个,而且路径中有”.:”这样的字符,开始还想,难道这是使用了IPv6么?但是后来发现把那个点去掉,就可以在本地计算机上连接。

我创建的数据库使用的是Amazon Ec2上创建的数据库,它提供了两种连接字符串:

总体来说,思路是对的,看样子这个数据库的性能还不错。但是,在000webhost上,怎么写连接字符串都无法访问。百度上也曾有人问到这个问题,但没见到回答。如果哪位读者成功了,记得分享啊。

logo

Shapez Theme

· Home Playground About

17


MARCH

做个视频网站,但并没有使用专门的流媒体服务器,所以要在apache上开个流式媒体输出。

这里的流式媒体输出跟专业的流媒体服务是两回事。这是在apache中添加一个模块,使得以视频流的方式访问,并不需要全部加载完视频后就可以播放。

这里只支持h264编码的mp4后缀。所需要启用的模块为:

mod_h264_streaming

安装过程:

1、首先安装 apxs2

sudo apt-get install apache2-threaded-dev

2、下载 H264 Streaming Module for Apache

cd ~
wget http://h264.code-shop.com/download/apache_mod_h264_streaming-2.2.7.tar.gz
tar -zxvf apache_mod_h264_streaming-2.2.7.tar.gz

3、编译

cd ~/mod_h264_streaming-2.2.7
./configure –with-apxs=`which apxs2`
make
sudo make install
注意:ubuntu 的apxs2 位于 /usr/bin/apxs2

4、编辑 Apache 的配置文件 (/etc/apache/httpd.conf)以添加流媒体处理选项

LoadModule h264_streaming_module /usr/lib/apache2/modules/mod_h264_streaming.so
AddHandler h264-streaming.extensions .mp4

5、最后,重启 Apache 即可

sudo /etc/init.d/apache2  restart

实际应用中遇到的问题

由于有些缩略图的文件名中包含”.mp4.”这样的部分,路径中出现这样的部分同样会被该模块捕获,但又处理不了,所以会报错。为此我们专门修改了文件的路径。

logo

Shapez Theme

· Home Playground About

17


MARCH

前几天开了个Amazon aws的帐号,由于是第一次碰,一点点摸索着运行了一台Ubuntu 10.04的实例,遇到的问题记录下。

1、记得开放需要的端口

linux一般使用SSH客户端进行连接,所以必须要打开22端口,否则实例化后连不上,等于白白消耗你的信用卡。

一般启动一个LAMP的话,这几个端口是需要打开的:

当然这些端口都可以修改的。但第一次一定要开的就是ssh的端口。

2、记得上网搜索问题,我遇到问题是Permission denied (publickey)

Amazon的帮助文档还是比较全面的,我这个不懂linux的人,也可以参照帮助文档连接,不过,文档中可是有错误的。比如点击连接计算机的时候,这里就只是说输入这样的命令就可以进去:

ssh -i xxx.pem root@your Public DNS

可是总也连不上去,提示:

Permission denied (publickey)

后来查了下,说linux第一次进去时,root是没启用的,要用ec2-user这样一个用户名。无奈,尝试了,还是不行,进不去啊。(后来查的说是在ami上自己安装的ubuntu使用ec2-user,我们是直接实例化的系统,不一样)

直到最后才搜索到ubuntu的登录又得用另外一个用户名:ubuntu。

其他关于ubuntu的设置,就不记录了,网上的资料比较多。

logo

Shapez Theme

· Home Playground About

17


MARCH

min.us是一个非常不错的在线存储空间,有需要的可以去申请下。

min.us是美国一家在线文件存储提供商,直接注册提供10G的在线存储空间,比dropbox等要大很多,最吸引我的一点是其支持直接外链,很是方便。主要指标为:

注册提供10G空间。
可以通过邀请好友提升空间到50G,1G/好友。比dropbox的每好友250M强多了。
提供直接外链。
外链流量无限制。
最大单文件大小限制:空间总容量的20%,10G的空间,大概有200M

邀请链接:min.us

logo

Shapez Theme

· Home Playground About

17


MARCH

上一篇写了网易邮箱的签名设置方法,普遍反馈太难了,为此,今天特制作一个邮箱设置的页面,用jquery实现的。

第一步:设置签名模板

下面是一个邮箱模板:

模板链接

点击该链接进去,可以看到一个签名模板,你可以点击其中的姓名,在弹出的输入框里写上你自己的姓名。如图:

填写你的名字,同理,你还可以在部门和电话的位置分别填写部门和电话,填写成功后检查是否正确,下面是我填写的一个示例:

这是后签名就已经设置好了。

第二步:设置邮箱中的签名。

复制这段文字,要从名字一直复制到最后的公司两个字,如图

右键选择复制,然后进入你的邮箱,在前面设置的位置,将复制的内容粘贴保存即可。如图:

这次还算简单吧。

logo

Shapez Theme

· Home Playground About

11


MARCH

本人电话号码使用已久,在各种网站上还注册时留过电话号码,今年明显感觉骚扰电话大量增加,为此一直想要更换个电话号码,但更换电话号码成本也很高,虽说大不了挨个通知,但实际上我也总收到朋友们更换号码的短信,实际上会存成两个号码,到最后很可能还是联系不上。所以一直想办法来解决这个问题。

对待骚扰电话,我向来是宁可错杀一千,也不漏过一个。不过我对电话倒不是很敏感,所有电话,往往反映很迟钝,以至于我媳妇总说给我配个电话多余,都接不通。

所以这种情况下,我实际上很少听到骚扰电话,只是每次拿起手机,就发现有几个未接电话。我的手机是早期的windows mobile的手机,之所以用这个手机,实际上比较熟悉这里的软件,值得一提的是一个叫做QCellCore的软件。它可以拦截骚扰电话(黑名单)、拦截垃圾短信,在拦截黑名单的时候,有三种模式:

我一直使用空号模式,之前用这种方式成功阻击了一个保险公司的推销电话,后来再也不来骚扰了(估计已经从他们的数据库中删除了),现在的安卓智能手机似乎也有个黑名单的功能,不过好像没有这个功能强大。

现在我对于每个收到的未接的非通讯录号码,直接加入黑名单,无奈,现在的骚扰电话方式越来越多样,每次拨给你的号码都不一样,逼得我曾经想屏蔽整个150、151号段,最近是屏蔽所有来自东莞的电话(不知道为啥,东莞的骗子电话特别多)。当然,一个人的黑名单,对于骗子来说,他每购买使用一个电话号码,就足够骚扰几亿人了,成本太低了。

于是,就有这么一个想法:把电话黑名单列出来,供大家参考,同时,将来维护一个电话黑名单数据库,让这些电话只能打少量的骚扰,只要有人汇报黑名单,就让他上黑名单,或许将来我们可以做的跟对付垃圾评论一样吧。

下面是我的手机中的黑名单记录:

[items]
04008195095=&3&00:00:00&23:59:59
4008125860=英孚推销&3&00:00:00&23:59:59
010950950=中意人寿推销&3&00:00:00&23:59:59
15920739461=&3&00:00:00&23:59:59
02129986075=&3&00:00:00&23:59:59
15011661034=&3&00:00:00&23:59:59
14790689147=&3&00:00:00&23:59:59
15010216974=&3&00:00:00&23:59:59
13425734244=&3&00:00:00&23:59:59
15813627825=&3&00:00:00&23:59:59
13726327445=&3&00:00:00&23:59:59
13516514201=&3&00:00:00&23:59:59
13726312720=&3&00:00:00&23:59:59
13630005435=&3&00:00:00&23:59:59
15820671693=&3&00:00:00&23:59:59
15015517040=&3&00:00:00&23:59:59
15044953394=&3&00:00:00&23:59:59
15813658456=&3&00:00:00&23:59:59
15919054480=&3&00:00:00&23:59:59
15007577742=&3&00:00:00&23:59:59
15813653546=&3&00:00:00&23:59:59
15015624093=&3&00:00:00&23:59:59
15011653831=&3&00:00:00&23:59:59

后面的时间,是全天拦截,=号后面的,是记录的备注名称。

我正在找合适的空间,google code似乎被 墙 了,再找个合适的空间维护这个黑名单记录吧。

logo

Shapez Theme

· Home Playground About

20


JANUARY

这里简单记录一下过程,其实大多数的说明在网上都有详细的说明,这里只详细记录遇到的过程。

1、在IIS中创建证书申请,注意一般加密的位长要设置为2048位。写入一个txt文件,可以生成一段密文,类似下面这段:

-—-BEGIN NEW CERTIFICATE REQUEST—–

…….

-—-END NEW CERTIFICATE REQUEST—–

2、把生成的证书文件提交给认证厂商。

3、对方会返回一个加密认证后的文本,将该文本保存为.cer文件,导入到iis中(使用完成证书申请)。

4、windows azure中的源代码中,找到Roles文件夹,选中.WebPortal文件,右键属性中,找到Certificates,点击Add Certificate

这是后会增加一行,前面的都不要管,只是在Thumbprint项中,点击后面的选择,会自动找到本机安装的所有证书,选择该证书即可。

5、在iis中将该证书导入到windows azure中的对应的证书目录中。然后上传编译好的代码。

注意事项,申请证书的计算机与完成认证过程的计算机需要是同一台,而且,申请和完成期间最好计算机不要做更新。我的电脑恰巧在第二天早上做了关于证书方面的更新,所以发生了证书完成后无效的问题,也就是说密钥被更新给弄乱了(具体情况不了解,反正是不能用了)。

解决办法就是找到证书的指纹,然后运行命令:

certutil -repairstore my “THUMBPRINT_OF_CERTIFICATE”

其中THUMBPRINT_OF_CERTIFICATE要替换成对应的指纹。

然后就可以了。

要回家了,先发这些吧,有时间再整理。

logo

Shapez Theme

· Home Playground About

28


DECEMBER

转自zendchina,可查看原文,之所以转载,是因为网上的各种资料都不太全,本文很全面。本人在该问题上也遇到很多困难,终于从本文获得启发。希望遇到同样问题的朋友们能尽快解决该问题。同时声明:网传的windows下不能使用zend调试是错的,很难用也是错的,只是不得法而已,不要以讹传讹。我自己尝试的辛苦,希望朋友们能少走些弯路。

下载xdebug,看清版本,很重要,这里使用php_xdebug-2.0.5-5.2.dll,符件中有;

必须以Zend方式加载,见php.ini中配置。配置D:EasyPHPPHPphp.ini,先把optimization注释掉使用”;”

如下:

;[Zend]
;zend_optimizer.optimization_level=1023
;zend_extension_ts=“../Zend/ZendExtensionManager.dll”
;zend_extension_manager.optimizer_ts=“../Zend/Optimizer-3.3.0”
;zend_extension_ts=“D:/EasyPHP/PHP/ext/ZendDebugger.dll”
;zend_debugger.allow_hosts=127.0.0.132
;zend_debugger.expose_remotely=always
;extension=php_xdebug-2.0.5-5.2.dll
[Xdebug]
zend_extension_ts=D:/EasyPHP/PHP/ext/php_xdebug-2.0.5-5.2.dll
xdebug.profiler_enable=on
xdebug.trace_output_dir=“D:/EasyPHP/xdebug”
xdebug.profiler_output_dir=“D:/EasyPHP/xdebug”
xdebug.remote_enable=On
xdebug.remote_host=“localhost”
xdebug.remote_port=19000
xdebug.remote_handler=“dbgp”

请修改端口为19000防止端口被占用,修改web browse,如下图

1_201105271110431yKQ8[1]
02f3aa69-a72c-3f6f-9961-df2175130fd1[1]

不要使用FF会报下面的错误:

waiting for XDebug seession…就不动了,选择IE正常
3b626781-cc30-3c93-a00a-37971669368f[1]

1_201105271110432Amea[1]

然后再按下面配置:

**另外:
**

Zend Studio for Eclipse开启XDebug的方法:

- 6.0.0pluginscom.zend.php_6.0.0.v20080107plugin_customization.ini

将这行org.eclipse.ui.workbench/UIActivities.com.zend.php.debug.ui.XDebugActivity=false
改成true,保存后,重新启动Zend Studio 7,php debug里面就可以选择Xdebug进行调试了。

1_201105271110433rX2W[1]
cfcf2c2e-e88f-3587-aa2a-8fd36d92d2cf[1]

1_201105271110434SBhM[1]
404fa9ad-6b50-300e-8397-8aed9bfb24df[1]

1_201105271110435A1DJ[1]

选择要debugger的web页面

1_201105271110436fT64[1]1_201105271110436fT64[1][1]1_201105271110436fT64[1][2]1_201105271110437mM47[1]1_201105271110437mM47[1][1]1_201105271110437mM47[1][2]1_2011052711104380406[1]1_2011052711104380406[1][1]1_2011052711104380406[1][2]1_2011052711104397eht[1]

另外WinCacheGrind的使用参考:http://hi.baidu.com/lostdays/blog/item/c2ef51a920c62ff81f17a2f4.html

我的phpinfo信息如下,方便出现问题对比版本:

PHP Version 5.2.5

System
Windows NT WV 5.1 build 2600

Build Date
Nov 8 2007 23:18:08

Configure Command
cscript /nologo configure.js “–enable-snapshot-build” “–with-gd=shared”

Server API
Apache 2.0 Handler

Virtual Directory Support
enabled

Configuration File (php.ini) Path
C:WINDOWS

Loaded Configuration File
D:EasyPHPPHPphp.ini

PHP API
20041225

PHP Extension
20060613

Zend Extension
220060519

Debug Build
no

Thread Safety
enabled

Zend Memory Manager
enabled

IPv6 Support
enabled

Registered PHP Streams
php, file, data, http, ftp, compress.zlib, compress.bzip2, zip

Registered Stream Socket Transports
tcp, udp

Registered Stream Filters
convert.iconv.*, string.rot13, string.toupper, string.tolower, string.strip_tags, convert.*, consumed, zlib.*, bzip2.*

logo

Shapez Theme

· Home Playground About

20


DECEMBER

ffmpeg简介
FFmpeg 是一款跨平台的,对视频、音频进行录制、转换、播放的命令行形式软件,它使用的是 libavcodec 编解码器。FFmpeg 官方网站是 http://ffmpeg.org/
官方网站提供的是未编译的 FFmpeg 源代码。有兴趣的朋友可以自己下载源代码编译。一般我们都会偷懒,去下载现成的。
php_ffmpeg资源
源码及编译方式见:

http://sergey89.ru/notes/ffmpeg-php-windows/

各种win32版本的下载:

http://ffmpeg.arrozcru.org/builds/

配置方法
1,解压
2,将 php_ffmpeg.dll 文件 复制到 php 的 extension 目录
3,将其他所有文件复制到 Windows 的SysWOW64目录(注意:32位系统复制到windows的 system32目录里)
4,在 php.ini 文件中,增加一句: extension=php_ffmpeg.dll
5,重启 apache
可以用 phpinfo(); 函数看安装结果。如果出现 ffmpeg support enable 字样,说明安装成功。
刚开始的时候,把相关文件拷贝到了system32中,总出错,提示“unable to load dynamic library‘ xx/xx/php_ffmpeg.dll’”,后来感觉可能是版本不对,想找到相应的64位的php_ffmpeg.dll文件,走了很多弯路,最后看到转载的这篇文章,才成功。

       原创版本没有找到,网上传播很广的都是改过的转载,但链接都没有了。      我这里加入了两个链接,在此向原作者致谢,同时未经许可,对文字做了修改,请谅解。另外把我自己下载的版本提供给大家下载。我的是php5.3版本的:

ffmpeg-php-5.3-win32-all.zip

logo

Shapez Theme

· Home Playground About

20


DECEMBER

很久之前,曾经用过一个代码编辑器,具体名字叫什么不记得了,但对我印象最深的是他的本地修改历史记录。我一直在意代码的历史记录,以至于在本地搞个vss来保存不同的版本。现在用的是svn。但总觉得许多时候本地修改记录本地来记录更合适一些。今天使用Eclipse时突然发现有个本地历史的功能,原来我想要的功能在Eclipse中已经包含了。

首先我们可以看看关于本地历史的设置位置:

窗口->首选项->常用->工作空间->本地历史,默认设置如下图所示:

这三个项分别是:

我们可以根据自己的情况进行设置。然后就可以从文件列表中直接打开本地历史记录了,还集成了比较功能呢。

logo

Shapez Theme

· Home Playground About

12


DECEMBER

本文记录youtube 的几个常用api,并使用其中一个介绍其使用方式。

首先,我们来看看这几个api:

http://gdata.youtube.com/feeds/users/username/uploads  
\- videos uploaded by username  
  
http://gdata.youtube.com/feeds/users/username/favorites  
\- videos bookmarked by username  
  
http://gdata.youtube.com/feeds/users/username/playlists  
\- playlists created by username  
  
http://gdata.youtube.com/feeds/users/username/subscriptions  
\- username's subscriptions

就是说,如果你要显示username这个用户(不知道有没有这个用户)的视频,可以访问
http://gdata.youtube.com/feeds/users/username/uploads
这个路径来获取数据。其他的就不用讲了。
有趣的是,google给这四个api设置了差不多的参数,常用的有:
?max-results=50:

最多要返回的记录数(默认情况下是25),不过要记住,youtube每次访问可返回的最大值恰好也是50,如果想要获得更多内容,可以多请求几次,哈哈。

?alt=rss or ?alt=json:

alt参数用于设置返回内容的格式。

?vq=query:

用于筛选结果,会从 metadata (title, tags, description)中进行检索,比如“google+ maps”,就是搜索google map。

?orderby={updated, viewCount, rating, relevance}:

排序,示例中以updated为第一排序,relevanced作为最后一个排序。

使用jquery的AJAX进行访问也很简单:

$.ajax({  
        type: "GET",  
        url: "http://gdata.youtube.com/feeds/users/username/uploads?alt=json”,  
        cache: false,  
        dataType: 'jsonp',  
        success: function (data) {  
            showMyVideos(data);  
        },  
       error: function (XMLHttpRequest, textStatus, errorThrown, data) {  
            alert("Not able to fetch the data due to feed unavailability!!!");  
       }  
});

这里的showMyVideos(data)的方法就没必要写了,实际上我们只要随便找之前用到的播放器把内容显示出来就行了。而data结构还是比较复杂的,这里简单说一下。

data实际是个数组,针对其中的每一个entry(=entries[i]),我们常用的内容有:

entry.title.$t:视频的标题

entries[i].media$group.media$thumbnail[0].url:视频的缩略图

entries[i].media$group.media$content[0].url:视频的实际地址,这里content[0]实际是第一视频的地址,这个是flv格式的视频,如果不支持flash,可以取第二个。

entry.published.$t:这是发布时间。

entry.yt$statistics.viewCount:这个是被浏览次数。

似乎没有直接提供视频的id,但是我们可以通过字符串算出来:

entries[i].media$group.media$content[0].url.substr(playerUrl.indexOf(‘v/’) + 2, 11)

好了,基本的东西就这些了,其实也可以自己在firebug中输出一下,然后对比一下就知道怎么回事了,或者输出rss自己对比xml。还是很简单的。

logo

Shapez Theme

· Home Playground About

09


NOVEMBER

前两个月还在感叹WebOS的垮掉,现在突然发现HTML5比预期的时间提前来到了。难道真的是惠普的WebOS就是死在早了那么一两年么?那么真如现在所说的Oracle要低价收购的话,那真是在最合适的时间捡到一个大便宜啊。好了,废话不多说,今天推荐10款不错的HTML5的开发框架。

1、 Sencha Touch

Sencha Touch是专门为移动设备开发应用的Javascrt框架。通过Sencha Touch你可以创建非常像native app的web app,用户界面组件和数据管理全部基于HTML5和CSS3的web标准,全面兼容Android和Apple iOS。这个是大名鼎鼎的EXT框架的公司整合其另外两个框架发展而来的,自然首先推荐。

17183957_tLNm[1]17183959_FanS[1]

今天 Sencha Touch 发布 2.0 的首个开发者预览版。这在 Sencha Touch 1.0 发布的一年之后。新版本主要工作侧重于性能提升、易用以及内置打包方面。

相关连接:

下载 Touch
Touch 文档

下载 SDK 工具 (Mac-only)

下图是 ST 2.0 和 1.0 在启动时间的比较:

12072727_b3Di[1]

另外 2.0 版本在文档方面也做了很多改进,查看 2.0 文档

2、PhoneGap

PhoneGap是一款HTML5平台,通过它,开发商可以使用HTML、CSS及JavaScript来开发本地移动应用程序。因此,目前开发商可以只 编写一次应用程序,然后在6个主要的移动平台和应用程序商店(app store)里进行发布,这些移动平台和应用程序商店包括:iOS、Android、BlackBerry、webOS、bada以及Symbian。上个月该公司已经被Adobe公司协议收购,有了强大的后台支撑。(话说Adobe也通过收购在HTML5开发标准上占了一席之地啊)

12103344_JTVe[1]

下面是一些使用该框架的代码示例:

获取地理位置:

 //GAP will invoke this function once it has the location function gotLocation(lat,lon){ $('lat').innerHTML = "latitude: " + lat; $('lon').innerHTML = "longitude: " + lon; }

获取摄像头捕捉的照片

 function takePhoto(){ var photo = gap:takePhoto(); return photo; }

http://phonegap.com/

honeGap Mobile App XDK,可以让开发人员创建、模拟和测试PhoneGap项目。该工具是一个集成开发环境(IDE),提供了用于创建HTML5和PhoneGap应用的全套开发工具。AppMobi称,新的XDK为PhoneGap项目开发提供了一个直观的开发环境。

17220652_sPDY[1]

备注: phoneGap已出现就有很大反响,现在国内有个http://phonegap.cn爱好者网站,里面有中文的使用介绍。

3、ChocolateChip-UI

ChocolateChip-UI 是一个手机移动 Web 开发框架,使用 HTML5, WAML, CSS 和 JavaScript,基于 ChocolateChip JavaScript 库,包含新的 ChUI.JS 和 ChUI.css.可以在没有什么设计的情况下,开发出类似原生应用的界面来。

28070855_BOVI[1] 28070859_vAzZ[1]28070901_yBw0[1] 28070901_CJk1[1] 28070902_Y0Wp[1] 28070902_xU47[1] 28070903_rJFR[1] 28070903_uOoe[1] 28070904_AEEz[1] 28070904_vwci[1] 28070905_nH2O[1] 28070906_WMGK[1] 28070910_CEVh[1] 28070911_wE6f[1] 28070912_HWHN[1]

4、 Joshfire

Joshfire是一个支持多种设备的开发框架,仅采用HTML5和JavaScript等标准,可以帮助开发者迅速开发本地专用的网络应用,用于浏览器、Node.JS、桌面电脑、智能手机、智能电视以及联网设备。

多设备支持

28070205_emzX[1]

不管你针对哪种设备开发,Joshfire可以让你「一次开发,多处兼容」,自动兼容手机、平板电脑、电视等设备。

针对内容进行优化

28070205_acYZ[1]

如果你想发布新闻、图片、音乐、视频,Joshfire框架可以帮你轻松开发全功能内容应用。

用户互动

28070206_haFW[1]

忘掉那些为触控板、电视遥控器、键盘、鼠标、Kinect准备的专门设计吧,你只需要描述你的应用,其他的交给Joshfire。

客户端、服务器任意切换

下载地址:http://framework.joshfire.com/download

5、DHTMLX Touch

它是针对移动和触摸设备的JavaScript 框架。DHTMLX Touch基于HTML5,创建移动web应用。它不只是一组UI 小工具,而是一个完整的框架,可以针对移动和触摸设备创建跨平台的web应用。它兼容主流的web浏览器,用DHTMLX Touch创建的应用,可以在iPad、iPhone、Android智能手机等上面运行流畅。

21075436_uEmn[1]

6、jo

22133154_ywXC[1]

Jo这个框架可用于开发那支持HTML5的移动设备,如iOS,webOS, Android和Chrome OS等平台。

它拥有标准,类原生的UI元素比如用于屏幕登录的Web表单控件,还有弹出小部件可用于在用户点击界面时提供一些额外的信息。

可以查看其网站提供的示例页面,它例子展示了在多种移动设备平上的Jo应用情况。

http://joapp.com/downloads.html

7、mobl

mobl 其实是一个新的开源的编程语言,主要用于加速手机应用的开发,mobl 可方便构建手机 web 应用程序,包括 iOS、Android 和其他支持 HTML5 技术的手机。

15040939_S7CH[1]

主要特点:

http://www.mobl-lang.org/get/

8、SproutCore

SproutCore是一款HTML5的应用框架

在线演示

9、Perkins

Perkins 是一个 HTML5/CSS3 框架,主要为简化开发者和设计师的工具。使用一个基础的 HTML5 模板,包含多数所支持的标签以及一些 CSS 样式,便于创建诸如导航、圆角、渐进等效果。遵循MIT协议。

17070503_bmzn[1]

http://code.google.com/p/perkins-less/

10、AppMobi公司的HTML5框架

一家名叫AppMobi的小公司,正致力一项工作,使开发者能创建可深入移动设备硬件或操作系统功能的HTML5应用, 如重力感应、加速计、GPS、相机、声音与震动、文件系统等,InfoWorld报道。‘其iOS MobiUs浏览器为游戏实现了HTML5的DirectCanvas API,并为将浏览器缓存中的可执行文件和数据存储在本地(以使应用可以离线运行)实现了HTML5本地存储API。但是使MobiUs不同于仅仅只是另 外一个浏览器的是,AppMobi在它上面提供了一个库,它能允许开发者访问本地硬件,并实现Web应用的消息推送。’

04123557_lSXX[1]

网站

http://www.appmobi.com/

其开发中心链接

http://www.appmobi.com/?q=node/27

API 文档

http://appmobi.com/documentation/index.html

这里罗列了这么多的HTML5的应用框架,大多数都没有尝试使用,不过多数的文档写的还算详细。而HTML5大多是冲着移动应用开发来的。其实在Web上的实现与在原生应用里面的效果如果一致,岂不是最受开发者和公司欢迎么?而对最终用户,才不管你使用什么技术、什么平台,只要效果好就可以啊。

logo

Shapez Theme

· Home Playground About

24


OCTOBER

用iphone拍的照片,有照片的位置信息,该信息存在与jpeg格式的exit信息中,也并不是苹果公司的原创。其实就是图片文件存储空间中,有一个区域是专门存储附加信息的,比如光圈、快门、日期等等,其实信息量也蛮大的,地理位置信息就是其中一组以gps开头的信息。当然,我们一般使用的图片编辑工具会忽略掉该信息,也就是说iphone拍的照片在使用平常windows下的照片编辑器后可能会丢失该信息。

要读取exit信息,其实就是加载图片文件后,以二进制读取文件中相应的偏移量,从而可以获得照片exif信息。这里查到一个js访问exit信息的脚本,还有一个C#访问exif的类。

通过javascript访问照片exit信息:

http://www.nihilogic.dk/labs/exif/exif.js

如果访问该url有问题,可以参考代码如下:

/\*  
 \* Javascript EXIF Reader 0.1.4  
 \* Copyright (c) 2008 Jacob Seidelin, [email protected], http://blog.nihilogic.dk/  
 \* Licensed under the MPL License \[http://www.nihilogic.dk/licenses/mpl-license.txt\]  
 \*/  
  
  
var EXIF = {};  
  
(function() {  
  
var bDebug = false;  
  
EXIF.Tags = {  
  
    // version tags  
    0x9000 : "ExifVersion",            // EXIF version  
    0xA000 : "FlashpixVersion",        // Flashpix format version  
  
    // colorspace tags  
    0xA001 : "ColorSpace",            // Color space information tag  
  
    // image configuration  
    0xA002 : "PixelXDimension",        // Valid width of meaningful image  
    0xA003 : "PixelYDimension",        // Valid height of meaningful image  
    0x9101 : "ComponentsConfiguration",    // Information about channels  
    0x9102 : "CompressedBitsPerPixel",    // Compressed bits per pixel  
  
    // user information  
    0x927C : "MakerNote",            // Any desired information written by the manufacturer  
    0x9286 : "UserComment",            // Comments by user  
  
    // related file  
    0xA004 : "RelatedSoundFile",        // Name of related sound file  
  
    // date and time  
    0x9003 : "DateTimeOriginal",        // Date and time when the original image was generated  
    0x9004 : "DateTimeDigitized",        // Date and time when the image was stored digitally  
    0x9290 : "SubsecTime",            // Fractions of seconds for DateTime  
    0x9291 : "SubsecTimeOriginal",        // Fractions of seconds for DateTimeOriginal  
    0x9292 : "SubsecTimeDigitized",        // Fractions of seconds for DateTimeDigitized  
  
    // picture-taking conditions  
    0x829A : "ExposureTime",        // Exposure time (in seconds)  
    0x829D : "FNumber",            // F number  
    0x8822 : "ExposureProgram",        // Exposure program  
    0x8824 : "SpectralSensitivity",        // Spectral sensitivity  
    0x8827 : "ISOSpeedRatings",        // ISO speed rating  
    0x8828 : "OECF",            // Optoelectric conversion factor  
    0x9201 : "ShutterSpeedValue",        // Shutter speed  
    0x9202 : "ApertureValue",        // Lens aperture  
    0x9203 : "BrightnessValue",        // Value of brightness  
    0x9204 : "ExposureBias",        // Exposure bias  
    0x9205 : "MaxApertureValue",        // Smallest F number of lens  
    0x9206 : "SubjectDistance",        // Distance to subject in meters  
    0x9207 : "MeteringMode",         // Metering mode  
    0x9208 : "LightSource",            // Kind of light source  
    0x9209 : "Flash",            // Flash status  
    0x9214 : "SubjectArea",            // Location and area of main subject  
    0x920A : "FocalLength",            // Focal length of the lens in mm  
    0xA20B : "FlashEnergy",            // Strobe energy in BCPS  
    0xA20C : "SpatialFrequencyResponse",    //   
    0xA20E : "FocalPlaneXResolution",     // Number of pixels in width direction per FocalPlaneResolutionUnit  
    0xA20F : "FocalPlaneYResolution",     // Number of pixels in height direction per FocalPlaneResolutionUnit  
    0xA210 : "FocalPlaneResolutionUnit",     // Unit for measuring FocalPlaneXResolution and FocalPlaneYResolution  
    0xA214 : "SubjectLocation",        // Location of subject in image  
    0xA215 : "ExposureIndex",        // Exposure index selected on camera  
    0xA217 : "SensingMethod",         // Image sensor type  
    0xA300 : "FileSource",             // Image source (3 == DSC)  
    0xA301 : "SceneType",             // Scene type (1 == directly photographed)  
    0xA302 : "CFAPattern",            // Color filter array geometric pattern  
    0xA401 : "CustomRendered",        // Special processing  
    0xA402 : "ExposureMode",        // Exposure mode  
    0xA403 : "WhiteBalance",        // 1 = auto white balance, 2 = manual  
    0xA404 : "DigitalZoomRation",        // Digital zoom ratio  
    0xA405 : "FocalLengthIn35mmFilm",    // Equivalent foacl length assuming 35mm film camera (in mm)  
    0xA406 : "SceneCaptureType",        // Type of scene  
    0xA407 : "GainControl",            // Degree of overall image gain adjustment  
    0xA408 : "Contrast",            // Direction of contrast processing applied by camera  
    0xA409 : "Saturation",             // Direction of saturation processing applied by camera  
    0xA40A : "Sharpness",            // Direction of sharpness processing applied by camera  
    0xA40B : "DeviceSettingDescription",    //   
    0xA40C : "SubjectDistanceRange",    // Distance to subject  
  
    // other tags  
    0xA005 : "InteroperabilityIFDPointer",  
    0xA420 : "ImageUniqueID"        // Identifier assigned uniquely to each image  
};  
  
EXIF.TiffTags = {  
    0x0100 : "ImageWidth",  
    0x0101 : "ImageHeight",  
    0x8769 : "ExifIFDPointer",  
    0x8825 : "GPSInfoIFDPointer",  
    0xA005 : "InteroperabilityIFDPointer",  
    0x0102 : "BitsPerSample",  
    0x0103 : "Compression",  
    0x0106 : "PhotometricInterpretation",  
    0x0112 : "Orientation",  
    0x0115 : "SamplesPerPixel",  
    0x011C : "PlanarConfiguration",  
    0x0212 : "YCbCrSubSampling",  
    0x0213 : "YCbCrPositioning",  
    0x011A : "XResolution",  
    0x011B : "YResolution",  
    0x0128 : "ResolutionUnit",  
    0x0111 : "StripOffsets",  
    0x0116 : "RowsPerStrip",  
    0x0117 : "StripByteCounts",  
    0x0201 : "JPEGInterchangeFormat",  
    0x0202 : "JPEGInterchangeFormatLength",  
    0x012D : "TransferFunction",  
    0x013E : "WhitePoint",  
    0x013F : "PrimaryChromaticities",  
    0x0211 : "YCbCrCoefficients",  
    0x0214 : "ReferenceBlackWhite",  
    0x0132 : "DateTime",  
    0x010E : "ImageDescription",  
    0x010F : "Make",  
    0x0110 : "Model",  
    0x0131 : "Software",  
    0x013B : "Artist",  
    0x8298 : "Copyright"  
}  
  
EXIF.GPSTags = {  
    0x0000 : "GPSVersionID",  
    0x0001 : "GPSLatitudeRef",  
    0x0002 : "GPSLatitude",  
    0x0003 : "GPSLongitudeRef",  
    0x0004 : "GPSLongitude",  
    0x0005 : "GPSAltitudeRef",  
    0x0006 : "GPSAltitude",  
    0x0007 : "GPSTimeStamp",  
    0x0008 : "GPSSatellites",  
    0x0009 : "GPSStatus",  
    0x000A : "GPSMeasureMode",  
    0x000B : "GPSDOP",  
    0x000C : "GPSSpeedRef",  
    0x000D : "GPSSpeed",  
    0x000E : "GPSTrackRef",  
    0x000F : "GPSTrack",  
    0x0010 : "GPSImgDirectionRef",  
    0x0011 : "GPSImgDirection",  
    0x0012 : "GPSMapDatum",  
    0x0013 : "GPSDestLatitudeRef",  
    0x0014 : "GPSDestLatitude",  
    0x0015 : "GPSDestLongitudeRef",  
    0x0016 : "GPSDestLongitude",  
    0x0017 : "GPSDestBearingRef",  
    0x0018 : "GPSDestBearing",  
    0x0019 : "GPSDestDistanceRef",  
    0x001A : "GPSDestDistance",  
    0x001B : "GPSProcessingMethod",  
    0x001C : "GPSAreaInformation",  
    0x001D : "GPSDateStamp",  
    0x001E : "GPSDifferential"  
}  
  
EXIF.StringValues = {  
    ExposureProgram : {  
        0 : "Not defined",  
        1 : "Manual",  
        2 : "Normal program",  
        3 : "Aperture priority",  
        4 : "Shutter priority",  
        5 : "Creative program",  
        6 : "Action program",  
        7 : "Portrait mode",  
        8 : "Landscape mode"  
    },  
    MeteringMode : {  
        0 : "Unknown",  
        1 : "Average",  
        2 : "CenterWeightedAverage",  
        3 : "Spot",  
        4 : "MultiSpot",  
        5 : "Pattern",  
        6 : "Partial",  
        255 : "Other"  
    },  
    LightSource : {  
        0 : "Unknown",  
        1 : "Daylight",  
        2 : "Fluorescent",  
        3 : "Tungsten (incandescent light)",  
        4 : "Flash",  
        9 : "Fine weather",  
        10 : "Cloudy weather",  
        11 : "Shade",  
        12 : "Daylight fluorescent (D 5700 - 7100K)",  
        13 : "Day white fluorescent (N 4600 - 5400K)",  
        14 : "Cool white fluorescent (W 3900 - 4500K)",  
        15 : "White fluorescent (WW 3200 - 3700K)",  
        17 : "Standard light A",  
        18 : "Standard light B",  
        19 : "Standard light C",  
        20 : "D55",  
        21 : "D65",  
        22 : "D75",  
        23 : "D50",  
        24 : "ISO studio tungsten",  
        255 : "Other"  
    },  
    Flash : {  
        0x0000 : "Flash did not fire",  
        0x0001 : "Flash fired",  
        0x0005 : "Strobe return light not detected",  
        0x0007 : "Strobe return light detected",  
        0x0009 : "Flash fired, compulsory flash mode",  
        0x000D : "Flash fired, compulsory flash mode, return light not detected",  
        0x000F : "Flash fired, compulsory flash mode, return light detected",  
        0x0010 : "Flash did not fire, compulsory flash mode",  
        0x0018 : "Flash did not fire, auto mode",  
        0x0019 : "Flash fired, auto mode",  
        0x001D : "Flash fired, auto mode, return light not detected",  
        0x001F : "Flash fired, auto mode, return light detected",  
        0x0020 : "No flash function",  
        0x0041 : "Flash fired, red-eye reduction mode",  
        0x0045 : "Flash fired, red-eye reduction mode, return light not detected",  
        0x0047 : "Flash fired, red-eye reduction mode, return light detected",  
        0x0049 : "Flash fired, compulsory flash mode, red-eye reduction mode",  
        0x004D : "Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected",  
        0x004F : "Flash fired, compulsory flash mode, red-eye reduction mode, return light detected",  
        0x0059 : "Flash fired, auto mode, red-eye reduction mode",  
        0x005D : "Flash fired, auto mode, return light not detected, red-eye reduction mode",  
        0x005F : "Flash fired, auto mode, return light detected, red-eye reduction mode"  
    },  
    SensingMethod : {  
        1 : "Not defined",  
        2 : "One-chip color area sensor",  
        3 : "Two-chip color area sensor",  
        4 : "Three-chip color area sensor",  
        5 : "Color sequential area sensor",  
        7 : "Trilinear sensor",  
        8 : "Color sequential linear sensor"  
    },  
    SceneCaptureType : {  
        0 : "Standard",  
        1 : "Landscape",  
        2 : "Portrait",  
        3 : "Night scene"  
    },  
    SceneType : {  
        1 : "Directly photographed"  
    },  
    CustomRendered : {  
        0 : "Normal process",  
        1 : "Custom process"  
    },  
    WhiteBalance : {  
        0 : "Auto white balance",  
        1 : "Manual white balance"  
    },  
    GainControl : {  
        0 : "None",  
        1 : "Low gain up",  
        2 : "High gain up",  
        3 : "Low gain down",  
        4 : "High gain down"  
    },  
    Contrast : {  
        0 : "Normal",  
        1 : "Soft",  
        2 : "Hard"  
    },  
    Saturation : {  
        0 : "Normal",  
        1 : "Low saturation",  
        2 : "High saturation"  
    },  
    Sharpness : {  
        0 : "Normal",  
        1 : "Soft",  
        2 : "Hard"  
    },  
    SubjectDistanceRange : {  
        0 : "Unknown",  
        1 : "Macro",  
        2 : "Close view",  
        3 : "Distant view"  
    },  
    FileSource : {  
        3 : "DSC"  
    },  
  
    Components : {  
        0 : "",  
        1 : "Y",  
        2 : "Cb",  
        3 : "Cr",  
        4 : "R",  
        5 : "G",  
        6 : "B"  
    }  
}  
  
function addEvent(oElement, strEvent, fncHandler)   
{  
    if (oElement.addEventListener) {   
        oElement.addEventListener(strEvent, fncHandler, false);   
    } else if (oElement.attachEvent) {   
        oElement.attachEvent("on" + strEvent, fncHandler);   
    }  
}  
  
  
function imageHasData(oImg)   
{  
    return !!(oImg.exifdata);  
}  
  
function getImageData(oImg, fncCallback)   
{  
    BinaryAjax(  
        oImg.src,  
        function(oHTTP) {  
            var oEXIF = findEXIFinJPEG(oHTTP.binaryResponse);  
            oImg.exifdata = oEXIF || {};  
            if (fncCallback) fncCallback();  
        }  
    )  
}  
  
function findEXIFinJPEG(oFile) {  
    var aMarkers = \[\];  
  
    if (oFile.getByteAt(0) != 0xFF || oFile.getByteAt(1) != 0xD8) {  
        return false; // not a valid jpeg  
    }  
  
    var iOffset = 2;  
    var iLength = oFile.getLength();  
    while (iOffset < iLength) {  
        if (oFile.getByteAt(iOffset) != 0xFF) {  
            if (bDebug) console.log("Not a valid marker at offset " + iOffset + ", found: " + oFile.getByteAt(iOffset));  
            return false; // not a valid marker, something is wrong  
        }  
  
        var iMarker = oFile.getByteAt(iOffset+1);  
  
        // we could implement handling for other markers here,   
        // but we're only looking for 0xFFE1 for EXIF data  
  
        if (iMarker == 22400) {  
            if (bDebug) console.log("Found 0xFFE1 marker");  
            return readEXIFData(oFile, iOffset + 4, oFile.getShortAt(iOffset+2, true)-2);  
            iOffset += 2 + oFile.getShortAt(iOffset+2, true);  
  
        } else if (iMarker == 225) {  
            // 0xE1 = Application-specific 1 (for EXIF)  
            if (bDebug) console.log("Found 0xFFE1 marker");  
            return readEXIFData(oFile, iOffset + 4, oFile.getShortAt(iOffset+2, true)-2);  
  
        } else {  
            iOffset += 2 + oFile.getShortAt(iOffset+2, true);  
        }  
  
    }  
  
}  
  
  
function readTags(oFile, iTIFFStart, iDirStart, oStrings, bBigEnd)   
{  
    var iEntries = oFile.getShortAt(iDirStart, bBigEnd);  
    var oTags = {};  
    for (var i=0;i<iEntries;i++) {  
        var iEntryOffset = iDirStart + i\*12 + 2;  
        var strTag = oStrings\[oFile.getShortAt(iEntryOffset, bBigEnd)\];  
        if (!strTag && bDebug) console.log("Unknown tag: " + oFile.getShortAt(iEntryOffset, bBigEnd));  
        oTags\[strTag\] = readTagValue(oFile, iEntryOffset, iTIFFStart, iDirStart, bBigEnd);  
    }  
    return oTags;  
}  
  
  
function readTagValue(oFile, iEntryOffset, iTIFFStart, iDirStart, bBigEnd)  
{  
    var iType = oFile.getShortAt(iEntryOffset+2, bBigEnd);  
    var iNumValues = oFile.getLongAt(iEntryOffset+4, bBigEnd);  
    var iValueOffset = oFile.getLongAt(iEntryOffset+8, bBigEnd) + iTIFFStart;  
  
    switch (iType) {  
        case 1: // byte, 8-bit unsigned int  
        case 7: // undefined, 8-bit byte, value depending on field  
            if (iNumValues == 1) {  
                return oFile.getByteAt(iEntryOffset + 8, bBigEnd);  
            } else {  
                var iValOffset = iNumValues > 4 ? iValueOffset : (iEntryOffset + 8);  
                var aVals = \[\];  
                for (var n=0;n<iNumValues;n++) {  
                    aVals\[n\] = oFile.getByteAt(iValOffset + n);  
                }  
                return aVals;  
            }  
            break;  
  
        case 2: // ascii, 8-bit byte  
            var iStringOffset = iNumValues > 4 ? iValueOffset : (iEntryOffset + 8);  
            return oFile.getStringAt(iStringOffset, iNumValues-1);  
            break;  
  
        case 3: // short, 16 bit int  
            if (iNumValues == 1) {  
                return oFile.getShortAt(iEntryOffset + 8, bBigEnd);  
            } else {  
                var iValOffset = iNumValues > 2 ? iValueOffset : (iEntryOffset + 8);  
                var aVals = \[\];  
                for (var n=0;n<iNumValues;n++) {  
                    aVals\[n\] = oFile.getShortAt(iValOffset + 2\*n, bBigEnd);  
                }  
                return aVals;  
            }  
            break;  
  
        case 4: // long, 32 bit int  
            if (iNumValues == 1) {  
                return oFile.getLongAt(iEntryOffset + 8, bBigEnd);  
            } else {  
                var aVals = \[\];  
                for (var n=0;n<iNumValues;n++) {  
                    aVals\[n\] = oFile.getLongAt(iValueOffset + 4\*n, bBigEnd);  
                }  
                return aVals;  
            }  
            break;  
        case 5:    // rational = two long values, first is numerator, second is denominator  
            if (iNumValues == 1) {  
                return oFile.getLongAt(iValueOffset, bBigEnd) / oFile.getLongAt(iValueOffset+4, bBigEnd);  
            } else {  
                var aVals = \[\];  
                for (var n=0;n<iNumValues;n++) {  
                    aVals\[n\] = oFile.getLongAt(iValueOffset + 8\*n, bBigEnd) / oFile.getLongAt(iValueOffset+4 + 8\*n, bBigEnd);  
                }  
                return aVals;  
            }  
            break;  
        case 9: // slong, 32 bit signed int  
            if (iNumValues == 1) {  
                return oFile.getSLongAt(iEntryOffset + 8, bBigEnd);  
            } else {  
                var aVals = \[\];  
                for (var n=0;n<iNumValues;n++) {  
                    aVals\[n\] = oFile.getSLongAt(iValueOffset + 4\*n, bBigEnd);  
                }  
                return aVals;  
            }  
            break;  
        case 10: // signed rational, two slongs, first is numerator, second is denominator  
            if (iNumValues == 1) {  
                return oFile.getSLongAt(iValueOffset, bBigEnd) / oFile.getSLongAt(iValueOffset+4, bBigEnd);  
            } else {  
                var aVals = \[\];  
                for (var n=0;n<iNumValues;n++) {  
                    aVals\[n\] = oFile.getSLongAt(iValueOffset + 8\*n, bBigEnd) / oFile.getSLongAt(iValueOffset+4 + 8\*n, bBigEnd);  
                }  
                return aVals;  
            }  
            break;  
    }  
}  
  
  
function readEXIFData(oFile, iStart, iLength)   
{  
    if (oFile.getStringAt(iStart, 4) != "Exif") {  
        if (bDebug) console.log("Not valid EXIF data! " + oFile.getStringAt(iStart, 4));  
        return false;  
    }  
  
    var bBigEnd;  
  
    var iTIFFOffset = iStart + 6;  
  
    // test for TIFF validity and endianness  
    if (oFile.getShortAt(iTIFFOffset) == 0x4949) {  
        bBigEnd = false;  
    } else if (oFile.getShortAt(iTIFFOffset) == 0x4D4D) {  
        bBigEnd = true;  
    } else {  
        if (bDebug) console.log("Not valid TIFF data! (no 0x4949 or 0x4D4D)");  
        return false;  
    }  
  
    if (oFile.getShortAt(iTIFFOffset+2, bBigEnd) != 0x002A) {  
        if (bDebug) console.log("Not valid TIFF data! (no 0x002A)");  
        return false;  
    }  
  
    if (oFile.getLongAt(iTIFFOffset+4, bBigEnd) != 0x00000008) {  
        if (bDebug) console.log("Not valid TIFF data! (First offset not 8)", oFile.getShortAt(iTIFFOffset+4, bBigEnd));  
        return false;  
    }  
  
    var oTags = readTags(oFile, iTIFFOffset, iTIFFOffset+8, EXIF.TiffTags, bBigEnd);  
  
    if (oTags.ExifIFDPointer) {  
        var oEXIFTags = readTags(oFile, iTIFFOffset, iTIFFOffset + oTags.ExifIFDPointer, EXIF.Tags, bBigEnd);  
        for (var strTag in oEXIFTags) {  
            switch (strTag) {  
                case "LightSource" :  
                case "Flash" :  
                case "MeteringMode" :  
                case "ExposureProgram" :  
                case "SensingMethod" :  
                case "SceneCaptureType" :  
                case "SceneType" :  
                case "CustomRendered" :  
                case "WhiteBalance" :   
                case "GainControl" :   
                case "Contrast" :  
                case "Saturation" :  
                case "Sharpness" :   
                case "SubjectDistanceRange" :  
                case "FileSource" :  
                    oEXIFTags\[strTag\] = EXIF.StringValues\[strTag\]\[oEXIFTags\[strTag\]\];  
                    break;  
      
                case "ExifVersion" :  
                case "FlashpixVersion" :  
                    oEXIFTags\[strTag\] = String.fromCharCode(oEXIFTags\[strTag\]\[0\], oEXIFTags\[strTag\]\[1\], oEXIFTags\[strTag\]\[2\], oEXIFTags\[strTag\]\[3\]);  
                    break;  
      
                case "ComponentsConfiguration" :   
                    oEXIFTags\[strTag\] =   
                        EXIF.StringValues.Components\[oEXIFTags\[strTag\]\[0\]\]  
                        + EXIF.StringValues.Components\[oEXIFTags\[strTag\]\[1\]\]  
                        + EXIF.StringValues.Components\[oEXIFTags\[strTag\]\[2\]\]  
                        + EXIF.StringValues.Components\[oEXIFTags\[strTag\]\[3\]\];  
                    break;  
            }  
            oTags\[strTag\] = oEXIFTags\[strTag\];  
        }  
    }  
  
    if (oTags.GPSInfoIFDPointer) {  
        var oGPSTags = readTags(oFile, iTIFFOffset, iTIFFOffset + oTags.GPSInfoIFDPointer, EXIF.GPSTags, bBigEnd);  
        for (var strTag in oGPSTags) {  
            switch (strTag) {  
                case "GPSVersionID" :   
                    oGPSTags\[strTag\] = oGPSTags\[strTag\]\[0\]   
                        + "." + oGPSTags\[strTag\]\[1\]   
                        + "." + oGPSTags\[strTag\]\[2\]   
                        + "." + oGPSTags\[strTag\]\[3\];  
                    break;  
            }  
            oTags\[strTag\] = oGPSTags\[strTag\];  
        }  
    }  
  
    return oTags;  
}  
  
  
EXIF.getData = function(oImg, fncCallback)   
{  
    if (!oImg.complete) return false;  
    if (!imageHasData(oImg)) {  
        getImageData(oImg, fncCallback);  
    } else {  
        if (fncCallback) fncCallback();  
    }  
    return true;  
}  
  
EXIF.getTag = function(oImg, strTag)   
{  
    if (!imageHasData(oImg)) return;  
    return oImg.exifdata\[strTag\];  
}  
  
EXIF.getAllTags = function(oImg)   
{  
    if (!imageHasData(oImg)) return {};  
    var oData = oImg.exifdata;  
    var oAllTags = {};  
    for (var a in oData) {  
        if (oData.hasOwnProperty(a)) {  
            oAllTags\[a\] = oData\[a\];  
        }  
    }  
    return oAllTags;  
}  
  
  
EXIF.pretty = function(oImg)   
{  
    if (!imageHasData(oImg)) return "";  
    var oData = oImg.exifdata;  
    var strPretty = "";  
    for (var a in oData) {  
        if (oData.hasOwnProperty(a)) {  
            if (typeof oData\[a\] == "object") {  
                strPretty += a + " : \[" + oData\[a\].length + " values\]rn";  
            } else {  
                strPretty += a + " : " + oData\[a\] + "rn";  
            }  
        }  
    }  
    return strPretty;  
}  
  
EXIF.readFromBinaryFile = function(oFile) {  
    return findEXIFinJPEG(oFile);  
}  
  
function loadAllImages()   
{  
    var aImages = document.getElementsByTagName("img");  
    for (var i=0;i<aImages.length;i++) {  
        if (aImages\[i\].getAttribute("exif") == "true") {  
            if (!aImages\[i\].complete) {  
                addEvent(aImages\[i\], "load",   
                    function() {  
                        EXIF.getData(this);  
                    }  
                );   
            } else {  
                EXIF.getData(aImages\[i\]);  
            }  
        }  
    }  
}  
  
addEvent(window, "load", loadAllImages);   
  
})();    

该网站同时提供jquery版的exif代码,具体链接为:

http://www.nihilogic.dk/labs/exifjquery/jquery.exif.js

经实际测试发现,该程序仅仅在火狐浏览器和chrome浏览器比较正常,当前的其他浏览器都或多或少有些问题,大多信息读取不全。简单示例代码可在

http://blogs8.sinaapp.com/demo/exif/

中进行查看。可以直接看源代码,写的比较简单。

下面是一个C#访问EXIF的类,网上转来的(自路径http://www.cnblogs.com/fengbp/articles/1403353.html),原作者不清楚

using System;  
using System.Collections.Generic;  
using System.Text;  
  
namespace ExifWorks  
{  
//   
// Utility class for working with EXIF data in images. Provides abstraction  
// for most common data and generic utilities for work with all other.   
//   
//   
// Copyright (c) Michal A. Valášek - Altair Communications, 2003-2005  
// Copmany: http://software.altaircom.net, E-mail: [email protected]  
// Private: http://www.rider.cz, E-mail: [email protected]  
// This is free software licensed under GNU Lesser General Public License  
//   
//   
// \[altair\] 10.09.2003 Created  
// \[altair\] 12.06.2004 Added capability to write EXIF data  
// \[altair\] 11.07.2004 Added option to change encoding  
// \[altair\] 04.09.2005 Changed source of Width and Height properties from EXIF to image  
// \[altair\] 05.09.2005 Code clean-up and minor changes  
// \[[email protected]\] 02-11-2006 C# translation  
//   
public class ExifManager : IDisposable  
{  
  
private System.Drawing.Bitmap \_Image;  
private System.Text.Encoding \_Encoding = System.Text.Encoding.UTF8;  
  
#region Type declarations  
  
//   
// Contains possible values of EXIF tag names (ID)  
//   
// See GdiPlusImaging.h  
//   
// \[altair\] 10.09.2003 Created  
//   
  
public enum TagNames : int  
{  
ExifIFD = 0x8769,  
GpsIFD = 0x8825,  
NewSubfileType = 0xFE,  
SubfileType = 0xFF,  
ImageWidth = 0x100,  
ImageHeight = 0x101,  
BitsPerSample = 0x102,  
Compression = 0x103,  
PhotometricInterp = 0x106,  
ThreshHolding = 0x107,  
CellWidth = 0x108,  
CellHeight = 0x109,  
FillOrder = 0x10A,  
DocumentName = 0x10D,  
ImageDescription = 0x10E,  
EquipMake = 0x10F,  
EquipModel = 0x110,  
StripOffsets = 0x111,  
Orientation = 0x112,  
SamplesPerPixel = 0x115,  
RowsPerStrip = 0x116,  
StripBytesCount = 0x117,  
MinSampleValue = 0x118,  
MaxSampleValue = 0x119,  
XResolution = 0x11A,  
YResolution = 0x11B,  
PlanarConfig = 0x11C,  
PageName = 0x11D,  
XPosition = 0x11E,  
YPosition = 0x11F,  
FreeOffset = 0x120,  
FreeByteCounts = 0x121,  
GrayResponseUnit = 0x122,  
GrayResponseCurve = 0x123,  
T4Option = 0x124,  
T6Option = 0x125,  
ResolutionUnit = 0x128,  
PageNumber = 0x129,  
TransferFuncition = 0x12D,  
SoftwareUsed = 0x131,  
DateTime = 0x132,  
Artist = 0x13B,  
HostComputer = 0x13C,  
Predictor = 0x13D,  
WhitePoint = 0x13E,  
PrimaryChromaticities = 0x13F,  
ColorMap = 0x140,  
HalftoneHints = 0x141,  
TileWidth = 0x142,  
TileLength = 0x143,  
TileOffset = 0x144,  
TileByteCounts = 0x145,  
InkSet = 0x14C,  
InkNames = 0x14D,  
NumberOfInks = 0x14E,  
DotRange = 0x150,  
TargetPrinter = 0x151,  
ExtraSamples = 0x152,  
SampleFormat = 0x153,  
SMinSampleValue = 0x154,  
SMaxSampleValue = 0x155,  
TransferRange = 0x156,  
JPEGProc = 0x200,  
JPEGInterFormat = 0x201,  
JPEGInterLength = 0x202,  
JPEGRestartInterval = 0x203,  
JPEGLosslessPredictors = 0x205,  
JPEGPointTransforms = 0x206,  
JPEGQTables = 0x207,  
JPEGDCTables = 0x208,  
JPEGACTables = 0x209,  
YCbCrCoefficients = 0x211,  
YCbCrSubsampling = 0x212,  
YCbCrPositioning = 0x213,  
REFBlackWhite = 0x214,  
ICCProfile = 0x8773,  
Gamma = 0x301,  
ICCProfileDescriptor = 0x302,  
SRGBRenderingIntent = 0x303,  
ImageTitle = 0x320,  
Copyright = 0x8298,  
ResolutionXUnit = 0x5001,  
ResolutionYUnit = 0x5002,  
ResolutionXLengthUnit = 0x5003,  
ResolutionYLengthUnit = 0x5004,  
PrintFlags = 0x5005,  
PrintFlagsVersion = 0x5006,  
PrintFlagsCrop = 0x5007,  
PrintFlagsBleedWidth = 0x5008,  
PrintFlagsBleedWidthScale = 0x5009,  
HalftoneLPI = 0x500A,  
HalftoneLPIUnit = 0x500B,  
HalftoneDegree = 0x500C,  
HalftoneShape = 0x500D,  
HalftoneMisc = 0x500E,  
HalftoneScreen = 0x500F,  
JPEGQuality = 0x5010,  
GridSize = 0x5011,  
ThumbnailFormat = 0x5012,  
ThumbnailWidth = 0x5013,  
ThumbnailHeight = 0x5014,  
ThumbnailColorDepth = 0x5015,  
ThumbnailPlanes = 0x5016,  
ThumbnailRawBytes = 0x5017,  
ThumbnailSize = 0x5018,  
ThumbnailCompressedSize = 0x5019,  
ColorTransferFunction = 0x501A,  
ThumbnailData = 0x501B,  
ThumbnailImageWidth = 0x5020,  
ThumbnailImageHeight = 0x502,  
ThumbnailBitsPerSample = 0x5022,  
ThumbnailCompression = 0x5023,  
ThumbnailPhotometricInterp = 0x5024,  
ThumbnailImageDescription = 0x5025,  
ThumbnailEquipMake = 0x5026,  
ThumbnailEquipModel = 0x5027,  
ThumbnailStripOffsets = 0x5028,  
ThumbnailOrientation = 0x5029,  
ThumbnailSamplesPerPixel = 0x502A,  
ThumbnailRowsPerStrip = 0x502B,  
ThumbnailStripBytesCount = 0x502C,  
ThumbnailResolutionX = 0x502D,  
ThumbnailResolutionY = 0x502E,  
ThumbnailPlanarConfig = 0x502F,  
ThumbnailResolutionUnit = 0x5030,  
ThumbnailTransferFunction = 0x5031,  
ThumbnailSoftwareUsed = 0x5032,  
ThumbnailDateTime = 0x5033,  
ThumbnailArtist = 0x5034,  
ThumbnailWhitePoint = 0x5035,  
ThumbnailPrimaryChromaticities = 0x5036,  
ThumbnailYCbCrCoefficients = 0x5037,  
ThumbnailYCbCrSubsampling = 0x5038,  
ThumbnailYCbCrPositioning = 0x5039,  
ThumbnailRefBlackWhite = 0x503A,  
ThumbnailCopyRight = 0x503B,  
LuminanceTable = 0x5090,  
ChrominanceTable = 0x5091,  
FrameDelay = 0x5100,  
LoopCount = 0x5101,  
PixelUnit = 0x5110,  
PixelPerUnitX = 0x5111,  
PixelPerUnitY = 0x5112,  
PaletteHistogram = 0x5113,  
ExifExposureTime = 0x829A,  
ExifFNumber = 0x829D,  
ExifExposureProg = 0x8822,  
ExifSpectralSense = 0x8824,  
ExifISOSpeed = 0x8827,  
ExifOECF = 0x8828,  
ExifVer = 0x9000,  
ExifDTOrig = 0x9003,  
ExifDTDigitized = 0x9004,  
ExifCompConfig = 0x9101,  
ExifCompBPP = 0x9102,  
ExifShutterSpeed = 0x9201,  
ExifAperture = 0x9202,  
ExifBrightness = 0x9203,  
ExifExposureBias = 0x9204,  
ExifMaxAperture = 0x9205,  
ExifSubjectDist = 0x9206,  
ExifMeteringMode = 0x9207,  
ExifLightSource = 0x9208,  
ExifFlash = 0x9209,  
ExifFocalLength = 0x920A,  
ExifMakerNote = 0x927C,  
ExifUserComment = 0x9286,  
ExifDTSubsec = 0x9290,  
ExifDTOrigSS = 0x9291,  
ExifDTDigSS = 0x9292,  
ExifFPXVer = 0xA000,  
ExifColorSpace = 0xA001,  
ExifPixXDim = 0xA002,  
ExifPixYDim = 0xA003,  
ExifRelatedWav = 0xA004,  
ExifInterop = 0xA005,  
ExifFlashEnergy = 0xA20B,  
ExifSpatialFR = 0xA20C,  
ExifFocalXRes = 0xA20E,  
ExifFocalYRes = 0xA20F,  
ExifFocalResUnit = 0xA210,  
ExifSubjectLoc = 0xA214,  
ExifExposureIndex = 0xA215,  
ExifSensingMethod = 0xA217,  
ExifFileSource = 0xA300,  
ExifSceneType = 0xA301,  
ExifCfaPattern = 0xA302,  
GpsVer = 0x0,  
GpsLatitudeRef = 0x1,  
GpsLatitude = 0x2,  
GpsLongitudeRef = 0x3,  
GpsLongitude = 0x4,  
GpsAltitudeRef = 0x5,  
GpsAltitude = 0x6,  
GpsGpsTime = 0x7,  
GpsGpsSatellites = 0x8,  
GpsGpsStatus = 0x9,  
GpsGpsMeasureMode = 0xA,  
GpsGpsDop = 0xB,  
GpsSpeedRef = 0xC,  
GpsSpeed = 0xD,  
GpsTrackRef = 0xE,  
GpsTrack = 0xF,  
GpsImgDirRef = 0x10,  
GpsImgDir = 0x11,  
GpsMapDatum = 0x12,  
GpsDestLatRef = 0x13,  
GpsDestLat = 0x14,  
GpsDestLongRef = 0x15,  
GpsDestLong = 0x16,  
GpsDestBearRef = 0x17,  
GpsDestBear = 0x18,  
GpsDestDistRef = 0x19,  
GpsDestDist = 0x1A  
}  
  
  
//   
// Real position of 0th row and column of picture  
//   
//   
//   
// \[altair\] 10.09.2003 Created  
//   
  
public enum Orientations  
{  
TopLeft = 1,  
TopRight = 2,  
BottomRight = 3,  
BottomLeft = 4,  
LeftTop = 5,  
RightTop = 6,  
RightBottom = 7,  
LftBottom = 8  
}  
  
  
//   
// Exposure programs  
//   
//   
//   
// \[altair\] 10.09.2003 Created  
//   
  
public enum ExposurePrograms  
{  
Manual = 1,  
Normal = 2,  
AperturePriority = 3,  
ShutterPriority = 4,  
Creative = 5,  
Action = 6,  
Portrait = 7,  
Landscape = 8,  
}  
  
  
//   
// Exposure metering modes  
//   
//   
//   
// \[altair\] 10.09.2003 Created  
//   
  
public enum ExposureMeteringModes  
{  
Unknown = 0,  
Average = 1,  
CenterWeightedAverage = 2,  
Spot = 3,  
MultiSpot = 4,  
MultiSegment = 5,  
Partial = 6,  
Other = 255  
}  
  
  
//   
// Flash activity modes  
//   
//   
//   
// \[altair\] 10.09.2003 Created  
//   
  
public enum FlashModes  
{  
NotFired = 0,  
Fired = 1,  
FiredButNoStrobeReturned = 5,  
FiredAndStrobeReturned = 7,  
}  
  
  
//   
// Possible light sources (white balance)  
//   
//   
//   
// \[altair\] 10.09.2003 Created  
//   
  
public enum LightSources  
{  
Unknown = 0,  
Daylight = 1,  
Fluorescent = 2,  
Tungsten = 3,  
Flash = 10,  
StandardLightA = 17,  
StandardLightB = 18,  
StandardLightC = 19,  
D55 = 20,  
D65 = 21,  
D75 = 22,  
Other = 255  
}  
  
  
//   
// EXIF data types  
//   
//   
//   
// \[altair\] 12.6.2004 Created  
//   
public enum ExifDataTypes : short  
{  
UnsignedByte = 1,  
AsciiString = 2,  
UnsignedShort = 3,  
UnsignedLong = 4,  
UnsignedRational = 5,  
SignedByte = 6,  
Undefined = 7,  
SignedShort = 8,  
SignedLong = 9,  
SignedRational = 10,  
SingleFloat = 11,  
DoubleFloat = 12  
}  
  
  
//   
// Represents rational which is type of some Exif properties  
//   
//   
//   
// \[altair\] 10.09.2003 Created  
//   
public struct Rational  
{  
public Int32 Numerator;  
public Int32 Denominator;  
  
  
//   
// Converts rational to string representation  
//   
// Optional, default "/". String to be used as delimiter of components.  
// String representation of the rational.  
//   
//   
// \[altair\] 10.09.2003 Created  
//   
  
public override string ToString()  
{  
return ToString("/");  
}  
  
public string ToString(string Delimiter)  
{  
return Numerator + "/" + Denominator;  
}  
  
//   
// Converts rational to double precision real number  
//   
// The rational as double precision real number.  
//   
//   
// \[altair\] 10.09.2003 Created  
//   
  
public double ToDouble()  
{  
return (double)Numerator / Denominator;  
}  
}  
  
#endregion  
  
//   
// Initializes new instance of this class.  
//   
// Bitmap to read exif information from  
//   
//   
// \[altair\] 10.09.2003 Created  
//   
public ExifManager(System.Drawing.Bitmap Bitmap)  
{  
if (Bitmap == null)  
throw new ArgumentNullException("Bitmap");  
this.\_Image = Bitmap;  
}  
  
//   
// Initializes new instance of this class.  
//   
// Name of file to be loaded  
//   
//   
// \[altair\] 13.06.2004 Created  
//   
public ExifManager(string FileName)  
{  
this.\_Image = (System.Drawing.Bitmap)System.Drawing.Bitmap.FromFile(FileName);  
}  
  
//   
// Get or set encoding used for string metadata  
//   
// Encoding used for string metadata  
// Default encoding is UTF-8  
//   
// \[altair\] 11.07.2004 Created  
// \[altair\] 05.09.2005 Changed from shared to instance member  
//   
public System.Text.Encoding Encoding  
{  
get  
{  
return this.\_Encoding;  
}  
set  
{  
if (value == null)  
throw new ArgumentNullException();  
this.\_Encoding = value;  
}  
}  
  
//   
// Returns copy of bitmap this instance is working on  
//   
//   
//   
//   
// \[altair\] 13.06.2004 Created  
//   
public System.Drawing.Bitmap GetBitmap()  
{  
return (System.Drawing.Bitmap)this.\_Image.Clone();  
}  
  
//   
// Returns all available data in formatted string form  
//   
//   
//   
//   
// \[altair\] 10.09.2003 Created  
//   
public override string ToString()  
{  
System.Text.StringBuilder SB = new StringBuilder();  
  
SB.Append("Image:");  
SB.Append("ntDimensions: " + this.Width + " x " + this.Height + " px");  
SB.Append("ntResolution: " + this.ResolutionX + " x " + this.ResolutionY + " dpi");  
SB.Append("ntOrientation: " + Enum.GetName(typeof(Orientations), this.Orientation));  
SB.Append("ntTitle: " + this.Title);  
SB.Append("ntDescription: " + this.Description);  
SB.Append("ntCopyright: " + this.Copyright);  
SB.Append("nEquipment:");  
SB.Append("ntMaker: " + this.EquipmentMaker);  
SB.Append("ntModel: " + this.EquipmentModel);  
SB.Append("ntSoftware: " + this.Software);  
SB.Append("nDate and time:");  
SB.Append("ntGeneral: " + this.DateTimeLastModified.ToString());  
SB.Append("ntOriginal: " + this.DateTimeOriginal.ToString());  
SB.Append("ntDigitized: " + this.DateTimeDigitized.ToString());  
SB.Append("nShooting conditions:");  
SB.Append("ntExposure time: " + this.ExposureTime.ToString("N4") + " s");  
SB.Append("ntExposure program: " + Enum.GetName(typeof(ExposurePrograms), this.ExposureProgram));  
SB.Append("ntExposure mode: " + Enum.GetName(typeof(ExposureMeteringModes), this.ExposureMeteringMode));  
SB.Append("ntAperture: F" + this.Aperture.ToString("N2"));  
SB.Append("ntISO sensitivity: " + this.ISO);  
SB.Append("ntSubject distance: " + this.SubjectDistance.ToString("N2") + " m");  
SB.Append("ntFocal length: " + this.FocalLength);  
SB.Append("ntFlash: " + Enum.GetName(typeof(FlashModes), this.FlashMode));  
SB.Append("ntLight source (WB): " + Enum.GetName(typeof(LightSources), this.LightSource));  
//SB.Replace("n", vbCrLf);  
//SB.Replace("t", vbTab);  
return SB.ToString();  
}  
  
#region Nicely formatted well-known properties  
  
//   
// Brand of equipment (EXIF EquipMake)  
//   
//   
//   
//   
// \[altair\] 10.09.2003 Created  
//   
public string EquipmentMaker  
{  
get  
{  
return this.GetPropertyString((int)TagNames.EquipMake);  
}  
}  
  
//   
// Model of equipment (EXIF EquipModel)  
//   
//   
//   
//   
// \[altair\] 10.09.2003 Created  
//   
public string EquipmentModel  
{  
get  
{  
return this.GetPropertyString((int)TagNames.EquipModel);  
}  
}  
  
//   
// Software used for processing (EXIF Software)  
//   
//   
//   
//   
// \[altair\] 10.09.2003 Created  
//   
public string Software  
{  
get  
{  
return this.GetPropertyString((int)TagNames.SoftwareUsed);  
}  
}  
  
//   
// Orientation of image (position of row 0, column 0) (EXIF Orientation)  
//   
//   
//   
//   
// \[altair\] 10.09.2003 Created  
//   
public Orientations Orientation  
{  
get  
{  
Int32 X = this.GetPropertyInt16((int)TagNames.Orientation);  
  
if (!Enum.IsDefined(typeof(Orientations), X))  
return Orientations.TopLeft;  
else  
return (Orientations)Enum.Parse(typeof(Orientations), Enum.GetName(typeof(Orientations), X));  
}  
}  
  
//   
// Time when image was last modified (EXIF DateTime).  
//   
//   
//   
//   
// \[altair\] 10.09.2003 Created  
//   
public DateTime DateTimeLastModified  
{  
get  
{  
try  
{  
return DateTime.ParseExact(this.GetPropertyString((int)TagNames.DateTime), @"yyyy:MM:dd HH:mm:ss", null);  
}  
catch  
{  
return DateTime.MinValue;  
}  
}  
set  
{  
try  
{  
this.SetPropertyString((int)TagNames.DateTime, value.ToString(@"yyyy:MM:dd HH:mm:ss"));  
}  
catch  
{ }  
}  
}  
  
//   
// Time when image was taken (EXIF DateTimeOriginal).  
//   
//   
//   
//   
// \[altair\] 10.09.2003 Created  
//   
public DateTime DateTimeOriginal  
{  
get  
{  
try  
{  
return DateTime.ParseExact(this.GetPropertyString((int)TagNames.ExifDTOrig), @"yyyy:MM:dd HH:mm:ss", null);  
}  
catch  
{  
return DateTime.MinValue;  
}  
}  
set  
{  
try  
{  
this.SetPropertyString((int)TagNames.ExifDTOrig, value.ToString(@"yyyy:MM:dd HH:mm:ss"));  
}  
catch  
{ }  
}  
}  
  
//   
// Time when image was digitized (EXIF DateTimeDigitized).  
//   
//   
//   
//   
// \[altair\] 10.09.2003 Created  
//   
public DateTime DateTimeDigitized  
{  
get  
{  
try  
{  
return DateTime.ParseExact(this.GetPropertyString((int)TagNames.ExifDTDigitized), @"yyyy:MM:dd HH:mm:ss", null);  
}  
catch  
{  
return DateTime.MinValue;  
}  
}  
set  
{  
try  
{  
this.SetPropertyString((int)TagNames.ExifDTDigitized, value.ToString(@"yyyy:MM:dd HH:mm:ss"));  
}  
catch  
{ }  
}  
}  
  
//   
// Image width  
//   
//   
//   
//   
// \[altair\] 10.09.2003 Created  
// \[altair\] 04.09.2005 Changed output to Int32, load from image instead of EXIF  
//   
public Int32 Width  
{  
get { return this.\_Image.Width; }  
}  
  
//   
// Image height  
//   
//   
//   
//   
// \[altair\] 10.09.2003 Created  
// \[altair\] 04.09.2005 Changed output to Int32, load from image instead of EXIF  
//   
public Int32 Height  
{  
get { return this.\_Image.Height; }  
}  
  
//   
// X resolution in dpi (EXIF XResolution/ResolutionUnit)  
//   
//   
//   
//   
// \[altair\] 10.09.2003 Created  
//   
public double ResolutionX  
{  
get  
{  
double R = this.GetPropertyRational((int)TagNames.XResolution).ToDouble();  
  
if (this.GetPropertyInt16((int)TagNames.ResolutionUnit) == 3)  
{  
// -- resolution is in points/cm  
return R \* 2.54;  
}  
else  
{  
// -- resolution is in points/inch  
return R;  
}  
}  
}  
  
//   
// Y resolution in dpi (EXIF YResolution/ResolutionUnit)  
//   
//   
//   
//   
// \[altair\] 10.09.2003 Created  
//   
public double ResolutionY  
{  
get  
{  
double R = this.GetPropertyRational((int)TagNames.YResolution).ToDouble();  
  
if (this.GetPropertyInt16((int)TagNames.ResolutionUnit) == 3)  
{  
// -- resolution is in points/cm  
return R \* 2.54;  
}  
else  
{  
// -- resolution is in points/inch  
return R;  
}  
}  
}  
  
//   
// Image title (EXIF ImageTitle)  
//   
//   
//   
//   
// \[altair\] 10.09.2003 Created  
//   
public string Title  
{  
get  
{  
return this.GetPropertyString((int)TagNames.ImageTitle);  
}  
set  
{  
try  
{  
this.SetPropertyString((int)TagNames.ImageTitle, value);  
}  
catch { }  
}  
}  
  
//   
// User comment (EXIF UserComment)  
//   
//   
//   
//   
// \[altair\] 13.06.2004 Created  
//   
public string UserComment  
{  
get  
{  
return this.GetPropertyString((int)TagNames.ExifUserComment);  
}  
set  
{  
try  
{  
this.SetPropertyString((int)TagNames.ExifUserComment, value);  
}  
catch { }  
}  
}  
  
//   
// Artist name (EXIF Artist)  
//   
//   
//   
//   
// \[altair\] 13.06.2004 Created  
//   
public string Artist  
{  
get  
{  
return this.GetPropertyString((int)TagNames.Artist);  
}  
set  
{  
try  
{  
this.SetPropertyString((int)TagNames.Artist, value);  
}  
catch { }  
}  
}  
  
//   
// Image description (EXIF ImageDescription)  
//   
//   
//   
//   
// \[altair\] 10.09.2003 Created  
//   
public string Description  
{  
get  
{  
return this.GetPropertyString((int)TagNames.ImageDescription);  
}  
set  
{  
try  
{  
this.SetPropertyString((int)TagNames.ImageDescription, value);  
}  
catch { }  
}  
}  
  
//   
// Image copyright (EXIF Copyright)  
//   
//   
//   
//   
// \[altair\] 10.09.2003 Created  
//   
public string Copyright  
{  
get  
{  
return this.GetPropertyString((int)TagNames.Copyright);  
}  
set  
{  
try  
{  
this.SetPropertyString((int)TagNames.Copyright, value);  
}  
catch { }  
}  
}  
  
  
//   
// Exposure time in seconds (EXIF ExifExposureTime/ExifShutterSpeed)  
//   
//   
//   
//   
// \[altair\] 10.09.2003 Created  
//   
public double ExposureTimeAbs  
{  
get  
{  
if (this.IsPropertyDefined((int)TagNames.ExifExposureTime))  
// -- Exposure time is explicitly specified  
return this.GetPropertyRational((int)TagNames.ExifExposureTime).ToDouble();  
else  
if (this.IsPropertyDefined((int)TagNames.ExifShutterSpeed))  
//'-- Compute exposure time from shutter spee   
return (1 / Math.Pow(2, this.GetPropertyRational((int)TagNames.ExifShutterSpeed).ToDouble()));  
else  
// -- Can't figure out   
return 0;  
}  
}  
  
public Rational ExposureTime  
{  
get  
{  
if (this.IsPropertyDefined((int)TagNames.ExifExposureTime))  
// -- Exposure time is explicitly specified  
return this.GetPropertyRational((int)TagNames.ExifExposureTime);  
else  
return new Rational();  
}  
}  
  
//   
// Aperture value as F number (EXIF ExifFNumber/ExifApertureValue)  
//   
//   
//   
//   
// \[altair\] 10.09.2003 Created  
//   
public double Aperture  
{  
get  
{  
if (this.IsPropertyDefined((int)TagNames.ExifFNumber))  
return this.GetPropertyRational((int)TagNames.ExifFNumber).ToDouble();  
else  
if (this.IsPropertyDefined((int)TagNames.ExifAperture))  
return Math.Pow(System.Math.Sqrt(2), this.GetPropertyRational((int)TagNames.ExifAperture).ToDouble());  
else  
return 0;  
}  
}  
  
//   
// Exposure program used (EXIF ExifExposureProg)  
//   
//   
// If not specified, returns Normal (2)  
//   
// \[altair\] 10.09.2003 Created  
//   
public ExposurePrograms ExposureProgram  
{  
get  
{  
Int32 X = this.GetPropertyInt16((int)TagNames.ExifExposureProg);  
  
if (Enum.IsDefined(typeof(ExposurePrograms), X))  
return (ExposurePrograms)Enum.Parse(typeof(ExposurePrograms), Enum.GetName(typeof(ExposurePrograms), X));  
else  
return ExposurePrograms.Normal;  
}  
}  
  
//   
// ISO sensitivity  
//   
//   
//   
//   
// \[altair\] 10.09.2003 Created  
//   
public Int16 ISO  
{  
get { return this.GetPropertyInt16((int)TagNames.ExifISOSpeed); }  
}  
  
//   
// Subject distance in meters (EXIF SubjectDistance)  
//   
//   
//   
//   
// \[altair\] 10.09.2003 Created  
//   
public double SubjectDistance  
{  
get { return this.GetPropertyRational((int)TagNames.ExifSubjectDist).ToDouble(); }  
}  
  
//   
// Exposure method metering mode used (EXIF MeteringMode)  
//   
//   
// If not specified, returns Unknown (0)  
//   
// \[altair\] 10.09.2003 Created  
//   
public ExposureMeteringModes ExposureMeteringMode  
{  
get  
{  
Int32 X = this.GetPropertyInt16((int)TagNames.ExifMeteringMode);  
  
if (Enum.IsDefined(typeof(ExposureMeteringModes), X))  
return (ExposureMeteringModes)Enum.Parse(typeof(ExposureMeteringModes), Enum.GetName(typeof(ExposureMeteringModes), X));  
else  
return ExposureMeteringModes.Unknown;  
}  
}  
  
//   
// Focal length of lenses in mm (EXIF FocalLength)  
//   
//   
//   
//   
// \[altair\] 10.09.2003 Created  
//   
public double FocalLength  
{  
get { return this.GetPropertyRational((int)TagNames.ExifFocalLength).ToDouble(); }  
}  
  
//   
// Flash mode (EXIF Flash)  
//   
//   
// If not present, value NotFired (0) is returned  
//   
// \[altair\] 10.09.2003 Created  
//   
public FlashModes FlashMode  
{  
get  
{  
Int32 X = this.GetPropertyInt16((int)TagNames.ExifFlash);  
  
if (Enum.IsDefined(typeof(FlashModes), X))  
return (FlashModes)Enum.Parse(typeof(FlashModes), Enum.GetName(typeof(FlashModes), X));  
else  
return FlashModes.NotFired;  
}  
}  
  
//   
// Light source / white balance (EXIF LightSource)  
//   
//   
// If not specified, returns Unknown (0).  
//   
// \[altair\] 10.09.2003 Created  
//   
public LightSources LightSource  
{  
get  
{  
Int32 X = this.GetPropertyInt16((int)TagNames.ExifLightSource);  
  
if (Enum.IsDefined(typeof(LightSources), X))  
return (LightSources)Enum.Parse(typeof(LightSources), Enum.GetName(typeof(LightSources), X));  
else  
return LightSources.Unknown;  
}  
}  
  
#endregion  
  
#region Support methods for working with EXIF properties  
  
//   
// Checks if current image has specified certain property  
//   
//   
// True if image has specified property, False otherwise.  
//   
//   
// \[altair\] 10.09.2003 Created  
//   
public bool IsPropertyDefined(Int32 PID)  
{  
return (Array.IndexOf(this.\_Image.PropertyIdList, PID) > -1);  
}  
  
//   
// Gets specified Int32 property  
//   
// Property ID  
// Optional, default 0. Default value returned if property is not present.  
// Value of property or DefaultValue if property is not present.  
//   
//   
// \[altair\] 10.09.2003 Created  
//   
public Int32 GetPropertyInt32(Int32 PID)  
{  
return GetPropertyInt32(PID, 0);  
}  
  
public Int32 GetPropertyInt32(Int32 PID, Int32 DefaultValue)  
{  
if (IsPropertyDefined(PID))  
return GetInt32(this.\_Image.GetPropertyItem(PID).Value);  
else  
return DefaultValue;  
}  
  
//   
// Gets specified Int16 property  
//   
// Property ID  
// Optional, default 0. Default value returned if property is not present.  
// Value of property or DefaultValue if property is not present.  
//   
//   
// \[altair\] 10.09.2003 Created  
//   
public Int16 GetPropertyInt16(Int32 PID)  
{  
return GetPropertyInt16(PID, 0);  
}  
  
public Int16 GetPropertyInt16(Int32 PID, Int16 DefaultValue)  
{  
if (IsPropertyDefined(PID))  
return GetInt16(this.\_Image.GetPropertyItem(PID).Value);  
else  
return DefaultValue;  
}  
  
//   
// Gets specified string property  
//   
// Property ID  
// Optional, default String.Empty. Default value returned if property is not present.  
//   
// Value of property or DefaultValue if property is not present.  
//   
// \[altair\] 10.09.2003 Created  
//   
public string GetPropertyString(Int32 PID)  
{  
return GetPropertyString(PID, "");  
}  
  
public string GetPropertyString(Int32 PID, string DefaultValue)  
{  
if (IsPropertyDefined(PID))  
return GetString(this.\_Image.GetPropertyItem(PID).Value);  
else  
return DefaultValue;  
}  
  
//   
// Gets specified property in raw form  
//   
// Property ID  
// Optional, default Nothing. Default value returned if property is not present.  
//   
// Is recommended to use typed methods (like etc.) instead, when possible.  
//   
// \[altair\] 05.09.2005 Created  
//   
public byte\[\] GetProperty(Int32 PID, byte\[\] DefaultValue)  
{  
if (IsPropertyDefined(PID))  
return this.\_Image.GetPropertyItem(PID).Value;  
else  
return DefaultValue;  
}  
  
public byte\[\] GetProperty(Int32 PID)  
{  
return GetProperty(PID, null);  
}  
  
//   
// Gets specified rational property  
//   
// Property ID  
//   
// Value of property or 0/1 if not present.  
//   
// \[altair\] 10.09.2003 Created  
//   
public Rational GetPropertyRational(Int32 PID)  
{  
if (IsPropertyDefined(PID))  
return GetRational(this.\_Image.GetPropertyItem(PID).Value);  
else  
{  
Rational R;  
R.Numerator = 0;  
R.Denominator = 1;  
return R;  
}  
}  
  
//   
// Sets specified string property  
//   
// Property ID  
// Value to be set  
//   
//   
// \[altair\] 12.6.2004 Created  
//   
public void SetPropertyString(Int32 PID, string Value)  
{  
byte\[\] Data = this.\_Encoding.GetBytes(Value + ' ');  
SetProperty(PID, Data, ExifDataTypes.AsciiString);  
}  
  
//   
// Sets specified Int16 property  
//   
// Property ID  
// Value to be set  
//   
//   
// \[altair\] 12.6.2004 Created  
//   
public void SetPropertyInt16(Int32 PID, Int16 Value)  
{  
byte\[\] Data = new byte\[2\];  
Data\[0\] = (byte)(Value & 0xFF);  
Data\[1\] = (byte)((Value & 0xFF00) >> 8);  
SetProperty(PID, Data, ExifDataTypes.SignedShort);  
}  
  
//   
// Sets specified Int32 property  
//   
// Property ID  
// Value to be set  
//   
//   
// \[altair\] 13.06.2004 Created  
//   
public void SetPropertyInt32(Int32 PID, Int32 Value)  
{  
byte\[\] Data = new byte\[4\];  
for (int I = 0; I < 4; I++)  
{  
Data\[I\] = (byte)(Value & 0xFF);  
Value >>= 8;  
}  
SetProperty(PID, Data, ExifDataTypes.SignedLong);  
}  
  
//   
// Sets specified property in raw form  
//   
// Property ID  
// Raw data  
// EXIF data type  
// Is recommended to use typed methods (like etc.) instead, when possible.  
//   
// \[altair\] 12.6.2004 Created  
//   
public void SetProperty(Int32 PID, byte\[\] Data, ExifDataTypes Type)  
{  
System.Drawing.Imaging.PropertyItem P = this.\_Image.PropertyItems\[0\];  
P.Id = PID;  
P.Value = Data;  
P.Type = (Int16)Type;  
P.Len = Data.Length;  
this.\_Image.SetPropertyItem(P);  
}  
  
//   
// Reads Int32 from EXIF bytearray.  
//   
// EXIF bytearray to process  
//   
//   
//   
// \[altair\] 10.09.2003 Created  
// \[altair\] 05.09.2005 Changed from public shared to private instance method  
//   
private Int32 GetInt32(byte\[\] B)  
{  
if (B.Length < 4)  
throw new ArgumentException("Data too short (4 bytes expected)", "B");  
  
return B\[3\] << 24 | B\[2\] << 16 | B\[1\] << 8 | B\[0\];  
}  
  
//   
// Reads Int16 from EXIF bytearray.  
//   
// EXIF bytearray to process  
//   
//   
//   
// \[altair\] 10.09.2003 Created  
// \[altair\] 05.09.2005 Changed from public shared to private instance method  
//   
private Int16 GetInt16(byte\[\] B)  
{  
if (B.Length < 2)  
throw new ArgumentException("Data too short (2 bytes expected)", "B");  
  
return (short)(B\[1\] << 8 | B\[0\]);  
}  
  
//   
// Reads string from EXIF bytearray.  
//   
// EXIF bytearray to process  
//   
//   
//   
// \[altair\] 10.09.2003 Created  
// \[altair\] 05.09.2005 Changed from public shared to private instance method  
//   
private string GetString(byte\[\] B)  
{  
string R = this.\_Encoding.GetString(B);  
if (R.EndsWith(" "))  
R = R.Substring(0, R.Length - 1);  
return R;  
}  
  
//   
// Reads rational from EXIF bytearray.  
//   
// EXIF bytearray to process  
//   
//   
//   
// \[altair\] 10.09.2003 Created  
// \[altair\] 05.09.2005 Changed from public shared to private instance method  
//   
private Rational GetRational(byte\[\] B)  
{  
Rational R = new Rational();  
byte\[\] N = new byte\[4\];  
byte\[\] D = new byte\[4\];  
Array.Copy(B, 0, N, 0, 4);  
Array.Copy(B, 4, D, 0, 4);  
R.Denominator = this.GetInt32(D);  
R.Numerator = this.GetInt32(N);  
return R;  
}  
  
#endregion  
  
#region " IDisposable implementation "  
  
//   
// Disposes unmanaged resources of this class  
//   
//   
//   
// \[altair\] 10.09.2003 Created  
//   
public void Dispose()  
{  
this.\_Image.Dispose();  
}  
  
#endregion  
  
}  
  
}
logo

Shapez Theme

· Home Playground About

18


OCTOBER

话说,最早使用Aptana的时候,还是06年。此后在各种Web的开发场合,一直大力宣传推广该软件的使用。Aptana经历一段时间的收费风波后,现在又开始免费使用了,于是搞了个最近的版本装上,却发现英文的还是不习惯啊,整了个中文包,记录下。

Aptana是一个基于Eclipse的集成开发环境,其最广为人知的是它非常强悍的JavaScript编辑器和调试器。近年来又扩展了Ruby和iphone的集成开发环境,最新版的还支持jquery和其他一些js框架,可以依据jquery的文档,直接在编辑器中对方法给予智能提示,这对我们这些习惯了vs开发的人来说,太有利了。

支持jquery看来很简单,这里有一段拷贝来的说明,大家看看吧,今天没时间测试了,明天再测试:

安装完毕Aptana后,还不能使用智能提示的,应为没有库,我们还要在我们的项目中加入库文件。  
  
首先下载:[https://raw.github.com/aptana/javascript-jquery.ruble/master/support/jquery.1.4.2.sdocml](https://raw.github.com/aptana/javascript-jquery.ruble/master/support/jquery.1.4.2.sdocml) 一定 要保证是.sdocml文件不是文本文档  
  
再下载:http://code.jquery.com/jquery-1.4.1-vsdoc.js或是[http://encosia.com/source/jquery/jquery-1.5.0-vsdoc.js](http://encosia.com/source/jquery/jquery-1.5.0-vsdoc.js)(需要3.0.1版本以上)

至于中文包,其实跟所有基于Eclipse的集成开发环境一样,都要找这个地址去安装,zend啊什么的,都要照这个路径安装就行,不过汉化的不全。

路径是:

http://download.eclipse.org/technology/babel/update-site/R0.9.0/helios/

至于怎么安装,不用说了吧。

logo

Shapez Theme

· Home Playground About

06


SEPTEMBER

这段时间,工作比较乱,各种开发环境的搭建、尝试多个开发工具,Win7的C盘hold不住了,本来我觉得50G的C盘不算太小,但某天却惊奇的发现C盘剩余空间是0!当然不久就变成100多兆了,用360清理助手也只能清理出300多兆(我平常经常做清理,垃圾本来就不多的)。但是想想我的软件都装到D盘去了啊,C盘只安装了那些必须安装到C盘的东西,什么visual studio、sqlserver还有windows phone开发包什么的,这些装别的盘符麻烦,而且本来50G的空间我觉得并不小。所以我决定手动清理下C盘。

清理之前,我们先看看下面这个搞笑图片:

                                           盖茨的磁盘空间理论

卸载不必要的程序

首先,把该卸载的卸载掉。虽然大多数软件没有安装在C盘,但VS的插件似乎必须的装到C盘,那个intel C ++的编译器,再加上他的ipp库,足足占了2个G的空间,还有一些vs内置的插件,比如水晶报表啥的,不需要用的都卸载掉,当然这个是特例。

清理用户文件夹

第二个需要清除的文件夹是用户文件夹:

C:UsersuserAppData

users是电脑上当前用户的文件夹,电脑如果自己用,就不要建那么多用户了,每个用户都需要占一部分的空间,不常用的用户文件夹,直接删除即可,当然一般也没有多大空间,我们这里要清除的是最常用的用户的appdata文件夹。

其实这个文件夹是比较有用的,如果整个删除的话,可能会引起部分程序无法使用。

这个文件夹中又分为三个文件夹,其中Roamin文件夹和local文件夹占据了大量的空间(各占1G左右)。仔细分析其中的文件夹后发现,占据空间最大的分别是微软、苹果和谷歌。要命的是,google的谷歌浏览器程序文件竟然在这里,更新文件也不会自动删除,浏览器缓存高达800M。

谷歌浏览器缓存路径默认为:

C:UsersuserAppDataLocalGoogleChromeUser DataDefaultCache

建议直接删除。

还有微软的文件夹中,带了很多不常用的程序,如果不需要,就删掉吧,路径:

C:UsersuserAppDataLocalMicrosoft

另外,如果你使用Windows Live Mail,最好把默认的邮件保存路径改到其他路径,否则该文件夹也将是容量杀手。

清理windows文件夹

前面讲的清理路径,都不是特别大量的文件夹,但windows目录占用了20G的空间,能不能清理下该目录呢?

百度上找到一个清理目录,但所述的文件都不大,而且实际去删除的时候报没有权限(我没用的administrator),就放弃了。

系统更新目录

记得早在win2003时,windows更新目录会占很大的空间,可以直接删除:

C:WindowsDownloaded Installations

现在win7中这个目录仍然存在,但我这里是空的,不知道是不是360帮忙清除掉了,该文件夹可以安全删除。

C:WindowsDownloaded Program Files

这个是ie上安装的插件什么的目录,不需要的插件可以直接删,不过都不大。

安装目录

查看C盘中有个隐藏目录

C:WindowsInstaller

该目录下竟然有10多G的占用,这个目录应该是安装程序是保留的临时文件。记得之前的windows安装程序的卸载直接放在程序目录里面,而且也不大,但这个目录里面放的,全是很大而且改名的msi或msp文件,能不能直接删呢?

经查,大多数的说法是该目录的文件如果删除,程序就无法卸载,也有人说删除后一部分功能不能使用了,比如office会彻底不能用。

其中有个$PatchCache$文件夹,看到有人评论说该目录可以完全删除(也有人说不可以删的),相信这句话是有风险的,但我还是信了。我删掉该目录(回收站),然后重启了电脑,打开office等常用的程序的,发现还能用,现在可以确信了。

这就是说:

C:WindowsInstaller$PatchCache$

目录是可以完全删除的,当时我的这个目录清出来6G的空间。

对于Installer下面的msi文件,据说有个工具可以帮忙清理,下面有段来自网上的摘录:

在命令行,通过命令msizap.exe G可以删除一些孤儿文件:

C:>msizap.exe G
MsiZapInfo: Performing operations for user S-1-5-21-1935655697-1409082233-839522115-1003
Removing orphaned cached files.
Removed file: C:WINDOWSInstaller102db95.mst
Removed file: C:WINDOWSInstaller102dba2.mst
Removed file: C:WINDOWSInstaller102dbac.mst
Removed file: C:WINDOWSInstaller337c229.mst
Removed file: C:WINDOWSInstaller3b1ae.mst
Removed file: C:WINDOWSInstaller41485c5.mst
Removed file: C:WINDOWSInstaller65a2f.mst
Removed file: C:WINDOWSInstaller76bf7.mst
Removed file: C:WINDOWSInstaller9419741.mst
Removed file: C:WINDOWSInstaller9419770.mst
Removed file: C:WINDOWSInstaller9419778.mst
Removed file: C:WINDOWSInstallera43b7be.mst
Removed file: C:WINDOWSInstallerf8fe2f1.mst

网上还可以找到这样一个工具:
Windows Installer UnUsed Files Cleanup Tool (简称WICleanup)是一个用于清理 Windows Installer 冗余文件的工具。
软件主页为:http://www.kztechs.com/wicleanup/
下载地址:http://www.kztechs.com/wicleanup/wicleanup.zip

我试了,确实能删除,删掉几个msi和mst文件,但问题是删掉的都是小文件。仔细看这段中的孤儿文件,估计只是检查某些程序已经卸载但没有删除掉的安装文件,所以不解决大问题,还得靠自己手工。

把详情打开,看看哪些文件永远都不需要删除的,自己删掉吧,比如vs的几个更新,有300兆的,有500兆的,挑大个的删。

总结

经此次清理,C盘空间达到12G,又可以折腾一阵子了。其实之前也做过多次清理,但从未触及Installer文件夹,此次也算有所发现吧。

logo

Shapez Theme

· Home Playground About

27


AUGUST

上个月被邀请了加入google+,也没怎么玩,不久前有朋友咨询有没有邀请,发现还是有部分朋友无法注册,本人有一些邀请,如果谁还需要邀请,就留言留下你的邮箱就可以了。

附访问方法:

(C:windowssystem32driversetc)添加以下内容既可

#—— Google+ ——
203.208.46.29 plus.google.com
203.208.46.29 talkgadget.google.com
203.208.46.29 picasaweb.google.com
203.208.46.29 lh1.ggpht.com
203.208.46.29 lh2.ggpht.com
203.208.46.29 lh3.ggpht.com
203.208.46.29 lh4.ggpht.com
203.208.46.29 lh5.ggpht.com
203.208.46.29 lh6.ggpht.com
203.208.46.29 lh6.googleusercontent.com
203.208.46.29 lh5.googleusercontent.com
203.208.46.29 lh4.googleusercontent.com
203.208.46.29 lh3.googleusercontent.com
203.208.46.29 lh2.googleusercontent.com
203.208.46.29 lh1.googleusercontent.com