문제

쓰 아이폰 응용 프로그램과 필요한 기본적으로 구현하는 뭔가 해당하는'스포이드'도구,포토샵 터치할 수 있는 시점에 이미지를 캡처 RGB 값을 픽셀에서 질문을 결정과 일치하다.을 받고 있는 uiimage 는 것은 쉬운 부분이지만,하는 방법이 있 변환 있는 uiimage 데이터 비트 맵으로 표현서는 수출에 대해 이 정보를 지정된 픽셀?작동하는 코드 샘플을 것이 대부분의 평가,그리고 나는 염려하지 않으로 알파 값이 있습니다.

도움이 되었습니까?

해결책

조금 더 세부적 ...

나는 오늘 저녁 일찍이 페이지에서 언급 된 내용에 대한 통합과 작은 추가로 게시했습니다.이 게시물의 맨 아래에서 찾을 수 있습니다. 그러나이 시점에서 게시물을 편집하고 있으며, 내가 제안한 내용을 게시하기 위해 (적어도 픽셀 데이터 수정을 포함하여 내 요구 사항에 대해) 더 나은 방법을 게시 할 수 있습니다. 이전 게시물에 의해 및이 게시물의 맨 아래에서 데이터에 대한 읽기 전용 참조).

방법 1 : 쓰기 가능한 픽셀 정보

  1. 상수를 정의했습니다

    #define RGBA        4
    #define RGBA_8_BIT  8
    
  2. 내 uiimage 서브 클래스에서 인스턴스 변수를 선언했습니다.

    size_t bytesPerRow;
    size_t byteCount;
    size_t pixelCount;
    
    CGContextRef context;
    CGColorSpaceRef colorSpace;
    
    UInt8 *pixelByteData;
    // A pointer to an array of RGBA bytes in memory
    RPVW_RGBAPixel *pixelData;
    
  3. 픽셀 구조물 (이 버전의 알파 포함)

    typedef struct RGBAPixel {
        byte red;
        byte green;
        byte blue;
        byte alpha;
    } RGBAPixel;
    
  4. 비트 맵 함수 (사전 계산 된 RGBA를 반환하고 RGB를 A로 나누기 위해 수정되지 않은 RGB를 얻음) :

    -(RGBAPixel*) bitmap {
        NSLog( @"Returning bitmap representation of UIImage." );
        // 8 bits each of red, green, blue, and alpha.
        [self setBytesPerRow:self.size.width * RGBA];
        [self setByteCount:bytesPerRow * self.size.height];
        [self setPixelCount:self.size.width * self.size.height];
    
        // Create RGB color space
        [self setColorSpace:CGColorSpaceCreateDeviceRGB()];
    
        if (!colorSpace)
        {
            NSLog(@"Error allocating color space.");
            return nil;
        }
    
        [self setPixelData:malloc(byteCount)];
    
        if (!pixelData)
        {
            NSLog(@"Error allocating bitmap memory. Releasing color space.");
            CGColorSpaceRelease(colorSpace);
    
            return nil;
        }
    
        // Create the bitmap context. 
        // Pre-multiplied RGBA, 8-bits per component. 
        // The source image format will be converted to the format specified here by CGBitmapContextCreate.
        [self setContext:CGBitmapContextCreate(
                                               (void*)pixelData,
                                               self.size.width,
                                               self.size.height,
                                               RGBA_8_BIT,
                                               bytesPerRow,
                                               colorSpace,
                                               kCGImageAlphaPremultipliedLast
                                               )];
    
        // Make sure we have our context
        if (!context)   {
            free(pixelData);
            NSLog(@"Context not created!");
        }
    
        // Draw the image to the bitmap context. 
        // The memory allocated for the context for rendering will then contain the raw image pixelData in the specified color space.
        CGRect rect = { { 0 , 0 }, { self.size.width, self.size.height } };
    
        CGContextDrawImage( context, rect, self.CGImage );
    
        // Now we can get a pointer to the image pixelData associated with the bitmap context.
        pixelData = (RGBAPixel*) CGBitmapContextGetData(context);
    
        return pixelData;
    }
    

읽기 전용 데이터 (이전 정보) - 메소드 2 :


1 단계. 바이트 유형을 선언했습니다.

 typedef unsigned char byte;

2 단계. 픽셀에 해당하도록 구조물을 선언했습니다.

 typedef struct RGBPixel{
    byte red;
    byte green;
    byte blue;  
    }   
RGBPixel;

단계 3. 나는 uiimageview를 서브 클래스하고 선언했다 (해당 합성 특성 포함) :

//  Reference to Quartz CGImage for receiver (self)  
CFDataRef bitmapData;   

//  Buffer holding raw pixel data copied from Quartz CGImage held in receiver (self)    
UInt8* pixelByteData;

//  A pointer to the first pixel element in an array    
RGBPixel* pixelData;

단계 4. 서브 클래스 코드 Bitmap이라는 메소드에 넣습니다 (BitMap 픽셀 데이터를 반환하려면) :

//Get the bitmap data from the receiver's CGImage (see UIImage docs)  
[self setBitmapData: CGDataProviderCopyData(CGImageGetDataProvider([self CGImage]))];

//Create a buffer to store bitmap data (unitialized memory as long as the data)    
[self setPixelBitData:malloc(CFDataGetLength(bitmapData))];

//Copy image data into allocated buffer    
CFDataGetBytes(bitmapData,CFRangeMake(0,CFDataGetLength(bitmapData)),pixelByteData);

//Cast a pointer to the first element of pixelByteData    
//Essentially what we're doing is making a second pointer that divides the byteData's units differently - instead of dividing each unit as 1 byte we will divide each unit as 3 bytes (1 pixel).    
pixelData = (RGBPixel*) pixelByteData;

//Now you can access pixels by index: pixelData[ index ]    
NSLog(@"Pixel data one red (%i), green (%i), blue (%i).", pixelData[0].red, pixelData[0].green, pixelData[0].blue);

//You can determine the desired index by multiplying row * column.    
return pixelData;

5 단계. 액세서 방법을 만들었습니다.

-(RGBPixel*)pixelDataForRow:(int)row column:(int)column{
    //Return a pointer to the pixel data
    return &pixelData[row * column];           
}

다른 팁

다음은 uiimage의 색상 샘플링을위한 솔루션입니다.

이 접근법은 요청 된 픽셀을 1px 큰 RGBA 버퍼로 렌더링하고 결과 색상 값을 uicolor 객체로 반환합니다. 이것은 내가 본 대부분의 다른 접근법보다 훨씬 빠르며 메모리를 거의 사용하지 않습니다.

이것은 일반적으로 특정 시간에 특정 픽셀의 값 만 필요로하는 컬러 피커와 같은 것에 대해 잘 작동해야합니다.

uiimage+picker.h

#import <UIKit/UIKit.h>


@interface UIImage (Picker)

- (UIColor *)colorAtPosition:(CGPoint)position;

@end

uiimage+picker.m

#import "UIImage+Picker.h"


@implementation UIImage (Picker)

- (UIColor *)colorAtPosition:(CGPoint)position {

    CGRect sourceRect = CGRectMake(position.x, position.y, 1.f, 1.f);
    CGImageRef imageRef = CGImageCreateWithImageInRect(self.CGImage, sourceRect);

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    unsigned char *buffer = malloc(4);
    CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big;
    CGContextRef context = CGBitmapContextCreate(buffer, 1, 1, 8, 4, colorSpace, bitmapInfo);
    CGColorSpaceRelease(colorSpace);
    CGContextDrawImage(context, CGRectMake(0.f, 0.f, 1.f, 1.f), imageRef);
    CGImageRelease(imageRef);
    CGContextRelease(context);

    CGFloat r = buffer[0] / 255.f;
    CGFloat g = buffer[1] / 255.f;
    CGFloat b = buffer[2] / 255.f;
    CGFloat a = buffer[3] / 255.f;

    free(buffer);

    return [UIColor colorWithRed:r green:g blue:b alpha:a];
}

@end 

당신은에 액세스할 수 없는 비트맵의 데이터가 있는 uiimage 직접 있습니다.

를 얻을 필요가 CGImage 의 표현이 있는 uiimage.다음 CGImage 의 데이터 제공업체에서는 CFData 표현의 bitmap.는지 확인하 릴리스 CFData 할 때.

CGImageRef cgImage = [image CGImage];
CGDataProviderRef provider = CGImageGetDataProvider(cgImage);
CFDataRef bitmapData = CGDataProviderCopyData(provider);

당신은 아마를 보고 싶을 비트맵보의 CGImage 을 얻을 픽셀을 위해,이미지 크기,등등.

Lajos의 대답은 저에게 효과적이었습니다. 픽셀 데이터를 바이트 배열로 가져 오려면 다음을 수행했습니다.

UInt8* data = CFDataGetBytePtr(bitmapData);

더 많은 정보 : cfdataref 선적 서류 비치.

또한 포함해야합니다 CoreGraphics.framework

모두 감사합니다! 이 답변 중 몇 가지를 함께 넣는 것은 다음과 같습니다.

- (UIColor*)colorFromImage:(UIImage*)image sampledAtPoint:(CGPoint)p {
    CGImageRef cgImage = [image CGImage];
    CGDataProviderRef provider = CGImageGetDataProvider(cgImage);
    CFDataRef bitmapData = CGDataProviderCopyData(provider);
    const UInt8* data = CFDataGetBytePtr(bitmapData);
    size_t bytesPerRow = CGImageGetBytesPerRow(cgImage);
    size_t width = CGImageGetWidth(cgImage);
    size_t height = CGImageGetHeight(cgImage);
    int col = p.x*(width-1);
    int row = p.y*(height-1);
    const UInt8* pixel = data + row*bytesPerRow+col*4;
    UIColor* returnColor = [UIColor colorWithRed:pixel[0]/255. green:pixel[1]/255. blue:pixel[2]/255. alpha:1.0];
    CFRelease(bitmapData);
    return returnColor;
}

이것은 x와 y 모두에 대해 포인트 범위 0.0-1.0을 차지합니다. 예시:

UIColor* sampledColor = [self colorFromImage:image
         sampledAtPoint:CGPointMake(p.x/imageView.frame.size.width,
                                    p.y/imageView.frame.size.height)];

이것은 나에게 훌륭하게 작동합니다. 픽셀 및 RGBA 색상 공간 당 비트와 같은 몇 가지 가정을 만들고 있지만 대부분의 경우에도 효과가 있습니다.

또 다른 메모 - 그것은 시뮬레이터와 장치 모두에서 작동하고 있습니다. 기기가 진행될 때 발생한 PNG 최적화로 인해 과거에 문제가 발생했습니다.

내 응용 프로그램에서 비슷한 일을하기 위해 작은 오프 스크린 CGIMAGECONTEXT를 만들어 UIIMAGE를 렌더링했습니다. 이를 통해 한 번에 여러 픽셀을 추출하는 빠른 방법이 가능했습니다. 즉, 구문 분석하기 쉬운 형식으로 대상 비트 맵을 설정하고 CoreGraphics가 색상 모델 또는 비트 맵 형식간에 변환하는 데 어려움을 겪게 할 수 있습니다.

주어진 x, y condination을 기반으로 이미지 데이터에 올바르게 색인하는 방법을 모르겠습니다. 아는 사람 있나요?

pixelPosition = (x+(y*((imageWidth)*bytesperPixel)));

// 피치는 내가 아는 한이 장치에서 문제가되지 않으며 0이 될 수 있습니다 ... // (또는 수학에서 뽑아 냈습니다).

사용 AnimageBitMaprep 픽셀 레벨 액세스 (읽기/쓰기)를 제공합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top