如何在 Cocoa 上使用 CIAffineTile?

How to I use CIAffineTile on Cocoa?

我有一个 CIImage,比方说 500x250 像素,我试图平铺它,所以它会变成 1000x500 图片,两行,每行两张图片,如下所示:

我正在尝试使用 Cocoa 上的 CIAffineTile 来做到这一点(我不确定这是否是最合适的过滤器)。

正如预期的那样,来自 Apple 的文档非常模糊和加密。

显然,过滤器的调用方式必须不同于 iOS 和 OSX,但 OSX 部分是神秘的。

这是我的代码:

我所做的是,我创建了 tile 过滤器,然后将其裁剪为每个方向上图片大小的两倍 + 2,以在它们之间创建一个 2 像素 space。

  // the picture has to translate this amount?
  CGAffineTransform translate = CGAffineTransformMakeTranslation(pictureWidth+2, pictureHeight+2);
  CIFilter *filterTile = [CIFilter filterWithName:@"CIAffineTile"];
  [filterTile setValue:[NSValue valueWithBytes:&translate
                                      objCType:@encode(CGAffineTransform)]
                                        forKey:@"inputTransform"];

  CIVector *cropRect =[CIVector vectorWithX:0
                                          Y:0
                                          Z:2 * pictureWidth+2
                                          W:2 * pictureHeight+2];

  CIFilter *crop = [CIFilter filterWithName:@"CICrop"];
  [crop setValue:[filterTile outputImage] forKey:@"inputImage"];
  [crop setValue:cropRect forKey:@"inputRectangle"];

这会导致不正确的 CIImage。我看到的是这样的:

转换有什么问题?难道不是假设图像必须转换为图块的像素数量吗?

最奇怪的部分:变换可以是任何东西,即使恒等变换和结果也是一样的。

我试图猜测如何在 OSX 上做到这一点并想象这样的事情:

NSAffineTransform *translate = [NSAffineTransform transform];
  [translate translateXBy:(pictureWidth + 2) yBy:(pictureHeight + 2];

  CIFilter *filterTile = [CIFilter filterWithName:@"CIAffineTile"];
  [filterTile setValue:imagem forKey:@"inputImage"];

但最后以逆时针旋转 90 度 (???) 的图像结束。

从概念上讲,您可以将 CIAffineTile 过滤器想象成这样:

  1. 使用 image.extent.size
  2. 在 X 和 Y 上无限平铺图像
  3. 应用仿射变换

鉴于此实现,仿射不会对图像块之间的间隙产生任何影响,这是预期的行为。

如果您想要图像之间有额外的间隙,那么您需要在使用 CIAffineTile 之前用白色像素填充图像。这可以通过使用

来完成
 [[i imageByCompositingOverImage:[CIImage imageWithColor:white]] imageByCroppingToRect:CGRectInset(i.extent,-1,-1)]

下面是一些代码,它可以在没有填充的情况下生成 2x2 图块

CGAffineTransform xform = CGAffineTransformIdentity;
NSValue *xformObj = [NSValue valueWithBytes:&xform objCType:@encode(CGAffineTransform)];

image = [image imageByApplyingFilter:@"CIAffineTile"
                 withInputParameters:@{kCIInputTransformKey : xformObj} ];
image = [image imageByCroppingToRect:CGRectMake(0,0, 2*pictureWidth, 2*pictureHeight)];