在iOS 8 / iPhone 6上获取像素数据 [英] Getting pixel data on iOS 8 / iPhone 6

查看:139
本文介绍了在iOS 8 / iPhone 6上获取像素数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要检索位图图像的给定(x,y)坐标的像素数据。多年来,我的代码如下:

I need to retrieve the pixel data for a given (x, y) coordinate of a bitmap image. For years my code has been 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;

这适用于运行iOS7的iPhone 4和5(不是S)。

This works perfectly on my iPhone 4 and 5 (not the S) running iOS7.

我现在正试图让它在运行iOS8的iPhone 6上运行。为此,我需要进行此更改:

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

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

请注意代码中的额外 * 2

Note the extra * 2 in the code.

我想了解为什么这个更改是必要的,这样我才能正确应用它。它与iOS8或iPhone 6的64位架构相关联?如果它是由于64位架构,那么因为它是没有意义的:

I'd like to understand why this change is necessary so that I can apply it correctly. It is linked to iOS8 or to the 64-bit architecture of the iPhone 6? If it's due to the 64-bit architecture then it doesn't make sense to be because:


  1. 像素数据本身仍被编码为4个字节。

  2. 似乎这是由于额外填充而改变的每行像素数据的宽度,但该行上数据的位置是相同的。即假设8字节像素工作:

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?

推荐答案

同样的问题一直在推动我整个星期都在墙上...

This same exact problem has been driving me up the wall all week...

我从PNG文件中网格中布置的字符中做我的字体。加载时,我会分析每个字符的像素以评估确切的宽度。这段代码多年来一直运作良好,刚刚开始打破iPhone 6(和iPad Mini)。

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

这不是因为iOS 8,因为代码仍然存在适用于iOS 8的iPhone 5。

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

这也不是因为编译过程有任何变化,因为我可以在模拟器和设备上重现问题,非常相同的项目。

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

这是多年来一直运作的代码:

This is the code that's 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 have recently tried that yields the exact 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 font image I pass into this function:

调查以上任何一种方式的输出实现此功能产生:

Investigating the outputs from either of these ways of implementing this function yields:

在iPhone 5上(正确)...

On an iPhone 5 (correctly)...

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

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

...和iPhone 6 ...

...and an iPhone 6...

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

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






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

如您所见,结果像素数据基本上已缩放1/2。有一段时间我一直在责备色彩空间,但这似乎并不是罪魁祸首。

As you can see, the resultant pixel data has basically been scaled by 1/2. For awhile I was blaming the colour space, but that doesn't seem to be the culprit.

我读过这个(很多)页面中的一个让我感到惊讶我认为iPhone 6和其他出现此问题的设备在幕后某处使用64位/像素,而不是通常的32位(尽管所有人都试图强迫32 BPP)。

One of the (many) pages I've read around this makes me think that the iPhone 6 and other devices exhibiting this problem 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).

跳至'Esoteric Layouts': http ://www.objc.io/issue-3/moving-pixels-onto-the-screen.html

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

我真的不想做一个'if(iPhone6 || iPadMini)做其他人正常工作'类型的东西,但说实话,我已经厌倦了试图整齐地解决这个问题。

I really don't want to do an 'if (iPhone6 || iPadMini) do hack else work properly' type thing, but to be honest, I'm so fed up with trying to fix this problem neatly.

也可能相关: iPhone 6 Plus分辨率混乱:Xcode还是Apple的网站?用于开发

这篇关于在iOS 8 / iPhone 6上获取像素数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆