Недавно мне нужно было решить эту задачу для одного из проектов под iPhone. Естественное, на помощь я позвал Google, который показал мне ссылки сразу на несколько вариантов решения. Однако не все они справились с поставленной задачей должным образом. Все реализации, испробованные мною в начале, «забывали» про альфа-канал. Они преобразовывали его в черный цвет, что было для меня неприемлемо. Альфа-канал должен был сохраняться. Поэтому я стал просматривать варианты более внимательно. Нужную мне реализацию я нашел акурат под ранее не подошедшей. На ней я и остановился. А ниже привожу её исходный код на Objective-C. Для себя, чтобы не искать потом снова, а может и еще кому-нибудь пригодится.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
typedef enum { ALPHA = 0, BLUE = 1, GREEN = 2, RED = 3 } PIXELS; //конвертирует картинку в "черно-белую" с сохранением альфа-канала + (UIImage *)convertToGrayscale:(UIImage*)img { CGSize size = [img size]; int width = size.width; int height = size.height; // пиксели будут рисоваться в этот массив uint32_t *pixels = (uint32_t *) malloc(width * height * sizeof(uint32_t)); // очищаем пиксели с сохранением прозрачности memset(pixels, 0, width * height * sizeof(uint32_t)); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); // создаем контекст с RGBA-пикселями CGContextRef context = CGBitmapContextCreate(pixels, width, height, 8, width * sizeof(uint32_t), colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedLast); // отображаем картинку на наш контекст CGContextDrawImage(context, CGRectMake(0, 0, width, height), [img CGImage]); for(int y = 0; y < height; y++) { for(int x = 0; x < width; x++) { uint8_t *rgbaPixel = (uint8_t *) &pixels[y * width + x]; // преобразуем в черно-белый формат, используя следующий метод: 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]; // устанавливаем пиксели в серый rgbaPixel[RED] = gray; rgbaPixel[GREEN] = gray; rgbaPixel[BLUE] = gray; } } // создаем CGImageRef из нашего контекста с модифицированными пикселями CGImageRef image = CGBitmapContextCreateImage(context); // завершаем работу с context, color space, и pixels CGContextRelease(context); CGColorSpaceRelease(colorSpace); free(pixels); // создаем новый UIImage для возвращения UIImage *resultUIImage = [UIImage imageWithCGImage:image]; // завершаем работу с image CGImageRelease(image); return resultUIImage; } |
В результативности приведенного Objective-C кода я убедился сам. Результат отличный — рекомендую :)
Полезная статья? Их будет больше, если вы поддержите меня!