2011-01-07 5 views
7

Pracowałem nad aplikacją, która zmienia obraz kolorowy na szary. Jednak niektóre, jak obraz wychodzi źle. Nie wiem, co jest nie tak z kodem. może parametr, który wprowadzam jest błędny, proszę o pomoc.Zmiana obrazu kolorowego RGB na obraz w skali szarości za pomocą Objective C

UIImage *c = [UIImage imageNamed:@"downRed.png"]; 
CGImageRef cRef = CGImageRetain(c.CGImage); 

NSData* pixelData = (NSData*) CGDataProviderCopyData(CGImageGetDataProvider(cRef)); 

size_t w = CGImageGetWidth(cRef); 
size_t h = CGImageGetHeight(cRef); 

unsigned char* pixelBytes = (unsigned char *)[pixelData bytes]; 

unsigned char* greyPixelData = (unsigned char*) malloc(w*h); 

for (int y = 0; y < h; y++) { 
for(int x = 0; x < w; x++){ 

int iter = 4*(w*y+x); 
int red = pixe lBytes[iter]; 
int green = pixelBytes[iter+1]; 
int blue = pixelBytes[iter+2]; 
greyPixelData[w*y+x] = (unsigned char)(red*0.3 + green*0.59+ blue*0.11); 
    int value = greyPixelData[w*y+x]; 

} 
} 

CFDataRef imgData = CFDataCreate(NULL, greyPixelData, w*h); 


CGDataProviderRef imgDataProvider = CGDataProviderCreateWithCFData(imgData); 


size_t width = CGImageGetWidth(cRef); 
size_t height = CGImageGetHeight(cRef); 
size_t bitsPerComponent = 8; 
size_t bitsPerPixel = 8; 
size_t bytesPerRow = CGImageGetWidth(cRef); 
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray(); 
CGBitmapInfo info = kCGImageAlphaNone; 
CGFloat *decode = NULL; 
BOOL shouldInteroplate = NO; 
CGColorRenderingIntent intent = kCGRenderingIntentDefault; 
    CGDataProviderRelease(imgDataProvider); 

CGImageRef throughCGImage = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpace, info, imgDataProvider, decode, shouldInteroplate, intent); 


UIImage* newImage = [UIImage imageWithCGImage:throughCGImage]; 

CGImageRelease(throughCGImage); 
newImageView.image = newImage; 
+0

Oto podobny wątek, który może pomóc out : http://stackoverflow.com/questions/4030430/iphone-convert-color-image-to-2bit-image-black-white –

+0

Jaki jest błąd, który otrzymujesz? również, użyj opcji "{}", aby sformatować kod w przyszłości. – KevinDTimm

+0

Dziękuję za link. Jednak to mi nie pomogło (nie dostaję żadnego błędu, ale obraz wychodzi dziwnie, wygląda na stagnację.) –

Odpowiedz

4

Wystarczy użyć tego:

- (UIImage *)convertImageToGrayScale:(UIImage *)image 
{ 
    // Create image rectangle with current image width/height 
    CGRect imageRect = CGRectMake(0, 0, image.size.width, image.size.height); 

    // Grayscale color space 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray(); 

    // Create bitmap content with current image size and grayscale colorspace 
    CGContextRef context = CGBitmapContextCreate(nil, image.size.width, image.size.height, 8, 0, colorSpace, kCGImageAlphaNone); 

    // Draw image into current context, with specified rectangle 
    // using previously defined context (with grayscale colorspace) 
    CGContextDrawImage(context, imageRect, [image CGImage]); 

    // Create bitmap image info from pixel data in current context 
    CGImageRef imageRef = CGBitmapContextCreateImage(context); 

    // Create a new UIImage object 
    UIImage *newImage = [UIImage imageWithCGImage:imageRef]; 

    // Release colorspace, context and bitmap information 
    CGColorSpaceRelease(colorSpace); 
    CGContextRelease(context); 
    CFRelease(imageRef); 

    // Return the new grayscale image 
    return newImage; 
} 
19

Jeśli ktoś chce szary skalować obrazy, które zawierają przezroczyste części rozwiązania oferowanego przez digipeople będzie mieć czarną maskę wokół niego. Użyj tego zamiast pozostawić przezroczystą taką jaka jest.

- (UIImage *)imageToGreyImage:(UIImage *)image { 
    // Create image rectangle with current image width/height 
    CGFloat actualWidth = image.size.width; 
    CGFloat actualHeight = image.size.height; 

    CGRect imageRect = CGRectMake(0, 0, actualWidth, actualHeight); 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray(); 

    CGContextRef context = CGBitmapContextCreate(nil, actualWidth, actualHeight, 8, 0, colorSpace, kCGImageAlphaNone); 
    CGContextDrawImage(context, imageRect, [image CGImage]); 

    CGImageRef grayImage = CGBitmapContextCreateImage(context); 
    CGColorSpaceRelease(colorSpace); 
    CGContextRelease(context); 

    context = CGBitmapContextCreate(nil, actualWidth, actualHeight, 8, 0, nil, kCGImageAlphaOnly); 
    CGContextDrawImage(context, imageRect, [image CGImage]); 
    CGImageRef mask = CGBitmapContextCreateImage(context); 
    CGContextRelease(context); 

    UIImage *grayScaleImage = [UIImage imageWithCGImage:CGImageCreateWithMask(grayImage, mask) scale:image.scale orientation:image.imageOrientation]; 
    CGImageRelease(grayImage); 
    CGImageRelease(mask); 

    // Return the new grayscale image 
    return grayScaleImage; 
} 
+0

@YoundukNam Jeśli to odpowiedziałeś na twoje pytanie Powinieneś to zaakceptować, zadziałało to dla mnie! – PickYourPoison

0

wersja Swift, przetestowany i działa w 100%:

func imageToGreyImage(image: UIImage) -> UIImage { 

    // Create image rectangle with current image width/height 
    var actualWidth = image.size.width; 
    var actualHeight = image.size.height; 

    var imageRect = CGRectMake(0, 0, actualWidth, actualHeight); 
    var colorSpace = CGColorSpaceCreateDeviceGray(); 

    var bitmapInfo = CGBitmapInfo(CGImageAlphaInfo.None.rawValue) 

    var context = CGBitmapContextCreate(nil, Int(actualWidth), Int(actualHeight), 8, 0, colorSpace, bitmapInfo); 
    CGContextDrawImage(context, imageRect, image.CGImage); 

    var grayImage = CGBitmapContextCreateImage(context); 
    bitmapInfo = CGBitmapInfo(CGImageAlphaInfo.Only.rawValue) 
    context = CGBitmapContextCreate(nil, Int(actualWidth), Int(actualHeight), 8, 0, nil, bitmapInfo); 
    CGContextDrawImage(context, imageRect, image.CGImage); 
    var mask = CGBitmapContextCreateImage(context); 

    var grayScaleImage = UIImage(CGImage: CGImageCreateWithMask(grayImage, mask), scale: image.scale, orientation: image.imageOrientation) 

    // Return the new grayscale image 
    return grayScaleImage!; 
} 

A jeśli u chcą nie alfa prostu usunąć następujący wiersz:

bitmapInfo = CGBitmapInfo(CGImageAlphaInfo.Only.rawValue) 
+0

Jak wywołać CGImageCreateWithMask w Swift 3? Przekształciłem resztę, ale walczę z tą funkcją. – Jeremiah