使用 UIImage 模拟 NSImage drawInRect:fromRect:operation:fraction

发布于 2024-08-22 12:46:32 字数 1164 浏览 20 评论 0原文

我真的需要使用 UIImage 来模拟 NSImage 的 drawInRect:fromRect:operation:fraction 的行为,我想知道什么是最好的方法或(更好),如果有人已经这样做并且愿意分享代码。

我尝试使用 CGImageCreateWithImageInRect 执行此操作(请参阅最后的代码),但我没有得到预期的结果。请注意,代码实际上是在 mac 上测试的(我现在无法在 iPhone 上运行整个代码),所以我可能在从 NSImage 获取 CGImage 时遇到一些问题

- (void)drawInRect:(CGRect)rect fromRect:(CGRect)fromRect alpha:(float)alpha {
      CGContextRef context;
       CGImageRef originalImageRef;
       CGImageRef subimageRef;

#if ERMac
       context=[[NSGraphicsContext currentContext] graphicsPort];

       CGImageSourceRef source;

       source = CGImageSourceCreateWithData((CFDataRef)[self TIFFRepresentation], NULL);
       originalImageRef =  CGImageSourceCreateImageAtIndex(source, 0, NULL);
       CFRelease(source);
#else
       context=UIGraphicsGetCurrentContext();
       originalImageRef=CGImageRetain([self CGImage]);
#endif

       subimageRef = CGImageCreateWithImageInRect (originalImageRef, fromRect);


       CGContextDrawImage(context, rect, subimageRef);


       if (subimageRef)
           CGImageRelease(subimageRef);
       if (originalImageRef)
           CGImageRelease(originalImageRef);
 }

I really need to emulate the behavior of NSImage's drawInRect:fromRect:operation:fraction using UIImage and I'm wondering what's the best approach or (better), if somebody already did this and willing to share the code.

I tried doing this using CGImageCreateWithImageInRect (see code at the end) but I'm not getting the expected results. Note that the code is actually testing this on the mac (I can't run the whole thing on the iPhone as of now) so I may have some issue with getting the CGImage from NSImage

- (void)drawInRect:(CGRect)rect fromRect:(CGRect)fromRect alpha:(float)alpha {
      CGContextRef context;
       CGImageRef originalImageRef;
       CGImageRef subimageRef;

#if ERMac
       context=[[NSGraphicsContext currentContext] graphicsPort];

       CGImageSourceRef source;

       source = CGImageSourceCreateWithData((CFDataRef)[self TIFFRepresentation], NULL);
       originalImageRef =  CGImageSourceCreateImageAtIndex(source, 0, NULL);
       CFRelease(source);
#else
       context=UIGraphicsGetCurrentContext();
       originalImageRef=CGImageRetain([self CGImage]);
#endif

       subimageRef = CGImageCreateWithImageInRect (originalImageRef, fromRect);


       CGContextDrawImage(context, rect, subimageRef);


       if (subimageRef)
           CGImageRelease(subimageRef);
       if (originalImageRef)
           CGImageRelease(originalImageRef);
 }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

归途 2024-08-29 12:46:32

我就是这样做的...

- (void)drawInRect:(CGRect)drawRect fromRect:(CGRect)fromRect operation:(CGBlendMode)blendMode fraction:(CGFloat)alpha
{
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSaveGState(context);
    CGContextClipToRect(context, drawRect);

    CGFloat xScale = (drawRect.size.width/fromRect.size.width);
    CGFloat yScale = (drawRect.size.height/fromRect.size.height);

    CGFloat scale = 1;
    if([self respondsToSelector:@selector(scale)])
    {
        scale = self.scale;
    }

    CGFloat actualWidth = (xScale * self.size.width)*scale;
    CGFloat actualHeight = (yScale * self.size.height)*scale;
    CGFloat xInset = fromRect.origin.x * xScale;
    CGFloat yInset = fromRect.origin.y * yScale;

    // Take care of Y-axis inversion problem by translating the context on the y axis
    CGContextTranslateCTM(context, 0, drawRect.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);
    CGContextDrawImage(context, CGRectMake(-xInset + drawRect.origin.x, -yInset + drawRect.origin.y, actualWidth, actualHeight), self.CGImage);

    CGContextRestoreGState(context);
}

This is how I do it...

- (void)drawInRect:(CGRect)drawRect fromRect:(CGRect)fromRect operation:(CGBlendMode)blendMode fraction:(CGFloat)alpha
{
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSaveGState(context);
    CGContextClipToRect(context, drawRect);

    CGFloat xScale = (drawRect.size.width/fromRect.size.width);
    CGFloat yScale = (drawRect.size.height/fromRect.size.height);

    CGFloat scale = 1;
    if([self respondsToSelector:@selector(scale)])
    {
        scale = self.scale;
    }

    CGFloat actualWidth = (xScale * self.size.width)*scale;
    CGFloat actualHeight = (yScale * self.size.height)*scale;
    CGFloat xInset = fromRect.origin.x * xScale;
    CGFloat yInset = fromRect.origin.y * yScale;

    // Take care of Y-axis inversion problem by translating the context on the y axis
    CGContextTranslateCTM(context, 0, drawRect.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);
    CGContextDrawImage(context, CGRectMake(-xInset + drawRect.origin.x, -yInset + drawRect.origin.y, actualWidth, actualHeight), self.CGImage);

    CGContextRestoreGState(context);
}
浸婚纱 2024-08-29 12:46:32

UIImage有drawInRect:blendMode:alpha:。提取 UIImage 子矩形的一个简单技巧是绘制到目标上下文中,该目标上下文是要提取的矩形的大小,向上和向左调整绘制图像的原点,以便右侧部分落入目标中语境。

CGImage 也是一个很好的方法,但是您可能会遇到在 iPhone 上翻转坐标系的问题。一个简单的解决方案是将 CGImage 包装到 UIImage 中并绘制它,因为 UIImage 知道向上绘制的方向。

UIImage has drawInRect:blendMode:alpha:. A simple trick for extracting a subrectangle of a UIImage is to draw into a target context which is the size of the rectangle you want to extract, adjusting the origin of the drawn image up and to the left so that the right portion falls into the target context.

CGImage is also a good way to do this but you may encounter problems with the coordinate system being flipped on the iPhone. An easy solution is to wrap the CGImage into a UIImage and draw that, since UIImage knows which way up to draw.

青朷 2024-08-29 12:46:32

NSImage类别方法示例和我移植到iOS:

-(NSImage*)getSubimageWithRect:(CGRect)rect {
    NSBitmapImageRep *rep = [[NSBitmapImageRep alloc]
                         initWithBitmapDataPlanes:NULL
                         pixelsWide:rect.size.width
                         pixelsHigh:rect.size.height
                         bitsPerSample:8
                         samplesPerPixel:4
                         hasAlpha:YES
                         isPlanar:NO
                         colorSpaceName:NSDeviceRGBColorSpace
                         bytesPerRow:0
                         bitsPerPixel:0];

    [NSGraphicsContext saveGraphicsState];
    [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:rep]];
    [self drawInRect:CGRectMake(0, 0, rect.size.width, rect.size.height) fromRect:rect operation:NSCompositingOperationCopy fraction:1.0];
    [NSGraphicsContext restoreGraphicsState];

    NSImage *newImage = [[NSImage alloc] initWithSize:rect.size];
    [newImage addRepresentation:rep];
    return newImage;
}

iOS代码:

-(UIImage*)getSubimageWithRect:(CGRect)rect {
    CGFloat width = rect.size.width;
    CGFloat height = rect.size.height;
    CGContextRef context = CGBitmapContextCreate(NULL, width, height,
8, 4*width, CGColorSpaceCreateDeviceRGB(),
kCGImageAlphaPremultipliedLast|kCGBitmapByteOrderDefault);

    CGContextDrawImage(context, CGRectMake(-rect.origin.x, -rect.origin.y, self.size.width, self.size.height), self.CGImage);
    CGImageRef ref = CGBitmapContextCreateImage(context);

    UIImage *newImage = [UIImage imageWithCGImage:ref];

    CGImageRelease(ref);
    CGContextRelease(context);

    return newImage;
}

NSImage category method example and my port to iOS:

-(NSImage*)getSubimageWithRect:(CGRect)rect {
    NSBitmapImageRep *rep = [[NSBitmapImageRep alloc]
                         initWithBitmapDataPlanes:NULL
                         pixelsWide:rect.size.width
                         pixelsHigh:rect.size.height
                         bitsPerSample:8
                         samplesPerPixel:4
                         hasAlpha:YES
                         isPlanar:NO
                         colorSpaceName:NSDeviceRGBColorSpace
                         bytesPerRow:0
                         bitsPerPixel:0];

    [NSGraphicsContext saveGraphicsState];
    [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:rep]];
    [self drawInRect:CGRectMake(0, 0, rect.size.width, rect.size.height) fromRect:rect operation:NSCompositingOperationCopy fraction:1.0];
    [NSGraphicsContext restoreGraphicsState];

    NSImage *newImage = [[NSImage alloc] initWithSize:rect.size];
    [newImage addRepresentation:rep];
    return newImage;
}

iOS code:

-(UIImage*)getSubimageWithRect:(CGRect)rect {
    CGFloat width = rect.size.width;
    CGFloat height = rect.size.height;
    CGContextRef context = CGBitmapContextCreate(NULL, width, height,
8, 4*width, CGColorSpaceCreateDeviceRGB(),
kCGImageAlphaPremultipliedLast|kCGBitmapByteOrderDefault);

    CGContextDrawImage(context, CGRectMake(-rect.origin.x, -rect.origin.y, self.size.width, self.size.height), self.CGImage);
    CGImageRef ref = CGBitmapContextCreateImage(context);

    UIImage *newImage = [UIImage imageWithCGImage:ref];

    CGImageRelease(ref);
    CGContextRelease(context);

    return newImage;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文