【问题标题】:iOS - Drawing efficiency (update on slider change)iOS - 绘图效率(滑块更改更新)
【发布时间】:2013-04-03 14:04:39
【问题描述】:

我正在 iOS 上为图像着色。我正在使用滑块来选择颜色。

当我将滑块上的“更新事件”设置为连续时,被调用的函数会被大量调用(滑块从 0 变为 1535),因此用户界面的响应速度不是很快。

有没有办法让下面的代码更有效率?我意识到每次调用函数时我都会开始一个新的绘图上下文 - 我可以“保存”这个上下文并重新使用它吗?

提前致谢。

- (IBAction)bodyColourChanged:(UISlider *)sender {
// get the UIColor from self.colourArray
UIColor *color = [self.colourArray objectAtIndex:sender.value];

UIImage *myImage = [UIImage imageNamed:@"body.png"];

// Begin a new image context to draw the coloured image onto
UIGraphicsBeginImageContext(self.bodyView.image.size);

// Get a reference to the context we created
CGContextRef context = UIGraphicsGetCurrentContext();

// Set the fill colour
//[[UIColor colorWithRed:color.CGColor green:green blue:blue alpha:1.0] setFill];
[color setFill];

// translate/flip the graphics context (for transforming from CG* coords to UI* coords
CGContextTranslateCTM(context, 0, self.bodyView.image.size.height);
CGContextScaleCTM(context, 1.0, -1.0);

// set the blend mode and the original image
CGContextSetBlendMode(context, kCGBlendModeOverlay);
CGRect rect = CGRectMake(0, 0, self.bodyView.image.size.width, self.bodyView.image.size.height);
CGContextDrawImage(context, rect, myImage.CGImage);

// Set a mask that matches the shape of the image, then draw (colour burn) a coloured rectangle
CGContextClipToMask(context, rect, self.bodyView.image.CGImage);
CGContextAddRect(context, rect);
CGContextDrawPath(context, kCGPathFill);

// Generate a new UIImage from the graphics context we drew onto
UIImage *colouredImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

self.bodyView.image = colouredImage;
}

编辑:我正在着色的图像非常大。它是 1541 x 2000 像素,因为我希望能够在不损失质量的情况下放大。也许这就是问题所在。我会继续修补,看看我能找到什么。

【问题讨论】:

  • 你试过CATiledLayer了吗?
  • 你说得对,图像大小是一个因素,你正面临图像大小的限制,正如大卫建议的那样,没有平铺它。更改颜色时是否需要具有缩放功能?您能否制作一个较小的副本,在其上预览颜色更改,然后在用户完成后将更改应用于较大的图像,也许在后台?

标签: iphone ios ipad cgcontext


【解决方案1】:

我不确定您的着色方法,但我通过在一小段延迟(即用户已暂停滑动)后仅调用性能密集型方法来解决与滑块类似的性能问题。

创建一些类变量/属性来保存与时间相关的对象:

@property (nonatomic, strong) NSDate *sliderValueChangedDate;
@property (nonatomic, strong) NSTimer *sliderValueChangedTimer;

在您连接到UISlider 事件的方法中:

- (IBAction)sliderValueChanged:(id)sender {
    // Save the time the slider was changed.
    self.sliderValueChangedDate = [NSDate date];
    // Start a timer if it's not already running.
    if (!self.sliderValueChangedTimer) {
        self.sliderValueChangedTimer = [NSTimer scheduledTimerWithTimeInterval:0.3 target:self selector:@selector(checkIfImageShouldBeColoured:) userInfo:nil repeats:YES];
    }
}

然后在您的 checkIfImageShouldBeColoured: 方法中,您可以查看值是否在此期间发生了变化:

- (void)checkIfImageShouldBeColoured:(NSTimer *)timer {
    // Get how long has been elapsed since the slider was last changed.
    NSTimeInterval elapsed = -[self.sliderValueChangedDate timeIntervalSinceNow];
    // If this is over our threshold, then perform the intensive method.
    if (elapsed > 0.3) {
        [self.sliderValueChangedTimer invalidate];
        self.sliderValueChangedTimer = nil;
        [self changeBodyColour];
    }
}

【讨论】:

  • 如果我没看错,您将安排 很多 个计时器;)
  • 嗯,是的。最好使用单个计时器并检查时间戳值:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-22
  • 1970-01-01
  • 1970-01-01
  • 2022-01-28
  • 2012-08-27
相关资源
最近更新 更多