#ios
#iOS
Вопрос:
Я работаю в iOS и столкнулся с этой проблемой. Я буду получать относительно большой набор данных (массив размером 500×500 или больше в стиле C). Мне нужно построить из этих данных то, что по сути является графиком X / Y, где каждой точке данных в сетке 500×500 соответствует цвет, основанный на ее значении. Дело в том, что это меняется со временем, создавая, так сказать, некоторую анимацию, поэтому вычисления должны быть быстрыми, чтобы изменяться при поступлении нового набора данных.
Итак, по сути, для каждой точки в массиве мне нужно выяснить, какому цвету она должна соответствовать, затем определить квадрат, который нужно нарисовать на сетке для представления данных. Если бы моя сетка составляла 768×768 пикселей, но у меня был набор данных размером 500×500, то каждая точка данных представляла бы собой прямоугольник размером примерно 1,5×1,5 (он округлен, но я надеюсь, вы поняли идею).
Я попробовал это, создав новый класс view и переопределив drawRect. Однако это привело к ужасной производительности при чем-либо намного превышающем набор данных 20×20.
Я видел несколько предложений о записи в буферы изображений, но мне не удалось найти никаких примеров этого (я довольно новичок в iOS). У вас есть какие-либо предложения или не могли бы вы указать мне на какие-либо ресурсы, которые могли бы помочь?
Спасибо, что уделили мне время,
Дэррил
Ответ №1:
Вот некоторый код, который вы можете поместить в метод, который будет генерировать и возвращать UIImage в контексте вне экрана. Чтобы повысить производительность, попробуйте придумать способы минимизировать количество итераций, например, увеличить ваши «пиксели» или отрисовывать только ту часть, которая изменяется.
UIGraphicsBeginImageContext(size); // Use your own image size here
CGContextRef context = UIGraphicsGetCurrentContext();
// push context to make it current
// (need to do this manually because we are not drawing in a UIView)
//
UIGraphicsPushContext(context);
for (CGFloat x = 0.0; x<size.width; x =1.0) {
for (CGFloat y=0.0; y< size.height; y =1.0) {
// Set your color here
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0));
CGContextFillRect(context, CGRectMake(x, y, 1.0, 1.0));
}
}
// pop context
//
UIGraphicsPopContext();
// get a UIImage from the image context- enjoy!!!
//
UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
[outputImage retain];
// clean up drawing environment
//
UIGraphicsEndImageContext();
return [outputImage autorelease];
Комментарии:
1. Нет, он использовал drawRect в подклассе UIView, что было бы намного медленнее, чем рисование в контексте закадрового изображения.
2. Что делает это намного быстрее? Почему рисование в закадровом контексте намного дешевле? Я тоже предлагаю закадровый рендеринг, но с прямым доступом к памяти вместо выполнения 25 000 вызовов quartz, которые, я думаю (не измеренные), являются здесь бутылочным горлышком производительности.
3. Это сработало, спасибо! (Извините, я только сейчас возвращаюсь к этому).
Ответ №2:
Если вы хотите работать быстро, вам не следует вызывать явные функции рисования для каждого пикселя. Вы можете выделить память и использовать CGBitmapContextCreate
для создания образа с данными в этой памяти, которая в основном представляет собой массив байтов. Выполните свои вычисления и запишите информацию о цвете (a-r-g-b) непосредственно в этот буфер. Однако вам придется самостоятельно рассчитать точность субпикселей (смешивание).
У меня нет примера под рукой, но поиск CGBitmapContextCreate
должен направить вас в правильном направлении.