Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <h2>A little more detail...</h2> <p>I posted earlier this evening with a consolidation and small addition to what had been said on this page - that can be found at the bottom of this post. I am editing the post at this point, however, to post what I propose is (at least for my requirements, which include modifying pixel data) a better method, as it provides writable data (whereas, as I understand it, the method provided by previous posts and at the bottom of this post provides a read-only reference to data). </p> <p>Method 1: Writable Pixel Information</p> <ol> <li><p>I defined constants</p> <pre><code>#define RGBA 4 #define RGBA_8_BIT 8 </code></pre></li> <li><p>In my UIImage subclass I declared instance variables:</p> <pre><code>size_t bytesPerRow; size_t byteCount; size_t pixelCount; CGContextRef context; CGColorSpaceRef colorSpace; UInt8 *pixelByteData; // A pointer to an array of RGBA bytes in memory RPVW_RGBAPixel *pixelData; </code></pre></li> <li><p>The pixel struct (with alpha in this version)</p> <pre><code>typedef struct RGBAPixel { byte red; byte green; byte blue; byte alpha; } RGBAPixel; </code></pre></li> <li><p>Bitmap function (returns pre-calculated RGBA; divide RGB by A to get unmodified RGB):</p> <pre><code>-(RGBAPixel*) bitmap { NSLog( @"Returning bitmap representation of UIImage." ); // 8 bits each of red, green, blue, and alpha. [self setBytesPerRow:self.size.width * RGBA]; [self setByteCount:bytesPerRow * self.size.height]; [self setPixelCount:self.size.width * self.size.height]; // Create RGB color space [self setColorSpace:CGColorSpaceCreateDeviceRGB()]; if (!colorSpace) { NSLog(@"Error allocating color space."); return nil; } [self setPixelData:malloc(byteCount)]; if (!pixelData) { NSLog(@"Error allocating bitmap memory. Releasing color space."); CGColorSpaceRelease(colorSpace); return nil; } // Create the bitmap context. // Pre-multiplied RGBA, 8-bits per component. // The source image format will be converted to the format specified here by CGBitmapContextCreate. [self setContext:CGBitmapContextCreate( (void*)pixelData, self.size.width, self.size.height, RGBA_8_BIT, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast )]; // Make sure we have our context if (!context) { free(pixelData); NSLog(@"Context not created!"); } // Draw the image to the bitmap context. // The memory allocated for the context for rendering will then contain the raw image pixelData in the specified color space. CGRect rect = { { 0 , 0 }, { self.size.width, self.size.height } }; CGContextDrawImage( context, rect, self.CGImage ); // Now we can get a pointer to the image pixelData associated with the bitmap context. pixelData = (RGBAPixel*) CGBitmapContextGetData(context); return pixelData; } </code></pre></li> </ol> <hr> <h2>Read-Only Data (Previous information) - method 2:</h2> <hr> <p>Step 1. I declared a type for byte:</p> <pre><code> typedef unsigned char byte; </code></pre> <p>Step 2. I declared a struct to correspond to a pixel: </p> <pre><code> typedef struct RGBPixel{ byte red; byte green; byte blue; } RGBPixel; </code></pre> <p>Step 3. I subclassed UIImageView and declared (with corresponding synthesized properties):</p> <pre><code>// Reference to Quartz CGImage for receiver (self) CFDataRef bitmapData; // Buffer holding raw pixel data copied from Quartz CGImage held in receiver (self) UInt8* pixelByteData; // A pointer to the first pixel element in an array RGBPixel* pixelData; </code></pre> <p>Step 4. Subclass code I put in a method named bitmap (to return the bitmap pixel data):</p> <pre><code>//Get the bitmap data from the receiver's CGImage (see UIImage docs) [self setBitmapData: CGDataProviderCopyData(CGImageGetDataProvider([self CGImage]))]; //Create a buffer to store bitmap data (unitialized memory as long as the data) [self setPixelBitData:malloc(CFDataGetLength(bitmapData))]; //Copy image data into allocated buffer CFDataGetBytes(bitmapData,CFRangeMake(0,CFDataGetLength(bitmapData)),pixelByteData); //Cast a pointer to the first element of pixelByteData //Essentially what we're doing is making a second pointer that divides the byteData's units differently - instead of dividing each unit as 1 byte we will divide each unit as 3 bytes (1 pixel). pixelData = (RGBPixel*) pixelByteData; //Now you can access pixels by index: pixelData[ index ] NSLog(@"Pixel data one red (%i), green (%i), blue (%i).", pixelData[0].red, pixelData[0].green, pixelData[0].blue); //You can determine the desired index by multiplying row * column. return pixelData; </code></pre> <p>Step 5. I made an accessor method:</p> <pre><code>-(RGBPixel*)pixelDataForRow:(int)row column:(int)column{ //Return a pointer to the pixel data return &amp;pixelData[row * column]; } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload