如何在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? 的相关文章

  • appcompat_v7 错误

    我发现材料支持库 更新的 appcompat v7 将于 10 月 17 日推出 http www reddit com r androiddev comments 2jd5gl roman nurik material support l
  • 无法运行 android/sdk/build-tools/23.0.2/aapt

    最近在 Ubuntu 15 上安装了 Android Studio 1 0 1 由于某些原因是旧版本 我正在尝试创建一个新项目 每当我构建它时 我都会收到此错误 无法运行程序 home user Android Sdk build tool
  • Android SSL 无对等证书

    我有一个例外 没有同行证书 当我询问谷歌时 我得到了解决方案 我信任所有证书 但这个问题的答案是 它是不安全的 所以我给班级打电话 HostnameVerifier hostnameVerifier org apache http conn
  • MaterialComponents AlertDialog 文本颜色

    Reading MaterialComponents 主题警报对话框按钮 https stackoverflow com questions 52829954 materialcomponents theme alert dialog bu
  • Flutter - 当用户移动到其他(预览)屏幕时如何正确暂停相机?

    我需要pause当我移动到导航树上的另一个屏幕以节省电池和性能时相机 我尝试过了dispose cameraController 但 flutter 从另一个屏幕返回时不会重新初始化状态 但这很明显 我使用相机的主要代码 override
  • RecyclerView.OnScrollListener:一次滚动实例被多次调用

    我有一个水平布局的回收视图 一次只有一个视图可见 mRecyclerView findViewById R id rvmain mRecyclerView setOnFlingListener null final SnapHelper s
  • 如何在datepickerdialog android中选择年份?

    我是 Android 编程新手 请帮忙 我正在使用创建材料设计的片段DatePickerDialog点击EditText 问题是它设置为当前日期 由我设置 但是 如果用户必须选择过去的日期 比如说 10 年前 用户必须每月滚动 这是痛苦的
  • Android、AdMob:AdMob 广告刷新会破坏帧速率

    我正在开发一款游戏 并且进展顺利 不过 我确实对 AdMob 广告刷新有一些疑问 每次刷新广告或绘制广告的不同方面时 我的帧速率都会急剧下降 几乎使游戏无法玩 这是我用于加载广告的内容 ad new AdView this AdSize B
  • 我应该保留远程数据库的本地副本吗?

    我正在开发一个应用程序 基本上允许人们创建 加入和管理其他人的群组 群组内的人也可以互相发送消息 我一直在想哪条路会更好 保留包含所有信息的远程数据库 包括发送给用户和从用户发送的消息 并让应用程序在每次需要信息时查询服务器 甚至是它以前见
  • 动画图像视图

    目前我正在开发一款游戏 这是我的游戏的详细信息 用户应选择正确的图像对象 我希望图像从左到右加速 当他们到达终点时 他们应该再次出现在活动中 这是我正在处理的屏幕截图 我有 5 个图像视图 它们应该会加速 您有此类动画的示例代码吗 非常感谢
  • sqlite 插入表中 select * from

    我需要在 Android 应用程序中将数据从一个表移动到另一个表 我想使用以下sql insert into MYTABLE2 select id STATUS risposta DATETIME now data ins from MYT
  • 从 DecorView@2da7146[MyActivity] 中找不到 ViewTreeLifecycleOwner

    从撰写更新后alpha 11 to alpha 12 or beta 01 每当我打开具有撰写视图的活动或片段时 我都会遇到此崩溃 我在用AppCompatActivity它实现了LifecycleOwner 所以这非常奇怪 java la
  • Android 6.0 缺乏访问相机服务的权限

    我在 Android 6 0 中使用 Camera2API 我在Android 5 0中没有报错 然而 当我在 Android 6 0 中使用我的代码时 我遇到了问题 问题是有时我可以成功打开相机并拍照 但有时相机打不开 出现错误 java
  • 如何将txt文件添加到你的android项目中? [复制]

    这个问题在这里已经有答案了 我的Android studio版本是1 5 1 显然这个 never 版本没有 txt 文件的 asset 文件夹 您打算如何将这些文件包含到您的项目中 以及如何进一步使用您内部的应用程序 谢谢你的建议 Pro
  • 错误:包 com.google.android.gms.appstate 不存在

    由于此错误 无法编译我的 android 项目 BaseGameUtils src main java com google example games basegameutils GameHelper java Error 32 39 e
  • ViewPager 的 Android Viewholder

    您好 我正在使用 ViewPager 但我现在想保留状态 而不是重新生成单元格 我注意到 viewpager 与 listviews 的自定义适配器非常相似 它们的功能类似 listview 在单元格不再出现在屏幕上后重新生成单元格中的数据
  • 膨胀类片段 InflateException 二进制 XML 文件时出错

    我正在使用 Material Design 和 NavigationDrawer 布局等设计我的第一个应用程序 但我遇到了一个问题 该应用程序非常简单 它只显示文本 并且基于 Android Studio 中提供的模板 尝试启动我的应用程序
  • 无法仅在控制台中启动 androidstudio

    你好 我的问题是下一个 我下载了Android Studio如果我去 路径 android studio bin 我执行studio sh 我收到以下错误 No JDK found Please validate either STUDIO
  • Android:毫米或英寸尺寸的视图尺寸不正确

    我有一个布局高度为 10mm 的按钮 在大多数设备上看起来都是正确的 但在 Lg Optimus 2X 和 Motorola Defy 上 按钮的尺寸大约只有一半 我检索了这些设备上的 DisplayMetrics 信息 这是一个简短的概述
  • Eclipse:缺少 Java 构建路径

    我正在尝试使用 Eclipse 来使用适用于 Android 的 Google SDK 教程 我能够让前两个项目正常工作 但是当运行第三个 R java 时消失了 所以我放弃了 我根据练习 3 的解决方案集制作了一个全新的包 它充满了错误

随机推荐

  • 如何在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 所