CIImage.clampedToExtent() doesn't fill some edges

Hi, I'm trying to find an explanation to strange behaviour of .clampedToExtent() method: I'm doing pretty strait forward thing, clamp the image and then crop it with some insets, so as a result I expert same image as original with padding on every side with repeating last pixel of each edge (to apply CIPixellate filter then), here is the code:

originalImage
  .clampedToExtent()
  .cropped(to: originalImage.extent.insetBy(dx: -50, dy: -50))

The result is strange: In the result image image has padding as specified, but only there sides have content there (left, right, bottom) and top side has transparent padding. Sometimes right side has transparency instead of content.

So the question is why this happens and how to get all sides filled with last pixel data?

I tested on two different devices with iOS 16 and 17.

Accepted Reply

I guess it has to do with the affine transform you apply to the image before you do the clampedToExtent():

As you can see, the output of the transform has non-integer extent. This probably creates a row of transparent pixels at the top of the image, that is then repeated when applying clampedToExtent().

To avoid this, you can calculate the scale factors for your transform separately for x and y to ensure that the resulting pixel size is integer. Alternatively, you can apply the clamping before you apply the affine transform.

Replies

I guess it has to do with the affine transform you apply to the image before you do the clampedToExtent():

As you can see, the output of the transform has non-integer extent. This probably creates a row of transparent pixels at the top of the image, that is then repeated when applying clampedToExtent().

To avoid this, you can calculate the scale factors for your transform separately for x and y to ensure that the resulting pixel size is integer. Alternatively, you can apply the clamping before you apply the affine transform.

Are you on the latest macOS Sonoma 14.2 Beta, by any chance? I'm currently investigating some unexpected/odd problems and they seem related to the -[CIImage imageByClampingToExtent:] / clampedToExtent() method too.

  • Never mind! The issue I was investigating is actually tied to tiling. If you are working with opaque images one solution would be to crop the image before calling clampedToExtent() to an integral rectangle. You want something similar to what CGRectIntegral() does, except that instead of expanding to the nearest integral coordinates, you shrink inward to make sure only fully opaque pixels fall within the rectangle.

Add a Comment