Есть задача написать на swift код для определения размера зон одного цвета на картинке.
Написал сначала на ObjectiveC, потом перевел на Swift но получил падение скорости обработки больше чем в 10x.
После всех оптимизаций получилось уменьшить разрыв до 2.5x но этого не достаточно.
-
Картинка: градиент от (0,0,0) до (255,0,0) с размером 2048x2048.
-
Код Swift:
@IBAction func allZonesOpt(_ sender: Any) {
let startDate = Date()let image : UIImage = UIImage(named:"idx.png")! let cgImage : CGImage = image.cgImage! guard let pixelData = CGDataProvider(data: (cgImage.dataProvider?.data)!)?.data else { return } let data = CFDataGetBytePtr(pixelData)! let numberOfComponents:Int = 4 let imageWidth = Int(image.size.width) let imageHeight = Int(image.size.height) let bytesPerRow = imageWidth * numberOfComponents let rangeOne = 0..<Int(image.size.height) let rangeTwo = 0..<Int(image.size.width) var arrayWithZones = [(Int, Int)]() for colorRed:UInt8 in 0...255 { let colorR = colorRed let colorG = 0 let colorB = 0 var minx:Int = imageWidth var miny:Int = imageHeight var maxx:Int = 0 var maxy:Int = 0 let startDateFor = Date() for y in rangeOne { for x in rangeTwo { let pixelData = (bytesPerRow * y) + x * numberOfComponents if data[pixelData] == colorR && data[pixelData + 1] == colorG && data[pixelData+2] == colorB{ if minx > x{ minx = x } if miny > y{ miny = y } if maxx < x{ maxx = x } if maxy < y{ maxy = y } } } } let methodFinishFor = Date() let timeIntervalFor = methodFinishFor.timeIntervalSince(startDateFor) print(" time execution = \(timeIntervalFor)") arrayWithZones.append((maxx - minx, maxy - miny)) } let methodFinish = Date() let timeInterval = methodFinish.timeIntervalSince(startDate) resultLabel.text = " time execution = \(timeInterval)" print(" time execution = \(timeInterval)") print("atFinal = \(arrayWithZones)");
}
-
Код ObjectiveC
- (IBAction)allZonesAsSwift:(id)sender {
NSDate *methodStart = [NSDate date];
UIImage *image = [UIImage imageNamed:@"idx.png"];
//static rawData
CGImageRef imageRef = [image CGImage];
unsigned int width = (unsigned int)CGImageGetWidth(imageRef);
unsigned int height = (unsigned int)CGImageGetHeight(imageRef);
int bytesPerPixel = 4;
int bytesPerRow = bytesPerPixel * width;
CFDataRef data = CGDataProviderCopyData(CGImageGetDataProvider(imageRef));
const unsigned char * rawData = CFDataGetBytePtr(data);
unsigned int minx = image.size.width;
unsigned int miny = image.size.height;
unsigned int maxx = 0;
unsigned int maxy = 0;
unsigned char colorR = 0;
unsigned char colorG = 0;
unsigned char colorB = 0;
NSMutableArray *arrayWithZones = [NSMutableArray<NSValue*> new];
for (int colorRed = 0; colorRed < 256; colorRed ++) {
colorR = (unsigned char)colorRed;
minx = (unsigned int)image.size.width;
miny = (unsigned int)image.size.height;
maxx = 0;
maxy = 0;
NSDate *methodStartFor = [NSDate date];
for (unsigned int y = height - 1; y; y--) {
for (unsigned int x = width - 1; x; x--) {
unsigned int byteIndex = (bytesPerRow * y) + x * bytesPerPixel;
if (rawData[byteIndex] == colorR && rawData[byteIndex + 1] == colorG && rawData[byteIndex + 2] == colorB) {
minx = x < minx ? x : minx;
maxx = x > maxx ? x : maxx;
miny = y < miny ? y : miny;
maxy = y > maxy ? y : maxy;
}
}
}
NSDate *methodFinishFor = [NSDate date];
NSTimeInterval executionTimeFor = [methodFinishFor timeIntervalSinceDate:methodStartFor];
NSLog(@"executionTime Zone = %f", executionTimeFor);
CGSize final = CGSizeMake(maxx - minx, maxy - miny);
[arrayWithZones addObject:[NSValue valueWithCGSize:final]];
}
free(rawData);
NSDate *methodFinish = [NSDate date];
NSTimeInterval executionTime = [methodFinish timeIntervalSinceDate:methodStart];
NSLog(@"color picker = %f", executionTime);
_resultLabel.text = [NSString stringWithFormat:@"color picker = %f", executionTime];
NSLog(@"final = %@", arrayWithZones);
}