如何编译vImage浮雕效果示例代码?

Posted

技术标签:

【中文标题】如何编译vImage浮雕效果示例代码?【英文标题】:How to compile vImage emboss effect sample code? 【发布时间】:2013-09-15 11:08:14 【问题描述】:

这是documentation中的代码:

int myEmboss(void *inData,
unsigned int inRowBytes,
void *outData,
unsigned int outRowBytes,
unsigned int height,
unsigned int width,
void *kernel,
unsigned int kernel_height,
unsigned int kernel_width,
int divisor ,
vImage_Flags flags ) 
   uint_8 kernel = -2, -2, 0, -2, 6, 0, 0, 0, 0; // 1
   vImage_Buffer src =  inData, height, width, inRowBytes ; // 2
   vImage_Buffer dest =  outData, height, width, outRowBytes ; // 3
   unsigned char bgColor[4] =  0, 0, 0, 0 ; // 4
   vImage_Error err; // 5
   err = vImageConvolve_ARGB8888(    &src,     //const vImage_Buffer *src
                                     &dest,    //const vImage_Buffer *dest,
                                      NULL,
                                      0,    //unsigned int srcOffsetToROI_X,
                                      0,    //unsigned int srcOffsetToROI_Y,
                                      kernel,    //const signed int *kernel,
                                      kernel_height,     //unsigned int
                                      kernel_width,    //unsigned int
                                      divisor,    //int
                                      bgColor,
                                      flags | kvImageBackgroundColorFill
                                      //vImage_Flags flags
                                    );


   return err;

问题来了:内核变量似乎指的是三种不同的类型:

    形参列表中的void * kernel 一个未定义的 unsigned int uint_8 内核,作为一个可能会影响形参的新变量 调用 vImageConvolve_ARGB8888 时为 const signed int *kernel。

这是实际代码吗?我该如何编译这个函数?

【问题讨论】:

【参考方案1】:

你说得对,那个功能很混乱。我建议使用提供反馈小部件让 Apple 知道。

我认为您应该从函数签名中删除kernelkernel_widthkernel_height 参数。这些似乎是应用调用者提供的内核的函数的保留,但此示例是关于应用内部定义的内核。

修复了kernel 局部变量的声明,使其成为uint8_t 的数组,如下所示:

    uint8_t kernel[] = -2, -2, 0, -2, 6, 0, 0, 0, 0; // 1

然后,在调用vImageConvolve_ARGB8888() 时,将kernel_widthkernel_height 替换为3。由于内核是硬编码的,因此维度也可以。

【讨论】:

我应该自己定义uint_8还是在某个头文件中定义? 在 stdint.h 中定义。 你能再具体一点吗?我在任何名为 stdint.h 的头文件中都找不到这种类型的任何痕迹 这是文档中此伪代码中的另一个错字。应该是:uint8_t 你是对的。我只是在没有注意到的情况下将它翻译成我脑海中的uint8_t! (或者,更确切地说,没有仔细阅读并替换了我“知道”的内容。)我已经更新了我的答案以包含该修复程序。【参考方案2】:

内核只是卷积中使用的内核。在数学术语中,它是与您的图像卷积的矩阵,以实现模糊/锐化/浮雕或其他效果。您提供的这个函数只是 vimage 卷积函数的一个薄包装器。要实际执行卷积,您可以按照下面的代码进行操作。代码都是手动输入的,因此不一定 100% 正确,但应该为您指明正确的方向。

要使用此功能,您首先需要对图像进行像素访问。假设你有一个 UIImage,你可以这样做:

//image is a UIImage
CGImageRef img = image.CGImage;
CGDataProviderRef dataProvider = CGImageGetDataProvider(img); 
CFDataRef cfData = CGDataProviderCopyData(dataProvider);
void * dataPtr = (void*)CFDataGetBytePtr(cfData);

接下来,您构建将传递给函数的 vImage_Buffer

vImage_Buffer inBuffer, outBuffer;
inBuffer.data = dataPtr;
inBuffer.width = CGImageGetWidth(img);
inBuffer.height = CGImageGetHeight(img);
inBuffer.rowBytes = CGImageGetBytesPerRow(img);

同时分配 outBuffer

outBuffer.data = malloc(inBuffer.height * inBuffer.rowBytes)
// Setup width, height, rowbytes equal to inBuffer here

现在我们创建内核,与您的示例中的内核相同,它是一个 3x3 矩阵 如果它们是浮点数,则将值乘以除数(它们需要是整数)

int divisor = 1000;
CGSize kernalSize = CGSizeMake(3,3);
int16_t *kernel = (int16_t*)malloc(sizeof(int16_t) * 3 * 3);
// Assign kernel values to the emboss kernel
// uint_8 kernel = -2, -2, 0, -2, 6, 0, 0, 0, 0 // * 1000 ;

现在对图像进行卷积!

//Use a background of transparent black as temp
Pixel_8888 temp = 0;
vImageConvolve_ARGB8888(&inBuffer, &outBuffer, NULL, 0, 0, kernel, kernelSize.width, kernelSize.height, divisor, temp, kvImageBackgroundColorFill);

现在用 outBuffer 构造一个新的 UIImage 就完成了!

记得释放内核和 outBuffer 数据。

【讨论】:

【参考方案3】:

这是我使用它来处理通过 AVAssetReader 从视频中读取的帧的方式。这是一个模糊,但您可以更改内核以满足您的需要。 'imageData' 当然可以通过其他方式获得,例如来自 UIImage。

     CMSampleBufferRef sampleBuffer = [asset_reader_output copyNextSampleBuffer];
     CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);            
     CVPixelBufferLockBaseAddress(imageBuffer,0);
     void *imageData = CVPixelBufferGetBaseAddress(imageBuffer);        

     int16_t kernel[9];
     for(int i = 0; i < 9; i++) 
        kernel[i] = 1;
     
     kernel[4] = 2;

     unsigned char *newData= (unsigned char*)malloc(4*currSize);

     vImage_Buffer  inBuff =  imageData, height, width, 4*width ;
     vImage_Buffer  outBuff =  newData, height, width, 4*width ;

     vImage_Error err=vImageConvolve_ARGB8888 (&inBuff,&outBuff,NULL, 0,0,kernel,3,3,10,nil,kvImageEdgeExtend);
     if (err != kvImageNoError) NSLog(@"convolve error %ld", err);
     CVPixelBufferUnlockBaseAddress(imageBuffer, 0);

     //newData holds the processed image

【讨论】:

以上是关于如何编译vImage浮雕效果示例代码?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 glsl 中复制 Photoshop 斜面/浮雕边框效果

为啥我不能在 iPhone 上编译引用 vImage 库的代码?

计算机视觉之图像特效(实现浮雕效果等功能)(待更新。。。)

编译cython的HelloWorld示例:不知道如何在平台上编译C/C++代码

需要基本示例代码编译帮助 - 我无法让任何 SDK 示例工作

C#图像处理(各种旋转改变大小柔化锐化雾化底片浮雕黑白滤镜效果)