Нет. Они испускают точно тот же самый IL.
Это - просто вопрос стиля.
var
обладает преимуществом, которое помогает Вам изменить тип возврата функций, не изменяя другие части исходного кода. Например, измените тип возврата с IEnumerable<T>
до List<T>
. Однако это могло бы помочь представить ошибки.
Способ узнать вашу проблему со скоростью - профилировать с помощью Shark. (В Xcode Run-> Start with Performance Tool-> Shark.) Однако в этом случае я достаточно уверен, что основными проблемами являются попиксельное malloc / free, арифметика с плавающей запятой и два вызова методов в внутренний цикл обработки.
Чтобы избежать malloc / free, вы хотите вместо этого сделать что-то вроде этого:
- (void) getColorForPixelX:(NSUInteger)x y:(NSUInteger)y pixel:(float[3])pixel
{ /* Write stuff to pixel[0], pixel[1], pixel[2] */ }
// To call:
float pixel[3];
for (each pixel)
{
[self getColorForPixelX:x y:y pixel:pixel];
// Do stuff
}
Второй вероятный источник замедления - использование чисел с плавающей запятой - или, скорее, стоимость преобразования в и с плавающей запятой. Для фильтра, который вы пишете, работать с целочисленной математикой просто - сложите значения целых пикселей и разделите на 255 * 3. (Между прочим, это довольно плохой способ преобразования в оттенки серого. См. http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale . )
Вызов методов происходит быстро, но все же довольно медленно по сравнению с базовой арифметикой фильтра. (Некоторые числа см. в этой статье .) Самый простой способ избавиться от вызовов методов - заменить их встроенными функциями.
Вы можете позволить Quartz выполнить преобразование оттенков серого за вас:
CGImageRef grayscaleCGImageFromCGImage(CGImageRef inputImage) {
size_t width = CGImageGetWidth(inputImage);
size_t height = CGImageGetHeight(inputImage);
// Create a gray scale context and render the input image into that
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceGray();
CGContextRef context = CGBitmapContextCreate(NULL, width, height, 8,
4*width, colorspace, kCGBitmapByteOrderDefault);
CGContextDrawImage(context, CGRectMake(0,0, width,height), inputImage);
// Get an image representation of the grayscale context which the input
// was rendered into.
CGImageRef outputImage = CGBitmapContextCreateImage(context);
// Cleanup
CGContextRelease(context);
CGColorSpaceRelease(colorspace);
return (CGImageRef)[(id)outputImage autorelease];
}
Недавно мне пришлось решить ту же проблему, и я придумал следующий код (он также сохраняет альфа-канал):
@implementation UIImage (grayscale)
typedef enum {
ALPHA = 0,
BLUE = 1,
GREEN = 2,
RED = 3
} PIXELS;
- (UIImage *)convertToGrayscale {
CGSize size = [self size];
int width = size.width;
int height = size.height;
// the pixels will be painted to this array
uint32_t *pixels = (uint32_t *) malloc(width * height * sizeof(uint32_t));
// clear the pixels so any transparency is preserved
memset(pixels, 0, width * height * sizeof(uint32_t));
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
// create a context with RGBA pixels
CGContextRef context = CGBitmapContextCreate(pixels, width, height, 8, width * sizeof(uint32_t), colorSpace,
kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedLast);
// paint the bitmap to our context which will fill in the pixels array
CGContextDrawImage(context, CGRectMake(0, 0, width, height), [self CGImage]);
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
uint8_t *rgbaPixel = (uint8_t *) &pixels[y * width + x];
// convert to grayscale using recommended method: http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale
uint32_t gray = 0.3 * rgbaPixel[RED] + 0.59 * rgbaPixel[GREEN] + 0.11 * rgbaPixel[BLUE];
// set the pixels to gray
rgbaPixel[RED] = gray;
rgbaPixel[GREEN] = gray;
rgbaPixel[BLUE] = gray;
}
}
// create a new CGImageRef from our context with the modified pixels
CGImageRef image = CGBitmapContextCreateImage(context);
// we're done with the context, color space, and pixels
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
free(pixels);
// make a new UIImage to return
UIImage *resultUIImage = [UIImage imageWithCGImage:image];
// we're done with image now too
CGImageRelease(image);
return resultUIImage;
}
@end
Вы пробовали использовать режим наложения яркости? Белое изображение, смешанное с вашим оригиналом в этом режиме наложения, кажется, дает оттенки серого. Эти два, изображение переднего плана справа и фоновое изображение слева:
смешанный с kCGBlendModeLuminosity
приводит к следующему:
Подробнее , см .: Рисование с помощью Quartz 2D: использование режимов наложения с изображениями