Also filed as FB11965555. Thanks!
Post
Replies
Boosts
Views
Activity
I'm not sure what the best way to encode an NSAffineTransform into an NSValue is (maybe NSValue(nonretainedObject:)?), but there is actually a much simpler way for applying a transformation to an image using a CGAffineTransform:
let transformedImage = image.transformed(by: CGAffineTransform(...))
No need to use the CIAffineTransform filter.
Also reported as FB11871301. Thanks!
It turns out the problem was caused by how we loaded the cube data. Previously, we did it like this:
let cubeImage: CGImage = ...
// render cube image into a 32-bit float context, since that's the data format needed by CIColorCube
let pixelData = UnsafeMutablePointer<simd_float4>.allocate(capacity: cubeImage.width * cubeImage.height)
let bitmapInfo = CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.floatComponents.rawValue | CGBitmapInfo.byteOrder32Little.rawValue
let colorSpace = cubeImage.colorSpace ?? CGColorSpace.sRGBColorSpace
guard let bitmapContext = CGContext(data: pixelData,
width: cubeImage.width,
height: cubeImage.height,
bitsPerComponent: MemoryLayout<simd_float4.Scalar>.size * 8,
bytesPerRow: MemoryLayout<simd_float4>.size * cubeImage.width,
space: colorSpace,
bitmapInfo: bitmapInfo)
else {
assertionFailure("Failed to create bitmap context for conversion")
}
bitmapContext.draw(cubeImage, in: CGRect(x: 0, y: 0, width: cubeImage.width, height: cubeImage.height))
let data = Data(bytesNoCopy: pixelData, count: bitmapContext.bytesPerRow * bitmapContext.height, deallocator: .free)
// pass data to filter
Note that we pre-allocated the pixelData buffer and gave it to the CGContext to render the cube image into it. It seems that data was corrupted or released too early in some cases, causing the erroneous behavior described above, even though we assumed that Data(bytesNoCopy:...) would take ownership of the data.
To fix this, we let CGContext create its own buffer and copy the cube data after the draw:
let cubeImage: CGImage = ...
// render cube image into a 32-bit float context, since that's the data format needed by CIColorCube
let bitmapInfo = CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.floatComponents.rawValue | CGBitmapInfo.byteOrder32Little.rawValue
let colorSpace = cubeImage.colorSpace ?? CGColorSpace.sRGBColorSpace
guard let bitmapContext = CGContext(data: nil,
width: cubeImage.width,
height: cubeImage.height,
bitsPerComponent: MemoryLayout<simd_float4.Scalar>.size * 8,
bytesPerRow: MemoryLayout<simd_float4>.size * cubeImage.width,
space: colorSpace,
bitmapInfo: bitmapInfo)
else {
assertionFailure("Failed to create bitmap context for conversion")
}
bitmapContext.draw(cubeImage, in: CGRect(x: 0, y: 0, width: cubeImage.width, height: cubeImage.height))
guard let pixelData = bitmapContext.data else {
assertionFailure("Failed to get cube data")
}
let data = Data(bytes: pixelData, count: bitmapContext.bytesPerRow * bitmapContext.height)
// pass data to filter
This was also filed as FB11736373, together with a demo project.
Are you using the same CIContext in all threads? And can you please post a screenshot of the stack when the crash happens?
I also filed Feedback requests for the Image I/O (FB11512515) and Core Image (FB11512528) APIs, as well as PHPicker improvements (FB9706029).
I think I found the reason why the gain map isn't showing any effect:
There seem to be two private {MakerApple} EXIF tags controlling the HDR effect.
The one @anteo83 mentioned (0x21) seems to control the global boost to brightness. I guess via some kind of gamma curve tone mapping.
But there is also the 0x30 which controls how much the embedded gain map adds to the effect. It seems to range between 0.0 and 8.0, with 0.0 having the biggest effect.
When 0x30 is present, 0x21 doesn't need to be present to show the effects of the gain map. They also seem to work in tandem, with 0x21 adding to the global value and 0x30 controlling local values via gain map.
There is some great fun to be had with this. Check out the attached image on your XDR or OLED device in Photos. 😁
Edit: I was trying to attach an example image here, but Forums seem to convert the image, losing the gain map in the process. You can find it here.
Yes, that would be very helpful! I also filed that request under FB10224187.
I encountered the same. When I re-watched the session, I heard Brad say the following:
And I need to ensure here that my extension's app group is prefixed by the MachServiceName in order for it to pass validation.
I changed the CMIOExtensionMachServiceName in the extension's Info.plist to the same value as my app's and extension's app group name and suddenly it passed validation. I'm not sure if this is the intended configuration. Maybe Apple's Extensions team can clarify what the "prefixed" means here and what the values should look like.
Also filed under FB10151072.
Also filed as FB10151072.
I guess this is happening because CIPhotoEffectTonal also has an effect on the transparent parts of the image.
If you want to limit the effect to the visible part, you can simply crop the image after the effect is applied and before you blend it over the background:
video1FilteredImage = [video1FilteredImage imageByCroppingToRect:video1FilteredImage.extent];
By the way: instead of using CIConstantColorGenerator you can simply get a colored image like this:
CIImage *colorBackgroundImage = [CIImage imageWithColor:inputColor];
Also filed as FB9989184.
You are capturing self in the roiCallback for no apparent reason. Can you please try to remove the [self] and check again?