菜鸟教程小白 发表于 2022-12-13 15:38:54

objective-c - 将 UIImage(或 JPEG)绘制到 EAGLView


                                            <p><p>我正在制作 PDF 注释器,当您切换页面时,它必须重绘所有之前绘制的 OpenGL 内容(以 JSON 格式保存到文件中)。问题是绘制的内容越多,需要的时间就越长。我为每个页面都保存了一个 UIImage 到磁盘,所以我希望通过将 UIImage 一次性绘制到 EAGLContext 上来加快这个过程。</p>

<p>我想知道如何获取 UIImage(或 JPEG/PNG 文件)并将其直接绘制到屏幕上。它必须在 EAGLView 上的原因是因为它需要支持橡皮擦,而使用常规的 UIKit 方式将无法使用它。 </p>

<p>我认为有某种方法可以将画笔设置为整个图像,然后在屏幕上标记一次。有什么建议吗?</p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>作为迂腐的注释,<a href="https://stackoverflow.com/questions/8412302/whats-the-difference-between-glkview-and-eaglview/8438138#8438138" rel="noreferrer noopener nofollow">there is no standard class named EAGLView</a> ,但我假设您指的是承载 OpenGL ES 内容的 Apple 示例 UIView 子类之一。</p>

<p>执行此操作的第一步是将 UIImage 加载到纹理中。以下是我在图像处理框架中使用的一些代码(<code>newImageSource</code> 是输入 UIImage):</p>

<pre><code>CGSize pointSizeOfImage = ;
CGFloat scaleOfImage = ;
pixelSizeOfImage = CGSizeMake(scaleOfImage * pointSizeOfImage.width, scaleOfImage * pointSizeOfImage.height);
CGSize pixelSizeToUseForTexture = pixelSizeOfImage;

BOOL shouldRedrawUsingCoreGraphics = YES;

// For now, deal with images larger than the maximum texture size by resizing to be within that limit
CGSize scaledImageSizeToFitOnGPU = ;
if (!CGSizeEqualToSize(scaledImageSizeToFitOnGPU, pixelSizeOfImage))
{
    pixelSizeOfImage = scaledImageSizeToFitOnGPU;
    pixelSizeToUseForTexture = pixelSizeOfImage;
    shouldRedrawUsingCoreGraphics = YES;
}

if (self.shouldSmoothlyScaleOutput)
{
    // In order to use mipmaps, you need to provide power-of-two textures, so convert to the next largest power of two and stretch to fill
    CGFloat powerClosestToWidth = ceil(log2(pixelSizeOfImage.width));
    CGFloat powerClosestToHeight = ceil(log2(pixelSizeOfImage.height));

    pixelSizeToUseForTexture = CGSizeMake(pow(2.0, powerClosestToWidth), pow(2.0, powerClosestToHeight));

    shouldRedrawUsingCoreGraphics = YES;
}

GLubyte *imageData = NULL;
CFDataRef dataFromImageDataProvider;

if (shouldRedrawUsingCoreGraphics)
{
    // For resized image, redraw
    imageData = (GLubyte *) calloc(1, (int)pixelSizeToUseForTexture.width * (int)pixelSizeToUseForTexture.height * 4);

    CGColorSpaceRef genericRGBColorspace = CGColorSpaceCreateDeviceRGB();   
    CGContextRef imageContext = CGBitmapContextCreate(imageData, (int)pixelSizeToUseForTexture.width, (int)pixelSizeToUseForTexture.height, 8, (int)pixelSizeToUseForTexture.width * 4, genericRGBColorspace,kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
    CGContextDrawImage(imageContext, CGRectMake(0.0, 0.0, pixelSizeToUseForTexture.width, pixelSizeToUseForTexture.height), );
    CGContextRelease(imageContext);
    CGColorSpaceRelease(genericRGBColorspace);
}
else
{
    // Access the raw image bytes directly
    dataFromImageDataProvider = CGDataProviderCopyData(CGImageGetDataProvider());
    imageData = (GLubyte *)CFDataGetBytePtr(dataFromImageDataProvider);
}   

glBindTexture(GL_TEXTURE_2D, outputTexture);
if (self.shouldSmoothlyScaleOutput)
{
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (int)pixelSizeToUseForTexture.width, (int)pixelSizeToUseForTexture.height, 0, GL_BGRA, GL_UNSIGNED_BYTE, imageData);

if (self.shouldSmoothlyScaleOutput)
{
    glGenerateMipmap(GL_TEXTURE_2D);
}

if (shouldRedrawUsingCoreGraphics)
{
    free(imageData);
}
else
{
    CFRelease(dataFromImageDataProvider);
}
</code></pre>

<p>如你所见,它有一些函数可以调整超过设备最大纹理大小的图像大小(上面代码中的类方法只是查询最大纹理大小),以及一个 bool 标志是否为纹理生成 mipmap 以实现更平滑的下采样。如果您不关心这些情况,可以将其删除。这也是 OpenGL ES 2.0 代码,因此您可能需要将一两个 <code>OES</code> 后缀添加到上述某些函数中,以便它们与 1.1 一起使用。</p>

<p>在纹理中拥有 UIImage 后,您可以使用带纹理的四边形(两个三角形组成一个矩形,边角具有适当的纹理坐标)将其绘制到屏幕上。 OpenGL ES 1.1 和 2.0 之间的操作方式会有所不同。对于 2.0,您使用直通着色器程序,该程序仅从纹理中的该位置读取颜色并将其绘制到屏幕上;对于 1.1,您只需为几何体设置纹理坐标并绘制两个三角形。</p>

<p>我在 <a href="https://stackoverflow.com/questions/4036737/how-to-draw-a-texture-as-a-2d-background-in-opengl-es-2-0/4227878#4227878" rel="noreferrer noopener nofollow">this answer</a> 中有一些 OpenGL ES 2.0 代码。 .</p></p>
                                   
                                                <p style="font-size: 20px;">关于objective-c - 将 UIImage(或 JPEG)绘制到 EAGLView,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/11958037/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/11958037/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: objective-c - 将 UIImage(或 JPEG)绘制到 EAGLView