- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
(更新如下...)
OpenGL Cocoa/OSX 桌面应用程序面向 10.8+
我遇到这样的情况:每帧接收一次 NSImage 对象,并希望将其转换为 openGL 纹理(它是来自 IPCamera 的视频帧)。从SO和互联网上,我能找到的将 NSImage 转换为 glTexture 的最有用的实用方法是下面的代码。
虽然这对于偶尔(IE 加载)的情况来说很好,但它会消耗大量的性能,并且每帧运行一次会很糟糕。我已经分析了代码并将瓶颈缩小到两个调用。这些调用加在一起几乎占了整个应用程序运行时间的三分之二。
位图准备创建
NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithData:[inputImage TIFFRepresentation]];
认为问题可能出在我获取位图的方式上,并且因为我听说过 TIFFRepresentation 的性能方面的不好的事情,所以我尝试了这个,这确实更快,但只有一点点,并且还引入了一些奇怪的东西变色(一切看起来都是红色的):
NSRect rect = NSMakeRect(0, 0, inputImage.size.width, inputImage.size.height);
CGImageRef cgImage = [inputImage CGImageForProposedRect:&rect context:[NSGraphicsContext currentContext] hints:nil];
NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithCGImage:cgImage];
glTexImage2D 调用(我不知道如何改进。)
如何使下面的方法更有效?
或者,告诉我我做错了,我应该看看其他地方?这些帧以 MJPEG 格式传入,因此我可以在将 NSData 转换为 NSImage 之前使用它。然而,它是 jpeg 编码的,所以我必须处理它。我实际上还想要 NSImage 对象作为应用程序的另一部分。
-(void)loadNSImage:(NSImage*)inputImage intoTexture:(GLuint)glTexture{
// If we are passed an empty image, just quit
if (inputImage == nil){
//NSLog(@"LOADTEXTUREFROMNSIMAGE: Error: you called me with an empty image!");
return;
}
// We need to save and restore the pixel state
[self GLpushPixelState];
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, glTexture);
// Aquire and flip the data
NSSize imageSize = inputImage.size;
if (![inputImage isFlipped]) {
NSImage *drawImage = [[NSImage alloc] initWithSize:imageSize];
NSAffineTransform *transform = [NSAffineTransform transform];
[drawImage lockFocus];
[transform translateXBy:0 yBy:imageSize.height];
[transform scaleXBy:1 yBy:-1];
[transform concat];
[inputImage drawAtPoint:NSZeroPoint
fromRect:(NSRect){NSZeroPoint, imageSize}
operation:NSCompositeCopy
fraction:1];
[drawImage unlockFocus];
inputImage = drawImage;
}
NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithData:[inputImage TIFFRepresentation]];
// Now make a texture out of the bitmap data
// Set proper unpacking row length for bitmap.
glPixelStorei(GL_UNPACK_ROW_LENGTH, (GLint)[bitmap pixelsWide]);
// Set byte aligned unpacking (needed for 3 byte per pixel bitmaps).
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
NSInteger samplesPerPixel = [bitmap samplesPerPixel];
// Nonplanar, RGB 24 bit bitmap, or RGBA 32 bit bitmap.
if(![bitmap isPlanar] && (samplesPerPixel == 3 || samplesPerPixel == 4)) {
// Create one OpenGL texture
// FIXME: Very slow
glTexImage2D(GL_TEXTURE_2D, 0,
GL_RGBA,//samplesPerPixel == 4 ? GL_RGBA8 : GL_RGB8,
(GLint)[bitmap pixelsWide],
(GLint)[bitmap pixelsHigh],
0,
GL_RGBA,//samplesPerPixel == 4 ? GL_RGBA : GL_RGB,
GL_UNSIGNED_BYTE,
[bitmap bitmapData]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
}else{
[[NSException exceptionWithName:@"ImageFormat" reason:@"Unsupported image format" userInfo:nil] raise];
}
[self GLpopPixelState];
}
根据下面 Brad 的评论,我决定考虑简单地绕过 NSImage。在我的特定情况下,我能够在将 JPG 数据转换为 NSImage 之前将其作为 NSData 对象访问,因此效果很好:
[NSBitmapImageRep imageRepWithData: imgData];
使用与上面大致相同的方法,但直接从位图代表开始,CPU 使用率从 80% 下降到 20%,我对速度感到满意。我有一个适合我的 ap 的解决方案。
我仍然想知道我原来的问题是否有答案,或者最好将其作为要避免的事情的实例教训。最后,我仍然想知道是否可以改善 glTexImage2D 调用的加载时间 - 尽管现在已经在合理范围内,但它仍然占用了该方法 99% 的负载(但也许这没关系。)
==========
最佳答案
根据数据的传入方式,您可以使用像素缓冲区对象 (PBO),它将在上传纹理时使用 DMA(避免 CPU),而将使用 memcpy 复制随机指针(使用 CPU )。
Apple 在此描述如何执行此操作:https://developer.apple.com/library/mac/documentation/graphicsimaging/conceptual/opengl-macprogguide/opengl_texturedata/opengl_texturedata.html
基本上,PBO 为您提供了 OpenGL 可以 DMA 的内存块,因此使用它来分配将解压缩帧复制到其中的内存,然后通过绑定(bind)缓冲区并以 nil 作为内存引用调用 glTexSubImage2D 来进行绘制。
这确实依赖于您能够将传入数据直接传入 PBO - 否则您仍然需要 memcpy 到 PBO,从而失去它可能带来的任何好处。
关于image - 从 NSImage 转换 glTexture 的最有效方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22761467/
我有一个矩形 NSImage A,我想缩放以嵌入到方形透明图像 B 中,保持 A 的比例。所以,最后我会得到一个带有矩形的方形图像。 我该如何构图?我的意思是,如何在另一个 NSImage 上绘制一个
我有一堆 NSImages,我将它们保存在 PDFDocument 中,作为 PDFPages。当我第一次插入 NSImage 时,NSImage 的大小以点 (72 dpi) 为单位,而(仅)NSI
我试图理解为什么 var tmp: Any = NSImage(byReferencingFile: somePath) var img: NSImage = tmp as NSImage 不会工作并
好吧,我很困惑,因为这应该很简单。 在 Xcode 5 中,我开始了一个新的 iphone 项目。在 ViewDidLoad 中,我开始输入: NSImage *图像 ... 实际上在“NSI”点……
我正在尝试将文件从 xcassets 加载到 NSImage,其中 Assets 名称是 Logo 。 我试过这个: let logoIcon = NSImage(named: "logo") 但我一
我正在编写一个简单的 MacRuby 应用程序。我有一个 NSView,它在调用 drawRect() 时在自身内部绘制图像。 在那个 NSView 子类中,我的 drawRect() 有(以及其他一
所以我有一个 NSImage *startingImage 它由带有灰色色彩空间的 NSBitmapImageRep 表示 我需要反转它的颜色,因此我将其转换为 CIImage CIImage *
首先,我知道我不应该使用 SQLite 数据库来存储图像,但我只存储非常小的网站图标。 我的问题是我尝试将这些图标插入数据库(似乎有效),我将图标转换为 NSData与 -tiffrepresenta
我正在尝试制作一个简单的基于文档的 cocoa 应用程序,可以在 pdf 文件中保存和加载图像。 对于保存部分,我正在使用 - (NSData *)dataOfType:(NSString *)typ
我使用 NSAffineTransform 类在其中心旋转了 NSImage,它可以工作。代码在这里: - (NSImage*)rotateImage: (NSImage*)myImage angle
我是 cocoa 和编程的新手,如果这是基本的东西,我很抱歉。 我正在使用 ARC。我有一个 NSImageView 组件,它由 DropZone 类控制。我将图像拖放到其中,但是一旦我尝试调用我得到
我想创建 NSScrollView 对象的 NSImage,这样我就可以将平面图形用于动画目的。 当我将 ScrollView 对象渲染为图形并将其添加回我的窗口时,它可以工作,但看起来非常糟糕,就像
到目前为止,我已经构建了一个应用程序,允许用户将图像拖放到 NSImageView 上。但是,我希望能够通过简单地单击任何图像并按住鼠标按钮来移动其位置来移动这些图像。 设置图像后如何操作 NSIma
我正在尝试打印 NSImage,但无法将其调整为正确的尺寸。我希望 NSImage 在任何足够大的纸张上打印为 4"x6"照片。这是我现在的代码。 var printView = NSImageVie
这可能是一个新问题,但我无法理解如何操作 NSImage 实例。 我正在尝试创建一个方法,该方法将采用 NSImage (一个图标),在其上绘制另一个 NSImage (复选标记),然后返回修改后的
由于 Cocoa-Java 已弃用,我正在将 Cocoa-Java 代码迁移到 Cocoa + JNI。该代码打印存储在文件中的图像。新的 Cocoa 代码基本上是: NSImage *image =
我正在尝试设置一个自定义拖动图标以在 NSTableView 中使用。一切似乎都正常,但由于我对 Quartz 缺乏经验,我遇到了问题。 - (NSImage *)dragImageForRowsWi
我有许多 NSImage,正在自定义 NSView 子类中渲染。当用户将鼠标放在这些图像上时,我希望放大这些图像,并且想知道执行此操作的最佳方法。 目前我正在使用 NSView 的 drawRect:
我的程序中有一个大型一维动态数组,它表示磁盘上的 FITS 图像,即它保存图像的所有像素值。数组的类型是double。目前,我只关心单色图像。 由于 Cocoa 不直接支持 FITS 格式,因此我使用
我想获取 NSImage.h 中定义的常量的图像文件,例如 NSImageNameGoRightTemplate 。我想复制并编辑其中一些。有谁知道这些图像位于哪里?我太笨了,在驱动器上找不到它们..
我是一名优秀的程序员,十分优秀!