Getting pixel data on iOS 8 / iPhone 6

I need to get pixel data for a given (x, y) coordinate of a bitmap. Over the years, my code was as follows:

_palettePixelData = CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage));
const UInt8 *rawData = CFDataGetBytePtr(_imagePixelData);

int pixelInfo = ((image.size.width * floorf(pointInImage.y) * image.scale) + floorf(pointInImage.x) * image.scale ) * 4;

CGFloat red   = rawData[pixelInfo + 0] / 255.0;
CGFloat green = rawData[pixelInfo + 1] / 255.0;
CGFloat blue  = rawData[pixelInfo + 2] / 255.0;
CGFloat alpha = rawData[pixelInfo + 3] / 255.0;

      

This works great on iPhone 4 and 5 (not S) running iOS7.

I am now trying to get it to work on an iPhone 6 running iOS8. To do this, I need to make this change:

int pixelInfo = ((image.size.width * floorf(pointInImage.y) * image.scale * 2) + floorf(pointInImage.x) * image.scale ) * 4;

      

Notice the extra * 2

in the code.

I would like to understand why this change is necessary so that I can apply it correctly. Is it related to iOS8 or the 64-bit architecture of the iPhone 6? If it has to do with 64-bit architecture, then it doesn't make sense because:

  • The data pixel itself is still encoded as 4 bytes.
  • It seems like the width of each line of pixel data that has changed due to the extra padding, but the position of the data on that line is the same. those. does n't work when using 8-byte pixels :

    int pixelInfo = ((image.size.width * floorf(pointInImage.y) * image.scale) + floorf(pointInImage.x) * image.scale ) * 8;

Can anyone shed some light on what's going on?

+3


source to share


1 answer


This same exact problem has been pushing me against the wall all week ...

I make my fonts from characters laid out in a grid in a PNG file. On load, I parse the pixels of each character to estimate the exact width. This code has been working well for years and has just started breaking on iPhone 6 (and iPad Mini).

This is NOT due to iOS 8, because the code still works on iPhone 5 with iOS 8.

It is also NOT due to any changes in the compilation process as I can reproduce the problem, on simulators and devices, from the same project.

This is the code that has worked for years:

void PixelMap::LoadPixelData (const char * imageFile)
{
    CFStringRef filename = CFStringCreateWithCString (NULL, imageFile, kCFStringEncodingASCII),
                fileExtension = CFStringCreateWithCString (NULL, "png", kCFStringEncodingASCII);

    // Open image
    CGImageRef image = SpriteManager::CreateNamedImage (filename, fileExtension);

    CFRelease (filename);
    CFRelease (fileExtension);

    if (image == NULL)
    {
        printf ("ERROR: cannot open image \"%s\"\n", imageFile);
        return;
    }

    // Get image information
    CGImageAlphaInfo info = CGImageGetAlphaInfo (image);

    BOOL hasAlpha =
    (
        (info == kCGImageAlphaPremultipliedLast) ||
        (info == kCGImageAlphaPremultipliedFirst) ||
        (info == kCGImageAlphaLast) ||
        (info == kCGImageAlphaFirst)
    );

    PixelFormat pixelFormat;

    if (CGImageGetColorSpace (image))
    {
        if (hasAlpha)
        {
            pixelFormat = format_RGBA8888;
        }
        else
        {
            pixelFormat = format_RGB565;
        }
    }
    else  // NOTE: No colorspace means a mask image
    {
        printf ("ERROR: invalid colour space for \"%s\"\nMust be RGBA8888...\n", imageFile);
        CGImageRelease (image);

        return;
    }

    // Round dimensions up to nearest power of 2
    CGSize imageSize = CGSizeMake (CGImageGetWidth (image), CGImageGetHeight (image));

    NSUInteger width = SpriteManager::MakePowerOf2 (imageSize.width),
               height = SpriteManager::MakePowerOf2 (imageSize.height);

#ifdef DEBUG
    // Check we're not wasting resources with padding
    if (width != imageSize.width || height != imageSize.height)
    {
        printf ("WARNING: texture \"%s\" has padded width and/or height.\n", imageFile);
    }

    // Check texture size is within maximum texture size
    if (width > TEXTURE_MAX_SIZE || height > TEXTURE_MAX_SIZE)
    {
        PANIC ("Texture is too big.");
    }
#endif

    // Store dimensions
    m_width = (int)width;
    m_height = (int)height;

    // Grab the data
    if (pixelFormat == format_RGBA8888)
    {
        // Make a pixel buffer
        Allocate (width * height * 4);

        if (m_data == NULL)
        {
            printf ("ERROR: out of memory for PixelMap of \"%s\"\n", imageFile);
        }
        else
        {
            // Get the pixels
            CGColorSpaceRef colourSpace = CGImageGetColorSpace (image);

            CGContextRef context = CGBitmapContextCreate (m_data, width, height, 8, (width * 4), colourSpace, (kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big));
            CGContextDrawImage (context, CGRectMake (0, 0, CGImageGetWidth (image), CGImageGetHeight (image)), image);

            CGColorSpaceRelease (colourSpace);
            CGContextRelease (context);

#ifdef DEBUG
            printf ("Loaded pixel map from texture \"%s\"\n", imageFile);
#endif
        }
    }
    else
    {
        printf ("ERROR: invalid pixel format for \"%s\"\nMust be RGBA8888...\n", imageFile);
    }

    // Clean up the image
    CGImageRelease (image);
}

      

And this is a much simpler alternative method that I recently tried, which gives the same effect:

void PixelMap::LoadImageData (const char * imageFile)
{
    NSString * filename = [NSString stringWithUTF8String:imageFile];

    UIImage * image = [UIImage imageNamed:filename];

    m_width = (int)image.size.width;
    m_height = (int)image.size.height;

    Allocate (m_width * m_height * 4);

    CFDataRef imageData = CGDataProviderCopyData (CGImageGetDataProvider (image.CGImage));
    const UInt32 * pixels = (const UInt32 *)CFDataGetBytePtr (imageData);

    memcpy (m_data, pixels, m_dataSize);

    CFRelease (imageData);
}

      

This is an example of a font image that I am passing to this function: Font

Examining the results of one of these ways of implementing this function gives:



On iPhone 5 (right) ...

Pixel Map Dump [64, 128 -> 128, 192]

                           ************                         
                         ****************                       
                       ********************                     
                      **********************                    
                     ***********************                    
                     ************************                   
                     ************************                   
                    *************************                   
                    *************************                   
                    *************************                   
                    *************************                   
                    *************************                   
                     ************************                   
                     ************************                   
                     ***********************                    
                     ***********************                    
                      *********************                     
                      *********************                     
                       *******************                      
                       *******************                      
                        *****************                       
                        *****************                       
                        *****************                       
                        *****************                       
                        *****************                       
                        ****************                        
                        ****************                        
                        ****************                        
                        ****************                        
                        ****************                        
                         **************                         
                          ***********                           
                            **********                          
                          *************                         
                         ***************                        
                        *****************                       
                        ******************                      
                       *******************                      
                       ********************                     
                       ********************                     
                      *********************                     
                      *********************                     
                      *********************                     
                      *********************                     
                      *********************                     
                      *********************                     
                      *********************                     
                      *********************                     
                       ********************                     
                       *******************                      
                        ******************                      
                         ***************                        
                          ************                          

      

... and iPhone 6 ...

Pixel Map Dump [64, 128 -> 128, 192]

        **************                       *********          
       *****************                    **************      
       ******************                 ****************      
       ******************                 ****************      
       ******************                *****************      
        *****************               ******************      
         ****************               ******************      
         ****************              *******************      
         ***************               ***********  ******      
         ****************              **********    ****       
         *****************             **********               
         ******************           ***********     ***       
        *******************           ***********   ******      
        ********************          ************ *******      
        ********************          ********************      
        ********************          ********************      
        ********************           *******************      
       *********************           *******************      
       *********************           *******************      
      **********************           *******************      
     ***********************            ******************      
     **********************              *****************      
     **********************              *****************      
     *********************                ***************       
      ******************                    ************        
         ************                         *******           






      ***************                      *************        
     ******************                   **************        
     *******************                 ****************       
     *******************                *****************       
     *******************                *****************       
     *******************                *****************       
      ******************                *****************       
      ******************                ****************        
       ****************                 **************          
      *****************                 ****************        
      ****************                   ****************       
      ******************                  ***************       
      *******************                  ***************      
      ********************                  **************      
      ********************             ***** *************      
      ********************            ********************      
     **********************           ********************      
     **********************           ********************      
     **********************           ********************      
    ************************          ********************      
   *************************          ********************      
   **************************          ******************       
   **************************          *****************        
   **************************           ****************        
    *************************            *************          
      **********    *******                 ********            

      

As you can see, the resulting pixel data was mostly scaled by 1/2. I've blamed color space for a while, but that doesn't seem to be the culprit.

One of the (many) pages I've read leads me to think that the iPhone 6 and other devices demonstrating this issue are using 64 bits per pixel behind the scenes somewhere instead of the usual 32 (despite all attempts to force 32 BPP from my end ).

Go to "Esoteric Layouts": http://www.objc.io/issue-3/moving-pixels-onto-the-screen.html

I really don't want to do "if (iPhone6 ​​|| iPadMini)" to crack work "correctly", but honestly I'm so sick of trying to fix this issue neatly.

Also possibly relevant: iPhone 6 Plus Resolution Clutter: Xcode or Apple Website? for development

0


source







All Articles