这个问题一直困扰着我整整一周...
我使用 PNG 文件中网格中的字符来制作字体。加载时,我分析每个字符的像素以评估确切的宽度。这段代码多年来一直运行良好,并且刚刚开始在 iPhone 6(和 iPad Mini)上破解。
这与 iOS 8 无关,因为该代码仍然适用于装有 iOS 8 的 iPhone 5。
这也不是因为编译过程发生了任何变化,因为我可以在模拟器和设备上从同一个项目中重现问题。
这是使用多年的代码:
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);
}
这是我最近尝试过的一种更简单的替代方法,可以产生完全相同的效果:
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);
}
这是我传递给此函数的示例字体图像:
调查实现此功能的这两种方式的输出:
在 iPhone 5 上(正确)...
Pixel Map Dump [64, 128 -> 128, 192]
************
****************
********************
**********************
***********************
************************
************************
*************************
*************************
*************************
*************************
*************************
************************
************************
***********************
***********************
*********************
*********************
*******************
*******************
*****************
*****************
*****************
*****************
*****************
****************
****************
****************
****************
****************
**************
***********
**********
*************
***************
*****************
******************
*******************
********************
********************
*********************
*********************
*********************
*********************
*********************
*********************
*********************
*********************
********************
*******************
******************
***************
************
...还有一部 iPhone 6...
Pixel Map Dump [64, 128 -> 128, 192]
************** *********
***************** **************
****************** ****************
****************** ****************
****************** *****************
***************** ******************
**************** ******************
**************** *******************
*************** *********** ******
**************** ********** ****
***************** **********
****************** *********** ***
******************* *********** ******
******************** ************ *******
******************** ********************
******************** ********************
******************** *******************
********************* *******************
********************* *******************
********************** *******************
*********************** ******************
********************** *****************
********************** *****************
********************* ***************
****************** ************
************ *******
*************** *************
****************** **************
******************* ****************
******************* *****************
******************* *****************
******************* *****************
****************** *****************
****************** ****************
**************** **************
***************** ****************
**************** ****************
****************** ***************
******************* ***************
******************** **************
******************** ***** *************
******************** ********************
********************** ********************
********************** ********************
********************** ********************
************************ ********************
************************* ********************
************************** ******************
************************** *****************
************************** ****************
************************* *************
********** ******* ********
如您所见,得到的像素数据基本上已经缩放了 1/2。有一段时间我一直在指责色彩空间,但这似乎不是罪魁祸首。
我读过的(许多)页面之一让我认为 iPhone 6 和其他出现此问题的设备在幕后某处使用每像素 64 位而不是通常的 32 位(尽管所有尝试强制32 BPP 从我这边)。
跳到“深奥的布局”:http://www.objc.io/issue-3/moving-pixels-onto-the-screen.html
我真的不想做“if (iPhone6 || iPadMini) do hack else work normal”之类的事情,但老实说,我已经厌倦了试图巧妙地解决这个问题。
也可能相关:iPhone 6 Plus resolution confusion: Xcode or Apple's website? for development