This same exact problem has been driving me up the wall all week...
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).
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:
On an iPhone 5 (correctly)...
Pixel Map Dump [64, 128 -> 128, 192]
************
****************
********************
**********************
***********************
************************
************************
*************************
*************************
*************************
*************************
*************************
************************
************************
***********************
***********************
*********************
*********************
*******************
*******************
*****************
*****************
*****************
*****************
*****************
****************
****************
****************
****************
****************
**************
***********
**********
*************
***************
*****************
******************
*******************
********************
********************
*********************
*********************
*********************
*********************
*********************
*********************
*********************
*********************
********************
*******************
******************
***************
************
...and an iPhone 6...
Pixel Map Dump [64, 128 -> 128, 192]
************** *********
***************** **************
****************** ****************
****************** ****************
****************** *****************
***************** ******************
**************** ******************
**************** *******************
*************** *********** ******
**************** ********** ****
***************** **********
****************** *********** ***
******************* *********** ******
******************** ************ *******
******************** ********************
******************** ********************
******************** *******************
********************* *******************
********************* *******************
********************** *******************
*********************** ******************
********************** *****************
********************** *****************
********************* ***************
****************** ************
************ *******
*************** *************
****************** **************
******************* ****************
******************* *****************
******************* *****************
******************* *****************
****************** *****************
****************** ****************
**************** **************
***************** ****************
**************** ****************
****************** ***************
******************* ***************
******************** **************
******************** ***** *************
******************** ********************
********************** ********************
********************** ********************
********************** ********************
************************ ********************
************************* ********************
************************** ******************
************************** *****************
************************** ****************
************************* *************
********** ******* ********
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.
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).
Skip to 'Esoteric Layouts': http://www.objc.io/issue-3/moving-pixels-onto-the-screen.html
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.
Also possibly relevant: iPhone 6 Plus resolution confusion: Xcode or Apple's website? for development