【问题标题】:nine-patch images with 1px width or height -- special case or faulty files?1px 宽度或高度的九个补丁图像 - 特殊情况或错误文件?
【发布时间】:2014-05-25 17:32:58
【问题描述】:

在修改Launcher2.apk中的图片的过程中,我发现了一些明显是九个补丁的文件,但高度或宽度只有1px:

$ file **/*.9.png G "\( 1 x\|x 1,\)"
Launcher2/res/drawable-land-xhdpi/workspace_bg.9.png:                   PNG image, 400 x 1, 8-bit gray+alpha, non-interlaced
Launcher2/res/drawable-sw720dp-xhdpi/workspace_bg.9.png:                PNG image, 1 x 400, 8-bit gray+alpha, non-interlaced
Launcher2/res/drawable-xhdpi/workspace_bg.9.png:                        PNG image, 1 x 400, 8-bit gray+alpha, non-interlaced

这些文件是否被其创建者以某种方式搞砸了,或者它们是特殊情况,即。 e.固定宽度但可变高度,反之亦然?

九个补丁文件的格式有什么正式的定义吗?当然,我用谷歌搜索,这花了我相当长的时间,但没有找到任何可以帮助我的信息。如果它还涵盖其他方面会最好,因为我发现了很多其他方面 可疑图像在几个包中,其中包含非二进制信息的左侧/顶部/右侧/底部像素;因此,我还想确切地知道哪些值编码重复/拉伸/原样,哪些被忽略。

Google 的 Canvas and Drawables 文档中的这个 section 没有提供很多细节(实际上没有)。并且分发的 draw9patch.jar 也没有多大帮助。

以防万一:我使用Launcher2.apk 和其他软件包的设备是 Moto G,库存 4.3 固件。

提前致谢

【问题讨论】:

  • 我说得太快了,我实际上也找不到规范。显然,编译和未编译的 9 补丁之间存在差异,我不知道。为创建 9 个补丁 png 编写客户端的人正在基于他们使用十六进制编辑器和 Android SDK 中的代码库本身找到的内容进行工作。 groups.google.com/forum/#!msg/adt-dev/z_iLJWyDQdo/lf4sR6CRl2cJ

标签: android nine-patch


【解决方案1】:

好的,自从我对九个补丁图像进行了更多调查后,我学到了什么:

主要的错误可能是认为九个补丁的重复/拉伸/保留元数据总是编码在图像文件的边界像素中。这不是正确的。

事实上,有两种九补丁格式,显然称为源格式和编译格式,前者具有众所周知的特殊边框,其中像素指定补丁(其中您可以有超过九个,确实)。这很可能被称为 source 形式,因为像素在图像编辑器中会显示出来(但是,在某些情况下它们可能不会;见下文)。

根据the apktool wiki,第二个——已编译——表单将元信息编码在一个特殊的(私有)PNG 块中;同一页面声称这些块被称为npTc,我尝试使用基本的 Linux 实用程序验证这一点可以证实这一点:

$ strings search_frame.9.png 
IHDR
TnpTc
yIDATX
[...]

TweakPNG 也显示这个块。

所以,我的实际问题的答案是:我认为那些 1 像素高/宽的图像是源形式的九个补丁,而它们实际上是编译后的压缩格式。


由于似乎没有官方规范,这是问题的一部分,我只是在这里开始收集信息。

从一种形式转换为另一种形式的工具

  • aapt(随 Android sdk 一起提供)有两个子命令,

    • s[inglecrunch]编译单个边框九个补丁图像到chunked/crunched格式(使用命令行选项-i和-o分别用于输入和输出文件),
    • c[runch] 采用资源目录(选项-S)和输出目录的名称(选项-C),遍历整个源目录并根据需要创建目标子目录。

     

    (警告:如果你忘记事先创建目标目录树的根目录,aapt 不会出错,而是忙于 $whatever,占用整个 CPU 内核/线程的注意力和力量,如此有效地表明它很忙,而它至少不是用户期望的。(只是为了完整起见:我正在运行 SDK 19.0.1))

  • apktool 是一个自定义的 java 应用程序,它能够解压整个 *.apk 文件,将 *.xml 文件转换为纯文本文件并将 *.9.png 文件转换为它们的源 格式。

    要将所有内容(可能已修改)放回 *.apk 存档,您需要手动从原始包中提取一些文件,这是大多数 zip/unzip 实用程序应该能够做到的,但没有转换。在重新打包的过程中,apktool显然使用了aapt,它已经捆绑了一个版本。

    这个捆绑的aapt 可能是从较旧的 SDK(19 之前)中提取的,因为它显示了相同的缺陷(上面提到的紧忙循环和几个段错误,其中一个简单的 if 可以防止这种讨厌的行为(例如,当您不将-C 选项提供给c[runch] 子命令时,它会出现段错误)),而它缺乏对s[ingleCrunch] 子命令的支持。

  • xUltimate-d9pc(这似乎是 source-to-crunched-格式转换器,但我没有真正测试一下。)

  • WebLaF(也未经测试;它似乎有来源,可以从中获得更多信息。)

九个补丁的格式

源表格

大多数人都已经知道,九个补丁的 source 形式确实包含图像的正常像素数据以及额外的边框。我将尝试用一个简单的ASCII 表示来说明(并希望您的字体能够识别它的含义):

    -------##--#####--##-------
    -......XXXXXXXXXXXXX......-
    -...XXX.............XXX...-
    -..X...................X..-
    -.X.....................X.-         Legend
    -.X.....................X.-
    #X.......................X-         (top and left borders)
    #X.......................X-         #  denotes a "stretch"/"repeat" mark
    -X.......XXXXXXXXX.......X-         -  denotes a "keep" mark
    -X.......X.......X.......X#
    #X.......X.......X.......X#         (bottom and right borders)
    #X.......X.......X.......X#         #  marks the content area (aka fill area)
    -X.......X.......X.......X#         -  marks ... umm... what is it called?
    -X.......XXXXXXXXX.......X-
    #X.......................X-         (image area)
    #X.......................X-         .  pixel in "background" color
    -.X.....................X.-         X  pixel in foreground color
    -.X.....................X.-
    -..X...................X..-
    -...XXX.............XXX...-
    -......XXXXXXXXXXXXX......-
    ----------#######----------

这是某种双盒,外层有圆角。这种形式的九个补丁的大小为 27x22px,但实际图像大小仅为 25x20px——这也是它可以在应用程序中显示的最小尺寸,但可以拉伸到任意大小。

重复标记告诉框架在拉伸图像时要重复哪些行,例如。 G。当图像以 26 像素的实际高度显示时,第 7、8、11、12、15 和 16 行并重复一次,以弥补屏幕上的多余行。这样可以确保两个框的边框始终保持 1 像素薄,并且外框的圆角始终具有相同的大小/半径。虽然标记区域将被充分拉伸(如果拉伸尺寸与原始尺寸的差异不是标记线的倍数,则会出现不规则性,但在今天的 160+ dpi 显示器上,这可能并不重要;然而,更少的重复/拉伸标记可能会更高效,但话又说回来......在今天的 1.6+ GHz 四核手机上,这也无关紧要......)

重复/拉伸标记的值 当我发布问题时,我不确定 stretching 和 repeating 之间是否有任何语义差异,我仍然没有。

根据A simple guide to 9-patch for Android UI,标记必须为纯黑色,以重复有问题的行/列,否则结果将是错误的,不会通知用户,除非屏幕上显示不正确;这对于以前的 SDK 版本可能是正确的(文章来自 2011 年 5 月)。

但是,aapt 版本(在 SDK 19 中和 apktool 1.5.2 中的版本)都抱怨边框中的任意颜色,例如:

ERROR: 9-patch image test/search_frame_.9.png malformed.
       Ticks in transparent frame must be black or red.
       Found at pixel #21 along top edge.
ERROR: 9-patch image test/tab_unselected_pressed_focused_holo.9.png malformed.
       Must have one-pixel frame that is either transparent or white.

第二个文件已经是经过编译/处理的九个补丁,而第一个不是。

我从“黑色或红色”消息中读到的是,边框可能不包含除#00000000(纯黑色,用于重复/拉伸标记)、#00ff0000(纯红色,可能相同)以外的像素值,和#xx000000(带有任意透明度的黑色(xx>0)用于“保留”标记,也可能是#xxFF0000,但我没有测试过)。

我仍然不确定红色和黑色是否具有不同的语义,或者红色是否只是使用黑色背景的图像编辑器的替代品,在视觉上很难区分 #00000000 和 #01000000,例如)。

编译/压缩表格

SDK 包含两个类android.graphics.NinePatch 和android.graphics.NinePatch_Delegate,它们利用对本机库的调用,因此源代码并没有提供太多信息。我没有安装 NDK,我什至不知道它是否提供相关库的源代码。

我发现最好的是answer 到Android: compiling 9-patch files to be used outside of the drawable folder?

【讨论】:

    猜你喜欢
    • 2012-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-14
    • 2012-10-03
    • 1970-01-01
    相关资源
    最近更新 更多