2015-07-03 4 views
0

Я ищу оптимизацию процедуры, которая извлекает данные пикселя из CGImage. То, как это делается в настоящее время (очень неэффективно), - это создать новый CGContext, нарисовать CGImage в контексте и затем получить данные из контекста.Получение данных пикселов из CGImageRef содержит дополнительные байты?

У меня есть следующая оптимизированная процедура для обработки этого:

CGImageRef imageRef = image.CGImage; 
uint8_t *pixelData = NULL; 

CGDataProviderRef imageDataProvider = CGImageGetDataProvider(imageRef); 
CFDataRef imageData = CGDataProviderCopyData(imageDataProvider); 
pixelData = (uint8_t *)malloc(CFDataGetLength(imageData)); 
CFDataGetBytes(imageData, CFRangeMake(0, CFDataGetLength(imageData)), pixelData); 
CFRelease(imageData); 

Это почти работает. После просмотра и сравнения шестнадцатеричного дампа данных пикселя, полученного с помощью обоих методов, я обнаружил, что в приведенном выше случае имеется 8 байтов из 0 каждый 6360 байт. В противном случае данные идентичны. например enter image description here

А вот сравнение с неоптимизированной версией: enter image description here

После 8 байт 0, правильные пиксельные данные продолжаются. Кто-нибудь знает, почему это происходит?

UPDATE: Вот процедура я оптимизация (отрезал код просто получить информацию о размере и других не важные вещи, соответствующий бит возвращаются пиксельные данные):

CGContextRef context = NULL; 
CGImageRef imageRef = image.CGImage; 
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 

CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst; 

// ... SNIP ... 

context = CGBitmapContextCreate(...); 
CGColorSpaceRelease(colorSpace); 

// ... SNIP ... 

CGContextDrawImage(context, rect, imageRef); 
uint8_t *pixelData = (uint8_t *)CGBitmapContextGetData(context); 

CGContextRelease(context); 

Очевидно, что это является чрезмерным объемом работы только для получения базовых данных пикселя. Создание контекста, а затем рисование в нем. Первая процедура находится в 5-10 раз быстрее. Но, как я уже указывал, данные пикселей, возвращаемые обеими процедурами, почти идентичны, за исключением того, что в оптимизированном коде (выделенном на изображениях) вставлено 8 нулевых байтов каждые 6360 байт.

В противном случае, все остальное же - цветовые значения, порядок байт и т.д.

+1

Непонятно, как вы получили эти два разных пиксельных буфера и то, что квалифицирует их как «оптимизированных», а другое «неоптимизированное». Я не понимаю, почему вы проходите этот процесс, который вы описываете. Либо яснее расскажу, как вы получили эти два пиксельных буфера, либо просто скажите нам, что вы пытаетесь сделать. – Rob

+0

@Rob См. Обновление выше. Я перехожу к процессу, чтобы получить базовые данные пикселя из CGImage, чтобы передать его настраиваемому механизму рендеринга, который работает с отдельными пикселями. – Chris

+0

Я хочу сказать, что если вы хотите получить базовые данные пикселя для изображения, вам не нужно проходить этот процесс кругового отключения. (Этот процесс, однако, полезен при работе с гетерогенными форматами изображений, и вы хотите получить его в одном согласованном формате.) В ответ на вопрос, почему у вас есть дополнительные байты, я бы сделал ставку на то, что 'CGImageGetBytesPerRow' для двух вернется разные значения. – Rob

ответ

2

растровые данные имеют отступы в конце каждой строки пикселей, округлить число байт в строку с точностью до большее значение. (В этом случае кратное 16 байт.)

Это дополнение добавляется, чтобы ускорить обработку и нарисовать изображение.

Вы должны использовать CGImageGetBytesPerRow(), чтобы узнать, сколько байтов занимает каждая строка. Не предполагайте, что это то же самое, что и CGImageGetWidth() * CGImageGetBitsPerPixel()/8; байты на строку могут быть больше.

Помните, что данные за произвольным CGImage могут быть не в том формате, который вы ожидаете. Вы не можете предположить, что все изображения являются ARGB с 32-битовыми пикселями без отступов. Вы должны либо использовать функции CG, чтобы выяснить, какой формат данных может быть, или перерисовать изображение в растровый контекст, который находится в точном формате, который вы ожидаете. Последнее, как правило, намного проще - пусть CG сделает для вас конверсии.

(Вы не показываете, какие параметры вы передаете CGBitmapContextCreate. Вы рассчитываете точный bytesPerRow или вы проходите в 0? Если вы перейдете в 0, CG может добавить для вас дополнение, и вы можете обнаружить, что рисование в контексте происходит быстрее.)

+0

Это похоже на заполнение, а 'CGImageGetBytesPerRow()' на 8 байт больше, чем вычисление в соответствии с шириной изображения. И да, я знаю, что CGImage может быть в самых разных форматах, но ARGB будет применен. И рисование в растровом контексте - это то, что он уже делал, и это просто слишком малоэффективно для метода, который вызывается многократно. – Chris

+0

Я просто провел все утро, пытаясь выяснить, что происходит. Спасибо за это, поддержали. – Vik

 Смежные вопросы

  • Нет связанных вопросов^_^