을 얻는 방법 RGB 값을 화소에 이미지에 iphone
-
02-07-2019 - |
문제
쓰 아이폰 응용 프로그램과 필요한 기본적으로 구현하는 뭔가 해당하는'스포이드'도구,포토샵 터치할 수 있는 시점에 이미지를 캡처 RGB 값을 픽셀에서 질문을 결정과 일치하다.을 받고 있는 uiimage 는 것은 쉬운 부분이지만,하는 방법이 있 변환 있는 uiimage 데이터 비트 맵으로 표현서는 수출에 대해 이 정보를 지정된 픽셀?작동하는 코드 샘플을 것이 대부분의 평가,그리고 나는 염려하지 않으로 알파 값이 있습니다.
해결책
조금 더 세부적 ...
나는 오늘 저녁 일찍이 페이지에서 언급 된 내용에 대한 통합과 작은 추가로 게시했습니다.이 게시물의 맨 아래에서 찾을 수 있습니다. 그러나이 시점에서 게시물을 편집하고 있으며, 내가 제안한 내용을 게시하기 위해 (적어도 픽셀 데이터 수정을 포함하여 내 요구 사항에 대해) 더 나은 방법을 게시 할 수 있습니다. 이전 게시물에 의해 및이 게시물의 맨 아래에서 데이터에 대한 읽기 전용 참조).
방법 1 : 쓰기 가능한 픽셀 정보
상수를 정의했습니다
#define RGBA 4 #define RGBA_8_BIT 8
내 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;
픽셀 구조물 (이 버전의 알파 포함)
typedef struct RGBAPixel { byte red; byte green; byte blue; byte alpha; } RGBAPixel;
비트 맵 함수 (사전 계산 된 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 픽셀 레벨 액세스 (읽기/쓰기)를 제공합니다.