Bitmap 文件结构

0x81 位图

Bitmap,即位图,是非常常见的一种图片文件结构。在我平时的Android开发当中,最常见的性能问题就是Bitmap资源的问题。一种不太严谨的说法是,所有压缩格式的图片经过解码后都是以Bitmap的形式存在于内存当中,之所以有这种说法,就是因为Bitmap是一步一个字节的图片存储方式,没有JPEG那种区域颜色涂抹。

位图又叫做光栅图,它以像素为单位一个点一个点的描述图像信息,因此也有人称他为点阵图。还有一种图片格式与之对立,叫做矢量图或向量图,它采用数学方法进行描述而不是记录每一个像素信息,因此它可以无限放大而不失真。一般的,我们又称他们为图像和图形,意为图片像素和图片形状。

0x82 位图文件

狭义上讲,我们平时所说的位图文件就是BMP文件,它以.bmp作为文件扩展名,是Windows采用的图像文件存储格式,在后来BMP才具有通用性成为了设备无关位图,而默认的扩展名依然是.bmp,当然也可以使用.dib(Device Independent Bitmap)。

Read More

为Python的TensorFlow添加CPU特性支持

0x81 性能警告

昨天经过漫长的编译时间等待后,我们在python解释器成功导入tensorflow模块说明安装成功,但是当我们测试使用时,却会遇到性能警告的提示。

我们执行以下命令:

1
2
3
4
import tensorflow as tf
hello = tf.constant("hello tensorflow")
session = tf.Session()
print session.run(hello)

得到了如下结果:

AVX和SSE警告

0x82 添加CPU支持

添加支持的方式很简单,只需要在之前的bazel构建命令里添加对应的参数,这样gcc在执行编译时便会添加对应的cpu特性支持。

bazel build -c opt --copt=-msse4.1 --copt=-msse4.2 --copt=-mavx --copt=-mavx2 --copt=-mfma -k //tensorflow/tools/pip_package:build_pip_package执行又要等待半个多小时,其中5个额外的copt参数便分别对应sse4.1、sse4.2、avx、avx2和fma。编译完成后按之前的流程生成wheel文件并安装即可。

为Python构建TensorFlow支持

0x81 直接使用pip安装whl

之前提到过使用Bazel构建系统为Android构建so库和jar包的支持,今天我们构建whl并为Python提供TensorFlow的支持。安装TensorFlow的方式很简单,使用Google提供的whl进行安装即可,根据网上的教程(具体是哪个网站的忘记了,都差不多也都比较旧,安装的都是0.x版本,而最新的已经到了1.1.0-rc2,根据官方的changelog版本1.0.0是一次比较大的更新),都是采用类似的pip安装命令sudo pip install --upgrade https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.8.0-cp27-none-linux_x86_64.whl进行安装的,通常情况下安装完成即可在python脚本中通过import tensorflow使用tensorflow提供的API。

0x82 使用源码构建whl

手动构建tensorflow仍然需要Bazel构建系统的支持,而Bazel依赖于JDK8,准备过程与为Android编译依赖库时一致,这里就不赘述了。

  1. ./configure
    在tensorflow目录下运行configure配置文件,就会询问你一系列问题用于配置,包括python解释器位置,hdfs支持以及python库位置等等,然后会出现以下错误:

    缺少numpy

    我们需要安装python2-numpy这一科学计算库,例如sudo dnf install python2-numpy,再次configure。

  2. build pip package
    和使用Bazel构建Android库时类似,执行构建命令bazel build -c opt tensorflow/tools/pip_package:build_pip_package,Bazel开始下载一些列依赖并开始构建,期间占用内存会比较多,不弱于编译Bazel时:

    编译过程

    最终耗时:INFO: Elapsed time: 2518.980s, Critical Path: 2429.50s

  3. 生成whl
    创建一个临时目录比如~/tensorflow用于存放whl文件,使用生成的命令bazel-bin/tensorflow/tools/pip_package/build_pip_package ~/tensorflow生成whl,你可能会遇到以下错误:

    缺少wheel

    使用pip执行sudo pip install wheel安装wheel库即可,再次生成wheel文件。

    生成的whl文件

  4. 安装whl
    pip install tensorflow-1.1.0rc1-cp27-cp27mu-linux_x86_64.whl

    1
    2
    Installing collected packages: html5lib, bleach, markdown, funcsigs, pbr, mock, werkzeug, protobuf, tensorflow
    Successfully installed bleach-1.5.0 funcsigs-1.0.2 html5lib-0.9999999 markdown-2.2.0 mock-2.0.0 pbr-2.1.0 protobuf-3.2.0 tensorflow-1.1.0rc1 werkzeug-0.12.1

    最终看到以上提示信息的时候,说明安装成功了。

0x83 测试tensorflow的python支持

进入交互式python shell,import tensorflow如果没有错误提示表明成功。

为Android构建TensorFlow支持

0x80 前言

本文参考《Android TensorFlow Machine Learning Example》

0x81 TensorFlow

TensorFlow是一个机器学习的开源库,出自Google之手,它的核心由C++编写而成,当然Google推荐使用python进行上层API的开发,我们可以通过JNI在Android进行调用。

0x82 Bazel

Bazel,一个构建系统,根据它官网的描述,Bazel是Google使用的构建系统。Bazel现在仍然是beta版本,但不可否认的,它是一个快速可靠可扩展的构建系统,你可以根据自己的需要书写构建规则。

Read More

Fedora下安装Unity Editor

0x81 Unity3D

Unity3D是一个跨平台的游戏框架引擎,对Windows、macOS、Linux、Android、iOS、Web都有很好的支持。如果你使用的是PC或Macbook,那么恭喜你,Unity官方对他们支持的很好,还可以分平台支持安装。如果你很不幸和我一样用Linux发行版做开发,并且还不想因为一个小小的开发工具就更换开发环境,那么恭喜你,Unity对它们没有支持。不过很幸运,Unity在论坛推出了内测计划,并且官方对LTS的Ubuntu还有预测试并提供deb安装包,deb在安装时会主动解决好依赖。相对应的,Unity提供了sh自解压脚本,这就需要你自己处理依赖问题。

0x82 Unity依赖

使用ldd命名可以很方便的查看可执行ELF文件需要依赖哪些动态运行库,大部分库只要你安装了显示驱动都伴随安装了,个别的依赖利用so搜索安装对应的包即可,下面主要说说解决了Unity的依赖后还可能遇到的问题。

Read More

Makefile 基础

0x00 吐槽

最近一段时间真是命途多舛,昨天晚上感觉差点被发烧烧成傻子,到晚上2点多都烧到了39,当时真的担心自己睡过去醒了会成为白痴,那我还如何去怼人,那么多没做的事自己再也意识不到是多么可悲的事情。这段时间诸多不顺,当然这种不顺利也不仅仅是在我身上,也许生活本该这样充满波折才比较有趣,但是大条的自己却往往不去在意一些细节,让自己一错再错,比如这日常笔记就一断再断。不得不说,能坚持做一件事情真的时非常不容易,那些可以坚持的人必然具有强大的内心,而我自己又是那种外表逞强内心脆弱的人,有的时候真的很羡慕那些无忧无虑做爱做的事情的人,也许,我羡慕的一直都是我自己而不知。

0x81 make

扒wiki的事情这里就不做了,有时候想想自己把网上的东西用自己理解的语言表达出来还不一定准确,毕竟这是此情此景下的理解,过个小半年自己如果再回来看也许都不知道自己当初说了啥。这里简单的说一下make,make在英语里就是做的意思,make love啦等等,我们可以将它理解为程序的构建工具,就像webpack一样,它根据描述文件Makefile调用编译工具如GCC完成整个构建任务build,说她是个辅助工具也不为过。它有很多实现,在Linux下常用的就是GNU Make Tool。

0x82 Makefile

Makefile是一个描述文件,也可以视为配置文件,就像webpack的webpack.config.js文件,它描述了构建任务所需的必要参数和构建过程。通常make工具会自己搜寻目录下的描述文件,如makefile、Makefile等,我们只需要在工程目录下创建相应的文件即可。

Read More

YouCompleteMe的C/C++支持

0x81 为YCM添加C系语言的支持

我曾经记录过一篇使用YouCompleteMe这一Vim插件补全Python脚本的方法,现在需要对C/C++进行支持,根据官方的解释,我们只需要在原来的install.py脚本后添加参数--clang-compiler即可以在ycm_core中添加C补全支持。YCM的C补全依托的是Clang编译器,通过编写时实时编译查询你可能需要的补全关键词,因此我们需要添加Clang的支持。

0x82 编译带C-Compiler的YCM

执行命令python3 install.py --clang-compiler便可以开始插件的编译,最新的编译脚本已经对Clang做了支持,如果你没有指定Clang环境,脚本会自动从llvm官网下载最新的二进制包。

在这里遇到了一个问题,就是脚本下载的二进制包速度非常非常慢,可能受限于天朝网络的影响,我不得不手动下载该包并放到对应的目录以便YCM直接开始编译。文件路径如下:

归档位置

Read More

Nexus5 Format F2FS Boom

0x80 前言

之前记录过一次作死经历,万万没想到就然还会有姊妹篇。Nexus 5作为我购机史上最成功的一次尝试,在它如此暮年之时,却又遭受如此折腾,前有mac丢失,现有数据丢失。。

文件系统结构基于AOSP 7.1.1。

0x81 数据丢失这种现象发生了不止一次

其实早在很久以前,我就遇到过几次数据丢失,当然那都是我自己作死去换Recovery,换了之后清理/data居然清理掉了整个emmc芯片上的数据。而这一次,对于切换/data区的ext4文件系统到f2fs,即使自己做了双重备份,却也是防不胜防,我最终惊奇地发现整个Internal Storage都变成了空的,冷汗直流。

0x82 F2FS

F2FS:Flash Friendly File System,顾名思义闪存友好的文件系统,最早由三星提出,声称可以最大限度的提高Flash闪存对于随机文件的读写效率,但是三星从来没有使用到自家的产品上。前一段时间华为发布了Mate9声称采用了F2FS可以18个月都不卡,都是噱头。

为什么要使用f2fs呢,其实好处还是很多的,特别是对于一些emmc5.0以下的老闪存设备,读写速度的提升还是有的,但是我们可能并感知不到,并且对于连续读写,f2fs可能还没ext4快。f2fs自发布以来,于早期被集成进了kernel 3.8并不断完善,后来各大开发者将这一feature引入自己rom的内核当中,逐渐的很多三方rom都开始支持f2fs,其中刷机小王子Nexus 5也是他们中的一员。

Read More

Fedora 26 下编译axel

0x81 axel

axel是一款轻量级的命令行加速下载工具,它支持多线程下载和断点续传,由C语言编写,在Linux上是一款非常实用的下载工具。

0x82 为什么要自己编译

在大部分发行版当中,由于axel是比较热门的Linux工具,包管理器通常能够在发行版仓库中找到稳定版本的二进制包,比如在Fedora 26(Branched)的repo中就提供axel2.5版本的二进制包,但是这个二进制包出于稳定性考虑有可能并不会是由最新的源代码编译而成的,所以可能缺少部分特性支持。

今天遇到了一个特殊的问题,我使用axel下载文件时,在过了很长时间的初始化下载之后,终端中报出了Too many redirects错误并终止下载,其意思是太多重定向,可能axel对重定向的支持还不是特别好。经过一番Google,我发现大部分人的问题是出现在http重定向到https时发生的,比如gayhub上release的一些源码打包,而我也发现我的下载地址默认打开其实是一个web页面之后触发的下载。通过查看axel的github issues,我发现在较新的版本已经做了重定向支持,而Fedora仓库提供的又是2.5版本,于是我决定自己编译它。

0x83 配置与编译

  1. 下载源码包
    github上的源码包已经release到了2.12。点我可以下载

  2. autogen 脚本
    在这里遇到了一个坑,autogen执行时遇到了autopoint不存在的问题,经过查询autopoint现在在gettext包里,grub2-efi也依赖了这个包,也就是说这个包肯定已经安装了。经过多次尝试,我才想到,这种手动编译通常需要头文件或开发包,于是我安装了gettext-devel这个包,autogen顺利跑完了并生成了configure文件

  3. configure 配置编译环境
    ./configure又遇到了问题,libssl bot found,我第一感觉是怎么可能?!后来一想,安装了openssl-devel就成功生成了makefile,有了makefile就可以进行编译了。

  4. 编译
    老套路,make & make install编译完成后会安装到/usr/local/bin/axel,安后就可以使用2.12版本的axel工具了~

Fresco与SharedElement共用的问题

0x81 Fresco 的坑

在之前的Android Transition动画框架中的共享元素部分我们提到过Fresco的SimpleDraweeView会导致图片消失,在gayhub上也有很多针对这个问题的issue提出来,后来官方给出的解决方案是不使用Android自带的ImageTransaction,而是使用Fresco提供的辅助工具生成Transaction:

1
2
3
4
getWindow().setSharedElementEnterTransition(DraweeTransition
.createTransitionSet(ScalingUtils.ScaleType.CENTER_CROP, ScalingUtils.ScaleType.FIT_CENTER));
getWindow().setSharedElementReturnTransition(DraweeTransition
.createTransitionSet(ScalingUtils.ScaleType.FIT_CENTER, ScalingUtils.ScaleType.CENTER_CROP));

当初发现这样可以工作了,但是返回时会有闪动,后来经过测试发现并不是闪动,而是原Activity里的空间不见了。至于闪动,是由于我在图片详情的页面里使用了沉浸式的界面,从目标Activity返回时重绘了界面使他又显示了出来,所以才出现闪动。

0x82 Nougat 上Fresco 新的问题

之所以官方的解决方案最终使issue们关闭了,是因为这种方式在Android L/M上工作的很好,是在Android N上才又出现了这个问题,由于WindowFlag的切换导致原来的ImageView又显示出来,虽然界面出现闪动但也不影响使用,但这样毕竟不够完美。gayhub上也有人指出调用一次requestLayout就能显示出来,但会闪动。

所以,又有人提出了看起来更合理的解决方案,使用ExitSharedElementsCallback,通过这个回调将消失的View显示出来:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
setExitSharedElementCallback(new SharedElementCallback() {
@Override
public void onSharedElementStart(
List<String> sharedElementNames,
List<View> sharedElements,
List<View> sharedElementSnapshots) {
super.onSharedElementStart(sharedElementNames,
sharedElements, sharedElementSnapshots);
for (View view : sharedElements) {
if (view instanceof SimpleDraweeView) {
view.setVisibility(View.VISIBLE);
}
}
}
});

原理很简单,就是找出时共享元素的SimpleDraweeView并手动让它显示出来,目前看起来工作良好。

虽然这样也能达到目的,我还是希望官方能出一个完备的解决方案,从根本上解决问题。