La image cargada desde mi server tiene colors incorrectos en la aplicación iPad.

Estoy desarrollando una aplicación para iPad que presenta imágenes de un fotógrafo. Esas fotos se cargan en un server web y se envían directamente a través de la aplicación, donde se descargan y se muestran utilizando el siguiente método:

if([[NSFileManager defaultManager] fileExistsAtPath:[url path]]){ CGImageSourceRef source = CGImageSourceCreateWithURL((CFURLRef)url, NULL); CGImageRef cgImage = nil; if(source){ cgImage = CGImageSourceCreateImageAtIndex(source, 0, (CFDictionaryRef)dict); } UIImage *retImage = [UIImage imageWithCGImage:cgImage]; if(cgImage){ CGImageRelease(cgImage); } if(source){ CFRelease(source); } return retImage; } 

Puedo observar un cambio importante en la visualización de los colors de las fotos entre la image original (que es la misma cuando se muestra desde el disco o desde la web en mi Mac y la Mac del fotógrafo) y en el iPad (el resultado es incorrecto en la aplicación e incluso en Safari).

Después de una búsqueda, encontré algunas publicaciones que explicaban cómo iDevices no usan el perfil de color embedded, así que descubrí que iba por este path. Las fotos se guardan con la siguiente información:

espacio de colores: RGB, colorprofile: sRGB iec ...

Descubrí en algunos artículos (por ejemplo, este enlace de imageoptim o analogsenses ) que debería save la image para la export del dispositivo convirtiéndola en sRGB, sin include el perfil de color, pero no puedo saber cómo podría hacerlo. Cada vez que intenté (no tengo Photoshop, por lo que usé la command-line ImageMagick), la image resultante tiene la siguiente información, y aún no se muestra correctamente en mi iPad (y en cualquier otro iPad que haya probado):

espacio de colores: RGB

Aquí hay un ejemplo de una image que no se muestra correctamente en el iPhone o iPad, pero sí en la web.

Me gustaría transformarlo para mostrarlo correctamente, cualquier Idea sería realmente bienvenida 🙂

[EDIT] He logrado get una image correcta usando las opciones de "save for web" de photoshop usando los siguientes parameters: ok parámetros de exportación de photoshop Pero aún no puedo aplicar esas configuraciones automáticamente a todas mis imágenes.

    Para leer una image, solo usa:

     UIImage *image = [UIImage imageWithContentsOfFile:path]; 

    En cuanto al problema del perfil de color, intente con la herramienta de command-line sips para arreglar los files de image. Algo como:

     mkdir converted sips -m "/System/Library/ColorSync/Profiles/sRGB Profile.icc" *.JPG --out converted 

    Puede get primero el espacio de color a través de CGImage.

     @property(nonatomic, readonly) CGImageRef CGImage CGColorSpaceRef CGImageGetColorSpace ( CGImageRef image ); 

    Y depping del colorSpace aplica una conversión de formatting. Entonces, para get el espacio de color de una image, harías:

     CGColorSpaceRef colorspace = CGImageGetColorSpace([myUIImage CGImage]); 

    Nota: asegúrese de seguir las reglas get / create / copy para objects CG.

    Conversión de color a RGB8 (también se puede aplicar a RGB16 o RGB32, cambiando los bits por componente en el método newBitmapRGBA8ContextFromImage ):

     // Create a bitmap unsigned char *bitmap = [ImageHelper convertUIImageToBitmapRGBA8:image]; // Create a UIImage using the bitmap UIImage *imageCopy = [ImageHelper convertBitmapRGBA8ToUIImage:bitmap withWidth:width withHeight:height]; // Display the image copy on the GUI UIImageView *imageView = [[UIImageView alloc] initWithImage:imageCopy]; 

    ImageHelper.h

     #import <Foundation/Foundation.h> @interface ImageHelper : NSObject { } /** Converts a UIImage to RGBA8 bitmap. @param image - a UIImage to be converted @return a RGBA8 bitmap, or NULL if any memory allocation issues. Cleanup memory with free() when done. */ + (unsigned char *) convertUIImageToBitmapRGBA8:(UIImage *)image; /** A helper routine used to convert a RGBA8 to UIImage @return a new context that is owned by the caller */ + (CGContextRef) newBitmapRGBA8ContextFromImage:(CGImageRef)image; /** Converts a RGBA8 bitmap to a UIImage. @param buffer - the RGBA8 unsigned char * bitmap @param width - the number of pixels wide @param height - the number of pixels tall @return a UIImage that is autoreleased or nil if memory allocation issues */ + (UIImage *) convertBitmapRGBA8ToUIImage:(unsigned char *)buffer withWidth:(int)width withHeight:(int)height; @end 

    ImageHelper.m

     #import "ImageHelper.h" @implementation ImageHelper + (unsigned char *) convertUIImageToBitmapRGBA8:(UIImage *) image { CGImageRef imageRef = image.CGImage; // Create a bitmap context to draw the uiimage into CGContextRef context = [self newBitmapRGBA8ContextFromImage:imageRef]; if(!context) { return NULL; } size_t width = CGImageGetWidth(imageRef); size_t height = CGImageGetHeight(imageRef); CGRect rect = CGRectMake(0, 0, width, height); // Draw image into the context to get the raw image data CGContextDrawImage(context, rect, imageRef); // Get a pointer to the data unsigned char *bitmapData = (unsigned char *)CGBitmapContextGetData(context); // Copy the data and release the memory (return memory allocated with new) size_t bytesPerRow = CGBitmapContextGetBytesPerRow(context); size_t bufferLength = bytesPerRow * height; unsigned char *newBitmap = NULL; if(bitmapData) { newBitmap = (unsigned char *)malloc(sizeof(unsigned char) * bytesPerRow * height); if(newBitmap) { // Copy the data for(int i = 0; i < bufferLength; ++i) { newBitmap[i] = bitmapData[i]; } } free(bitmapData); } else { NSLog(@"Error getting bitmap pixel data\n"); } CGContextRelease(context); return newBitmap; } + (CGContextRef) newBitmapRGBA8ContextFromImage:(CGImageRef) image { CGContextRef context = NULL; CGColorSpaceRef colorSpace; uint32_t *bitmapData; size_t bitsPerPixel = 32; size_t bitsPerComponent = 8; size_t bytesPerPixel = bitsPerPixel / bitsPerComponent; size_t width = CGImageGetWidth(image); size_t height = CGImageGetHeight(image); size_t bytesPerRow = width * bytesPerPixel; size_t bufferLength = bytesPerRow * height; colorSpace = CGColorSpaceCreateDeviceRGB(); if(!colorSpace) { NSLog(@"Error allocating color space RGB\n"); return NULL; } // Allocate memory for image data bitmapData = (uint32_t *)malloc(bufferLength); if(!bitmapData) { NSLog(@"Error allocating memory for bitmap\n"); CGColorSpaceRelease(colorSpace); return NULL; } //Create bitmap context context = CGBitmapContextCreate(bitmapData, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast); // RGBA if(!context) { free(bitmapData); NSLog(@"Bitmap context not created"); } CGColorSpaceRelease(colorSpace); return context; } + (UIImage *) convertBitmapRGBA8ToUIImage:(unsigned char *) buffer withWidth:(int) width withHeight:(int) height { size_t bufferLength = width * height * 4; CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer, bufferLength, NULL); size_t bitsPerComponent = 8; size_t bitsPerPixel = 32; size_t bytesPerRow = 4 * width; CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB(); if(colorSpaceRef == NULL) { NSLog(@"Error allocating color space"); CGDataProviderRelease(provider); return nil; } CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedLast; CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault; CGImageRef iref = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, // data provider NULL, // decode YES, // should interpolate renderingIntent); uint32_t* pixels = (uint32_t*)malloc(bufferLength); if(pixels == NULL) { NSLog(@"Error: Memory not allocated for bitmap"); CGDataProviderRelease(provider); CGColorSpaceRelease(colorSpaceRef); CGImageRelease(iref); return nil; } CGContextRef context = CGBitmapContextCreate(pixels, width, height, bitsPerComponent, bytesPerRow, colorSpaceRef, bitmapInfo); if(context == NULL) { NSLog(@"Error context not created"); free(pixels); } UIImage *image = nil; if(context) { CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, width, height), iref); CGImageRef imageRef = CGBitmapContextCreateImage(context); // Support both iPad 3.2 and iPhone 4 Retina displays with the correct scale if([UIImage respondsToSelector:@selector(imageWithCGImage:scale:orientation:)]) { float scale = [[UIScreen mainScreen] scale]; image = [UIImage imageWithCGImage:imageRef scale:scale orientation:UIImageOrientationUp]; } else { image = [UIImage imageWithCGImage:imageRef]; } CGImageRelease(imageRef); CGContextRelease(context); } CGColorSpaceRelease(colorSpaceRef); CGImageRelease(iref); CGDataProviderRelease(provider); if(pixels) { free(pixels); } return image; } @end 

    @PhilippeAuriach Creo que podría tener problemas con [UIImage imageWithCGImage:cgImage] , Mi sugerencia es utilizar [UIImage imageWithContentsOfFile:path] lugar de arriba.

    Debajo del código podría ayudarlo.

     if([[NSFileManager defaultManager] fileExistsAtPath:[url path]]){ //Provide image path here... UIImage *image = [UIImage imageWithContentsOfFile:path]; if(image){ return image; }else{ //Return default image return image; } }