在最近的一个项目中,需要实现 Mac OS X 环境下的摄像头图像实时捕获并转换为 Java 中的 BufferedImage 对象。首先通过开发一个本地库实现 Mac OS X 的摄像头图像捕获,采用的是 Apple 推荐的新的 AVFoundation 框架,摄像头图像格式设置为 kCVPixelFormatType_32ARGB(设置成其他的测试了无法得到图像,系统不支持),通过 delegate 方式得到 CMSampleBufferRef 类型的 sample buffer 后,需要通过 CMSampleBufferGetImageBuffer 函数将其转换为 CVImageBufferRef 类型的图像缓冲(因为这里捕获的是图像数据,并不是采样数据,所以不能用 CMSampleBufferGetDataBuffer)。然后通过 CVPixelBufferGetBaseAddress 函数得到图像缓冲的首地址,用 CVPixelBufferGetDataSize 函数得到图像缓冲区数据大小,但这里千万要注意,不要以为这时获取的图像缓冲区数据就可以通过Java 的 Raster 和 DataBuffer 等方式来直接填充 Java 中的 BufferedImage(这里假定 BufferedImage 采用 TYPE_INT_ARGB,因为想着对应 kCVPixelFormatType_32ARGB)。因为这么做了会发现图像颜色完全是错乱的,事实上,我们通过计算就可以知道,对应高、宽下的 TYPE_INT_ARGB 格式的 BufferedImage 图像数据大小为 width × height × 4 字节(因为这时一个像素为 int 类型,4 字节大小),但 CVPixelBufferGetDataSize 得到的图像数据大小总比前者要多 4 个字节,可能是保存了其他的一些信息。所以这里直接创建 TYPE_INT_ARGB 格式的 BufferedImage 然后用 Raster 以及 DataBuffer 等方式进行填充是行不通的。

这里就需要采取另外的方式,用 DataBufferByte、ComponentSampleModel、WritableRaster、ColorSpace、ColorModel 来构建 BufferedImage,其实也是使用了 BufferedImage 的另一种不常用的、但效率非常高的构造函数模式。当然,前提是还需要通过 CVPixelBufferGetBytesPerRow 函数得到图像中每个扫描行的字节数,通过 CVPixelBufferGetHeight 函数得到图像的高度,通过 CVPixelBufferGetWidth 函数得到图像的宽度,后面会用得上。具体如以下代码:

 DataBufferByte dataBufferByte = new DataBufferByte(new byte[][] {dataBytes}, dataSize); // 这里假定 dataBytes 保存了本地获取的图像数据,dataSize 为图像数据大小(总是比“w * h * 每像素字节数”计算出来要大一点)
ComponentSampleModel componentSampleModel = new ComponentSampleModel(DataBuffer.TYPE_BYTE, width, height, 4, bytesPerRow, new int[] {1, 2, 3, 0}); // 自定义 BufferedImage 中的图像格式,还是以字节来存储每个像素,具体构造函数的说明见 javadoc api
WritableRaster writableRaster = Raster.createWritableRaster(componentSampleModel, dataBufferByte, new Point(0, 0)); // 创建包含具体图像数据的栅格阵列
ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB); // 创建 RGB 颜色空间
int[] nBits = {8, 8, 8, 8}; // 对应源图像数据的 ARGB,因为源图像数据采用 32ARGB,等效于 4 个字节,每个字节按顺序分别表示 alpha、red、green、blue
ColorModel colorModel = new ComponentColorModel(colorSpace, nBits, true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE); // 创建颜色模式
BufferedImage bufferedImage = new BufferedImage(colorModel, writableRaster, false, null); // 构建自定义像素格式的 BufferedImage

这种方式就不会出现问题了,本地库捕获的实时摄像头图像能够正确填充到 Java 的 BufferedImage 中,而且效率非常高。

基于现有图像数据创建自定义像素格式的 BufferedImage的更多相关文章

  1. NumPy 基于已有数据创建数组

    原文:Python Numpy 教程 章节 Numpy 介绍 Numpy 安装 NumPy ndarray NumPy 数据类型 NumPy 数组创建 NumPy 基于已有数据创建数组 NumPy 基 ...

  2. .Net Core WebApi返回的json数据,自定义日期格式

    基本上所有的人都在DateTime类型的字段,被序列化成json的时候,遇到过可恨的Date(1294499956278+0800):但是又苦于不能全局格式化设置,比较难受.以往的方式,要么使用全局的 ...

  3. ASP.Net Core 返回的json数据,自定义日期格式

    //代码位置:Startup.cs public void ConfigureServices(IServiceCollection services) { services.AddMvc() .Ad ...

  4. CAFFE学习笔记(四)将自己的jpg数据转成lmdb格式

    1 引言 1-1 以example_mnist为例,如何加载属于自己的测试集? 首先抛出一个问题:在example_mnist这个例子中,测试集是人家给好了的.那么如果我们想自己试着手写几个数字然后验 ...

  5. Excel 2007中自定义数字格式前要了解的准则

    要在Excel 2007中创建自定义数字格式,首先应了解自定义数字格式的准则,并从选择某一内置数字格式开始.然后,可以更改该格式的任意代码部分,从而创建自己的自定义数字格式. 数字格式最多可包含四个代 ...

  6. .net下灰度模式图像在创建Graphics时出现:无法从带有索引像素格式的图像创建graphics对象 问题的解决方案。

    在.net下,如果你加载了一副8位的灰度图像,然后想向其中绘制一些线条.或者填充一些矩形.椭圆等,都需要通过Grahpics.FromImage创建Grahphics对象,而此时会出现:无法从带有索引 ...

  7. 无法从带有索引像素格式的图像创建graphics对象(转)

    大家在用 .NET 做图片水印功能的时候, 很可能会遇到 “无法从带有索引像素格式的图像创建graphics对象”这个错误,对应的英文错误提示是“A Graphics object cannot be ...

  8. 无法从带有索引像素格式的图像创建graphics对象

    大家在用 .NET 做图片水印功能的时候, 很可能会遇到 “无法从带有索引像素格式的图像创建graphics对象”这个错误,对应的英文错误提示是“A Graphics object cannot be ...

  9. .Net给图片加水印,并解决“无法从带有索引像素格式的图像创建Graphics对象”问题

    using (Image img = Image.FromFile(savePath)) { //如果原图片是索引像素格式之列的,则需要转换 if (img.PixelFormat!=null) { ...

随机推荐

  1. 基于Inception搭建MySQL SQL审核平台Yearing

    基于Inception搭建MySQL SQL审核平台Yearing Inception 1. Inceptionj简介 2. Inception安装 2.1 下载和编译 2.2 启动配置 Yearni ...

  2. 【Redis】DENIED Redis is running in protected mode

    .修改redis服务器的配置文件 vi redis.conf 注释以下绑定的主机地址 # bind 127.0.0.1 .修改redis服务器的参数配置 修改redis的守护进程为no ,不启用 &g ...

  3. Django 惰性机制

    惰性机制:Publisher.objects.all()或者.filter()等都只是返回了一个QuerySet(查询结果集对象),它并不会马上执行sql,而是当调用QuerySet的时候才执行sql ...

  4. Python 简单购物程序

    # Author:Eric Zhao# -*- coding:utf-8 -*-'''需求:启动程序后,让用户输入工资,然后打印商品列表允许用户根据商品编号购买商品用户选择商品后,检测余额是否够,够就 ...

  5. Cplex: MIP Control Callback

    *本文主要记录和分享学习到的知识,算不上原创 *参考文献见链接 之前,我们有简单提到Cplex中的MIP Callback Interface,包括了Informational callback, q ...

  6. Sublime插件开发——简单的代码模板插件

    最近一段一直使用sublime进行golang开发,整体感觉很不错,虽然比不上eclipse之类IDE强大,但是用起来很轻巧便捷,开发golang完全做够了.由于有一部分代码复用率很高,经常要用到,而 ...

  7. 不可取代的网站开发工具---------dreamweaver

    现在web开发的工具越来越多,sublime text,webstorm等web开发工具日益崛起,一直威胁着当年网页三剑客之一的dreamweaver工具的地位,然而dreamweaver却是无法取代 ...

  8. webdriver高级应用- 高亮显示正在操作的页面元素

    #encoding=utf-8 import unittest from selenium import webdriver import time def highLightElement(driv ...

  9. Django--------问题:在terminal命令行创建超级用户时入到password时输入为什么没有反应?

    首先如果遇到这样的问题不用担心,一般一会儿就可以解决: 其实,输入的时候并不是没有反应,只是你输入的时候命令行没有将你的输入显示出来,关键是输入行对Password:********也不是采用这种方式 ...

  10. Wannafly模拟赛3

    喜欢想飞啊,毕竟这里的题目还都算挺好的中文题,不过做英文题久了还是感觉英文题更好理解一点 反蝴蝶效应 时间限制:1秒 空间限制:65536K 题目描述 一只南美洲亚马孙河流域热带雨林中的蝴蝶,偶尔扇动 ...