2016-06-29 7 views
0

Я работаю над OSX-приложением, которое делает некоторые манипуляции с изображениями на уровне пикселей. Я использую следующий код для доступа к компонентам пиксельных цветов (RGBA) в качестве обычных байтов в качестве указателей uint8.Доступ к CGImageRef для базовых байтов и изменения?

NSImage *image = self.iv.image; 
NSRect imageRect = NSMakeRect(0, 0, image.size.width, image.size.height); 
CGImageRef cgImage = [image CGImageForProposedRect:&imageRect context:NULL hints:nil]; 
NSData *data = (NSData *)CFBridgingRelease(CGDataProviderCopyData(CGImageGetDataProvider(cgImage))); 
    uint8 *pixels = (uint8 *)[data bytes]; 

В этот момент я применить некоторые изменения уровня байт:

for (int i = 0; i < [data length]; i += 4) { ... } 

Изменение этой области памяти не оказывает какого-либо воздействия на первоначальную CGImageRef (который в то время отображается в NSImageView). Я должен сделать следующее, чтобы увидеть обновления изображения соответственно:

CGImageRef newImageRef = CGImageCreate (width, 
              height, 
              bitsPerComponent, 
              bitsPerPixel, 
              bytesPerRow, 
              colorspace, 
              bitmapInfo, 
              provider, 
              NULL, 
              false, 
              kCGRenderingIntentDefault); 

    NSSize size = NSMakeSize(CGImageGetWidth(newImageRef), 
          CGImageGetHeight(newImageRef)); 

    NSImage * newIm = [[NSImage alloc] initWithCGImage:newImageRef size:size]; 

    self.iv.image = newIm; 

Другими словами, байты, которые я получаю обратно изменить только копию исходных байтов, предположительно, в результате CGDataProviderCopyData(CGImageGetDataProvider(cgImage).

Мой вопрос заключается в следующем. Есть ли способ напрямую обращаться к базовым байтам CGImageRef, так что когда я их модифицирую, изображение обновляется на экране, когда я ими манипулирую?

ответ

2

CGImage s неизменяемы. Вы не можете изменить их после их создания.

В вашем коде на звонок [data bytes] указан указатель к constvoid. Вы выбросили const, который получает его для компиляции без предупреждений, но это является нарушением проектного контракта. Запись в буфер, поддерживающая поставщика данных, не является законной и не гарантируется работать, даже если вы создаете из нее новый CGImage.

Я также укажу, что формат данных в буфере может сильно отличаться от того, что вы ожидали. Нет никакой веской причины ожидать, что данные будут 32 бита на пиксель, RGBA против BGRA против ARGB против ... или что-то еще.

Я настоятельно рекомендую вам прочитать разделы о различных объектах изображения в 10.6 AppKit release notes. Прокрутите вниз до «NSImage, CGImage и соответствия полного соответствия CoreGraphics» и прочитайте все следующие разделы, связанные с изображением, до тех пор, пока вы не нажмете «NSComboBox». Раздел «NSBitmapImageRep: сопоставление полного соответствия CoreGraphics и примечания по производительности» является одним из наиболее важных для ваших целей.

Помимо того, что сказано, вы можете просто поддерживать буфер пикселей, который вы выделили себе в любом формате, который вы предпочитаете. Затем, когда вы хотите получить CGImage, создайте его из буфера, нарисуйте с ним и отбросьте его. Любые манипуляции с пикселями будут выполняться в этом буфере.