如何在Android上更快地将RGB565转换为YUV420SP?

2024-01-12

我需要显示一张jpeg图片,并将其转换为YUV420SP。首先我使用SkBitmap解析jpeg并显示它,然后我使用下面的代码在android上将RGB565转换为YUV420SP,但是转换640*480 RGB565图片花费了75ms,所以有人知道在android上将RGB565转换为YUV420SP的更快方法安卓?或者在 Android 上将 jpeg 文件转换为 YUV420SP 的更快方法?

// Convert from RGB to YUV420
int RGB2YUV_YR[256], RGB2YUV_YG[256], RGB2YUV_YB[256];
int RGB2YUV_UR[256], RGB2YUV_UG[256], RGB2YUV_UBVR[256];
int RGB2YUV_VG[256], RGB2YUV_VB[256];

//
// Table used for RGB to YUV420 conversion
//
void InitLookupTable()
{
    static bool hasInited = false;
    if(hasInited)
        return ;
    hasInited = true;
    int i;
    for (i = 0; i < 256; i++)
        RGB2YUV_YR[i] = (float) 65.481 * (i << 8);
    for (i = 0; i < 256; i++)
        RGB2YUV_YG[i] = (float) 128.553 * (i << 8);
    for (i = 0; i < 256; i++)
        RGB2YUV_YB[i] = (float) 24.966 * (i << 8);
    for (i = 0; i < 256; i++)
        RGB2YUV_UR[i] = (float) 37.797 * (i << 8);
    for (i = 0; i < 256; i++)
        RGB2YUV_UG[i] = (float) 74.203 * (i << 8);
    for (i = 0; i < 256; i++)
        RGB2YUV_VG[i] = (float) 93.786 * (i << 8);
    for (i = 0; i < 256; i++)
        RGB2YUV_VB[i] = (float) 18.214 * (i << 8);
    for (i = 0; i < 256; i++)
        RGB2YUV_UBVR[i] = (float) 112 * (i << 8);
}

int ConvertRGB5652YUV420SP(int w, int h, unsigned char *bmp, unsigned char *yuv)
{
    unsigned char *u, *v, *y, *uu, *vv;
    unsigned char *pu1, *pu2, *pu3, *pu4;
    unsigned char *pv1, *pv2, *pv3, *pv4;
    unsigned char rValue = 0, gValue = 0, bValue = 0;
    uint16_t* bmpPtr;
    int i, j;
    printf("ConvertRGB5652YUV420SP begin,w=%d,h=%d,bmp=%p,yuv=%p\n", w, h, bmp, yuv);

    struct timeval tpstart,tpend;
    gettimeofday(&tpstart,NULL);

    InitLookupTable();

    gettimeofday(&tpend,NULL);
    float timeuse=1000000*(tpend.tv_sec-tpstart.tv_sec)+tpend.tv_usec-tpstart.tv_usec;
    timeuse/=1000;
    printf("InitLookupTable used time=%f\n", timeuse);
    gettimeofday(&tpstart,NULL);

    uu = new unsigned char[w * h];
    vv = new unsigned char[w * h];
    if (uu == NULL || vv == NULL || yuv == NULL)
        return 0;
    y = yuv;
    u = uu;
    v = vv;
    // Get r,g,b pointers from bmp image data....
    bmpPtr = (uint16_t*)bmp;

    //Get YUV values for rgb values...
    for (i = 0; i < h; i++) {
        for (j = 0; j < w; j++) {
            uint16_t color = *bmpPtr;
            unsigned int r = (color>>11) & 0x1f;
            unsigned int g = (color>> 5) & 0x3f;
            unsigned int b = (color    ) & 0x1f;
            rValue = (r<<3) | (r>>2);      
            gValue = (g<<2) | (g>>4);   
            bValue = (b<<3) | (b>>2);

            *y++ = (RGB2YUV_YR[rValue] + RGB2YUV_YG[gValue] + RGB2YUV_YB[bValue] +
                1048576) >> 16;
            *u++ = (-RGB2YUV_UR[rValue] - RGB2YUV_UG[gValue] + RGB2YUV_UBVR[bValue] +
                8388608) >> 16;
            *v++ = (RGB2YUV_UBVR[rValue] - RGB2YUV_VG[gValue] - RGB2YUV_VB[bValue] +
                8388608) >> 16;
            bmpPtr++;
        }
    }

    gettimeofday(&tpend,NULL);
    timeuse=1000000*(tpend.tv_sec-tpstart.tv_sec)+tpend.tv_usec-tpstart.tv_usec;
    timeuse/=1000;
    printf("Get YUV values used  time=%f\n", timeuse);
    gettimeofday(&tpstart,NULL);

    // Now sample the U & V to obtain YUV 4:2:0 format
    // Get the right pointers...
    u = yuv + w * h;
    v = u + 1;
    // For U
    pu1 = uu;
    pu2 = pu1 + 1;
    pu3 = pu1 + w;
    pu4 = pu3 + 1;
    // For V
    pv1 = vv;
    pv2 = pv1 + 1;
    pv3 = pv1 + w;
    pv4 = pv3 + 1;
    // Do sampling....
    for (i = 0; i < h; i += 2) {
        for (j = 0; j < w; j += 2) {
            *u = (*pu1 + *pu2 + *pu3 + *pu4) >> 2;
            u += 2;
            *v = (*pv1 + *pv2 + *pv3 + *pv4) >> 2;
            v += 2;
            pu1 += 2;
            pu2 += 2;
            pu3 += 2;
            pu4 += 2;
            pv1 += 2;
            pv2 += 2;
            pv3 += 2;
            pv4 += 2;
        }

        pu1 += w;
        pu2 += w;
        pu3 += w;
        pu4 += w;
        pv1 += w;
        pv2 += w;
        pv3 += w;
        pv4 += w;
    }

    gettimeofday(&tpend,NULL);
    timeuse=1000000*(tpend.tv_sec-tpstart.tv_sec)+tpend.tv_usec-tpstart.tv_usec;
    timeuse/=1000;
    printf("Do sampling used time=%f\n", timeuse);
    gettimeofday(&tpstart,NULL);

    delete uu;
    delete vv;
    return 1;
}

int main(int argc, char **argv) {
    unsigned char bmp[640*480*2] = {0};
    unsigned char yuv[(640*480*3)/2] = {0};
    struct timeval tpstart,tpend;
    gettimeofday(&tpstart,NULL);

    ConvertRGB5652YUV420SP(640, 480, bmp, yuv);

    gettimeofday(&tpend,NULL);
    float timeuse=1000000*(tpend.tv_sec-tpstart.tv_sec)+tpend.tv_usec-tpstart.tv_usec;
    timeuse/=1000;
    printf("ConvertARGB2YUV420SP used time=%f\n", timeuse);
    return 0;
}

在 android(armv6) 上输出:

ConvertRGB5652YUV420SP begin,w=640,h=480,bmp=0xbe7314fc,yuv=0xbe7c74fc
InitLookupTable used time=0.383000
Get YUV values used  time=61.394001
Do sampling used time=11.918000
ConvertARGB2YUV420SP used time=74.596001

中央处理器信息:

$ cat /proc/cpuinfo
cat /proc/cpuinfo
Processor       : ARMv6-compatible processor rev 5 (v6l)
BogoMIPS        : 791.34
Features        : swp half thumb fastmult vfp edsp java
CPU implementer : 0x41
CPU architecture: 6TEJ
CPU variant     : 0x1
CPU part        : 0xb36
CPU revision    : 5

Hardware        : IMAPX200
Revision        : 0000
Serial          : 0000000000000000

在 ARMv7 上,使用 NEON。它将在不到 1 毫秒的时间内完成这项工作。 (VGA)

如果您无法使用 ARMv6,请在 ARM 汇编中对其进行优化。 (VGA 上大约 8 毫秒)

使用定点算术而不是查找表。摆脱他们。

制作两个面具:

  • 0x001f001f:掩码1
  • 0x003f003f:掩码2

然后一次将两个像素加载到 32 位寄存器中(这比 16 位读取快得多)

and red, mask1, pixel, lsr #11
and grn, mask2, pixel, lsr #5
and blu, mask1, pixel

现在您有三个寄存器,每个寄存器包含两个值 - 一个位于低位,另一个位于高 16 位。

从现在开始,smulax 指令将会创造一些奇迹。 (16位乘法)

祝你好运。

PS:你的查找表也不是那么好。为什么它们的长度都是256? 您可以将它们减少到 32(r 和 b 相关)和 64(g 相关),这将提高缓存命中率。 也许这将只需要 40 毫秒的目标,而无需求助于组装。 是的,缓存未命中就是那么痛苦。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在Android上更快地将RGB565转换为YUV420SP? 的相关文章

  • 如何从 SDK 实现每个会话的 Google Places 自动完成功能?

    是否可以从 Android 和 iOS 应用程序的 place sdk 实现基于会话的自动完成 根据 6 月 11 日生效的新 Google 地图框架定价 对自动完成的请求可以分为基于击键 会话的请求 我找不到描述实施步骤的文档 除了这个参
  • 按下按钮时应用不同的样式

    有没有办法在按下按钮时将样式应用于按钮 如果我有一种风格样式 xml
  • fetchUuidsWithSdp 的奇怪 UUID 逆转

    我有一个在树莓派上运行的 python 蓝牙服务器 使用 PyBluez 我在服务器中使用的uuid是 8f86d132 4ab8 4c15 b8df 0b70cf10ea56 我正在打电话device fetchUuidsWithSdp
  • 如何在 Linux 内核中定义并触发我自己的新软中断?

    我想在 Linux 内核中创建自己的软中断 这是正确的方法吗 In the init我想触发该模块的softirq我将添加一个调用 394 void open softirq int nr void action struct softir
  • Android WebView里面的ScrollView只滚动scrollview

    在我的应用程序中 我有一个 ScrollView 其中包含一些线性视图 一些文本视图和一个 Webview 然后是其他线性布局等 问题是 WebView 不滚动 Scroll 仅侦听 ScrollView 有什么建议么
  • Android应用程序组件销毁和重新创建的详细信息

    有人可以向我提供一些具体的 值得信赖的 最好是简洁的 信息 内容如下 系统销毁和 如果适用 重新创建组件的顺序 片段 活动 活动的线程 异步任务 计时器 静态数据 类何时卸载 其他类中的线程 异步任务 定时器 主机 TabActivity
  • ExoPlayer2 - 如何使 HTTP 301 重定向工作?

    我开始使用 ExoPlayer 来传输一些音频 一切都很顺利 直到我遇到一个带有 301 永久移动 重定向的 URL ExoPlayer2 默认情况下不处理该问题 我已经看过这个线程 https github com google ExoP
  • 在 android 中建立与 MySQL 的池连接

    我需要从我的 Android 应用程序访问 MySQL 数据库 现在所有的工作都通过 DriverManager getConnection url 等等 但我必须从多个线程访问数据库 所以我必须使用连接池 问题1 是 com mysql
  • Android Eclipse 上的 Web 服务

    我是 android eclipse java 的新手 事实上这个论坛也是如此 有人遇到过这种情况吗 从用户那里获取输入并通过使用 android eclipse 中的 Web 服务来显示适当的结果 有可用的示例吗 非常感谢 我正在发布教程
  • 为什么是 javascript:history.go(-1);无法在移动设备上工作?

    首先 一些背景 我有一个向用户呈现搜索页面 html 表单 的应用程序 填写标准并单击 搜索 按钮后 结果将显示在标准部分下方 在结果列表中 您可以通过单击将您带到新页面的链接来查看单个结果的详细信息 在详细信息页面中 我添加了一个 返回结
  • Android - AudioRecord类不读取数据,audioData和fftArray返回零

    我是 Android 新手 一直在开发音调分析器应用程序 最低 SDK 8 我读了很多关于如何实现 Audiorecord 类的文章 但我想知道为什么它在我录制时不读取任何数据 我尝试显示 audioData 和 fftArray 的值 但
  • WorkManager 或 AlarmManager 用于日常请求然后通知工作?

    这是用例 用户设置具有特定时间的每日通知 在指定时间 发出网络请求以获取一些数据 然后使用检索到的数据显示通知 我不确定是否应该使用 AlarmManager 还是 WorkManager 来实现这个用例 据我了解 AlarmManager
  • OnLongClickListener 不工作

    我有一个ImageView 我需要使用onLongClickListener对于图像视图 当我使用这段代码时 什么也没有发生 Code gallery Gallery findViewById R id gall1 gallery setA
  • Android 中的处理程序与异步调用

    目前我正在使用处理程序来调用 Web 服务方法以使其在后台运行 问题是它需要更多的时间来给出响应 在性能方面似乎更昂贵 现在我计划使用异步调用 哪一个是最好的 Android 中的处理程序和异步调用有什么区别 请帮我想出一个最好的解决方案
  • YUV420和YUV422的区别

    您能帮我了解一下 YUV420 和 YUV422 格式之间的区别吗 我读到了这个 http www fourcc org yuv php http www fourcc org yuv php 但我找不到区别 YUV420 和 YUV420
  • 上网本上可以进行Android开发吗? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我想使用我的上网本进行 Android 开发 但是当我尝试使用 Eclipse 运行 SDK 时 没有加载任何内容 上网本对于 Android 开发来
  • 卡片视图 单击卡片移至新活动

    我是 Android 编程新手 正在研究卡片布局 我想知道如何使其可点击 android clickable true android foreground android attr selectableItemBackground 我的卡
  • 如何检查 Android 中的同步设置

    我正在构建一个 Android 应用程序 我需要检查设备中注册的每个单独帐户的同步设置 我知道我可以通过 ContentResolver 类来做到这一点 但我遇到了一些问题 我已设法获取设备上所有帐户的列表 但我不知道在运行时从哪里获取特定
  • Android:如何从网络异步获取搜索建议?

    我创建了一个可搜索的活动 现在 我想添加从网络服务获取的搜索建议 我想异步获取这些建议 根据添加自定义建议 http developer android com guide topics search adding custom sugge
  • Git 实验分支还是单独的实验存储库?

    我正在开发一个 Android 应用程序 并且在整个开发周期中一直使用 Git 现在 我想构建并发布实验性功能 供人们尝试和安装 同时仍将原始的 稳定的应用程序安装在他们的设备上 现在 这意味着我需要使用不同的包名称 这会更改开发项目中的一

随机推荐

  • 如何在golang中编写bson形式的mongo查询?

    我可以使用命令行查询查询我的 mongodb 集合 以根据 nfType 和最小距离获取 ipv4Addresses db nfinstancesdb aggregate match nfType AMF unwind ipv4Addres
  • 如何解密MySQL密码

    创建我公司使用的平台的开发人员不再为我们工作 我不知道如何从自定义 PHP 应用程序检索密码 当我查看 PHPmyAdmin 时 密码已加密 例如 2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 我如何更改
  • 如何禁用布局中的所有按钮?

    应用程序的工作方式如下 应用程序向用户提示 30 个按钮 用户可以通过点击猜出正确的按钮 当用户点击某个按钮时 所有按钮 例如包含这些按钮的视图 都应该被锁定 同时播放相应的 正确或错误的猜测 动画 点击的按钮本身应该被禁用 直到下一轮 动
  • 停止 Chrome 标签页睡眠/休眠

    如何阻止 Chrome 的选项卡睡眠 休眠 我正在运行 左轮手枪 扩展 我希望在循环之前重新加载选项卡 但是 chrome 的选项卡似乎处于休眠状态 因此在选项卡处于 活动 状态之前不会重新加载 并且显示 有解决方法吗 来自 wOxxOm
  • ember-data DS.RESTAdapter 导致 TypeError

    我正在尝试使用 Ember js 和 ember data 并且定义了以下应用程序 window App Ember Application create App store DS Store create revision 4 adapt
  • Django - {% csrf_token %} 在模板中使用,但上下文未提供值

    我是 Django 的新手 我仍在尝试掌握它的功能 我创建了非常简单的项目姜戈 1 4 2它有简单形式的索引页面 您可以在其中输入内容 还有结果页面 您的输入在提交后显示 代码如下 提交后 我收到错误 403 和以下消息 模板中使用了 cs
  • shell: /bin/bash -e {0} 在 github Action Worker 的 bash shell 输出中意味着什么?

    因为当没有要提交的更改时 git 会使用非零代码提交退出 这会导致 github 操作失败 为了克服这个问题 我尝试在提交之前检查是否有任何更改 如下所示 if git diff index quiet HEAD then echo cha
  • C++读取wav文件,subchunk1size = 18

    通常 wav 文件的 subchunk1size 是 16 但是 我有一些 subchunk1size 18 的 wav 文件 我有 C 代码来读取 subchunk1size 16 的 wav 文件 现在我想读取 subchunk1siz
  • iOS 6 旋转问题 - 呈现的模态视图控制器没有旋转

    我有一个 MainViewController 它有一个按钮 可以通过水平翻转推送新视图 InfoViewController 像这样 controller modalTransitionStyle UIModalTransitionSty
  • 构建动态 where 子句,Linq To Sql

    我使用的是 EF Code First 4 2 当需要动态构建 where 子句时 您提出什么样的解决方案 然而 非常需要包含功能 var results db Set
  • 使用 rsync 仅同步修改过的文件

    我正在尝试同步两个文件夹 developer and shared 在Ubuntu中 当我修改文件时 shared 我希望能够将文件复制到 developer folder I tried rsync r shared developer
  • 在Android中使用BI LSTM CTC Tensorflow模型

    TL DR 我想知道如何在 Android 应用程序中使用 bi lstm ctc 张量流模型 我已经成功训练了我的 bi lstm ctc 张量流模型 现在我想将它用于我的手写识别 Android 应用程序 这是定义我使用的图表的代码部分
  • “JSON.stringify”中的“符号键控”是什么意思

    有一个Node js生成的Object 当我使用时它看起来像这样console log dataValues a 1 b 2 fn1 function fn2 function 当我使用JSON stringify 它返回这个字符串 a 1
  • 用小数字代替零?

    我一直在制作一个矩阵类 作为学习练习 并且在测试我的反函数时遇到并发出问题 我输入一个任意矩阵 2 1 1 1 2 1 1 1 2 并让它计算逆 我得到了正确的结果 0 75 0 25 0 25 0 25 0 75 0 25 0 25 0
  • 将 HTML 转换为 PDF - 任何 ASP.net 库 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • SerialPort.Open() 抛出 IOException - 系统资源不足,无法完成请求的服务

    我编写了一个 NET 4 Windows 服务 该服务定期 通常每天一次 通过串行端口与外部设备进行通信 总而言之 服务效果很好 但对于一位客户来说 时不时地打电话给SerialPort Open 抛出以下异常 System IO IOEx
  • iPhone 分布:当前没有匹配的配置文件

    我即将将应用程序上传到 iTunes Connect 我不是团队代理 团队代理似乎也不能让我成为团队代理 于是他登录会员中心并下载了分发证书 该证书与 WWDR 证书一起位于我的钥匙串中 捆绑包标识符设置为 se companyname a
  • C++ 和 UTF8 - 为什么不直接替换 ASCII?

    在我的应用程序中 我必须不断地在之间转换字符串std string and std wstring由于不同的 API boost win32 ffmpeg 等 特别是对于 ffmpeg 字符串以 utf8 gt utf16 gt utf8
  • 我想使用并行 ssh 在多个服务器上运行 bash 脚本,但它简单地打印 echo 语句

    我有一个名为的 bash 脚本sr run batch sh它可以实现图像的超分辨率 现在我想同时在不同的服务器上并行进行测试 IE 1 个给定时间点的虚拟机 然后在某个时间点有 2 个虚拟机 然后是 3 个 然后是 4 个 我尝试将命令写
  • 如何在Android上更快地将RGB565转换为YUV420SP?

    我需要显示一张jpeg图片 并将其转换为YUV420SP 首先我使用SkBitmap解析jpeg并显示它 然后我使用下面的代码在android上将RGB565转换为YUV420SP 但是转换640 480 RGB565图片花费了75ms 所