كيفية الحصول على RGB قيم بكسل على الصورة على اي فون

StackOverflow https://stackoverflow.com/questions/144250

سؤال

أنا أكتب اي فون التطبيق و تحتاج أساسا إلى تنفيذ شيء ما يعادل 'القطارة' أداة في الفوتوشوب حيث يمكنك لمس نقطة على الصورة والتقاط 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 قبل الحصول على معدلة 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.لقد أعلنت نوع byte:

 typedef unsigned char byte;

الخطوة 2.لقد أعلن البنية لتتوافق مع بكسل:

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

الخطوة 3.أنا ثم subclassed 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.فرعية قانون وضعت في أسلوب يسمى نقطية (العودة إلى الصورة النقطية بكسل البيانات):

//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.لقد قمت accessor الطريقة:

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

نصائح أخرى

هنا الحل أخذ العينات اللون UIImage.

هذا النهج يجعل طلب بكسل في 1px كبيرة RGBA العازلة و يعود اللون الناتج القيم باعتبارها UIColor الكائن.هذا هو أسرع بكثير من معظم مناهج أخرى رأيت يستخدم سوى القليل جدا من الذاكرة.

هذا يجب أن تعمل بشكل جيد على شيء مثل منتقي الألوان ، حيث عادة تحتاج فقط قيمة واحدة محددة بكسل في أي وقت من الأوقات.

Uiimage+منقار.ح

#import <UIKit/UIKit.h>


@interface UIImage (Picker)

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

@end

Uiimage+منقار.م

#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 تمثيل الصورة النقطية.تأكد من أن إطلاق سراح 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;
}

وهذا يستغرق سوى مجموعة نقطة 0.0-1.0 لكل من x و y.على سبيل المثال:

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

هذا يعمل كبيرة بالنسبة لي.أنا جعل بضعة افتراضات مثل بت لكل بكسل و RGBA colorspace ، ولكن هذا يجب أن تعمل في معظم الحالات.

ملاحظة أخرى - أنها تعمل على كلا محاكاة الجهاز بالنسبة لي - لدي مشاكل مع أنه في الماضي بسبب PNG الأمثل الذي حدث عندما ذهب على الجهاز.

أن تفعل شيئا من هذا القبيل في طلبي, أنا خلقت صغيرة قبالة الشاشة CGImageContext ثم جعل UIImage في ذلك.هذا ما سمح لي طريقة سريعة لاستخراج عدد من بكسل في آن واحد.هذا يعني أنه يمكنك تعيين الهدف نقطية في شكل تجد من السهل تحليل, والسماح CoreGraphics القيام بالعمل الشاق تحويل بين نماذج الألوان أو صيغ النقطية.

أنا لا أعرف كيف أن المؤشر إلى بيانات الصورة بشكل صحيح على أساس إعطاء X,Y تنسيق.لا أحد يعرف ؟

pixelPosition = (x+(y*((imagewidth)*BytesPerPixel)));

// الملعب ليست مشكلة مع هذا الجهاز بقدر ما أعرف يمكن السماح صفر...// ( أو انسحبت من الرياضيات ).

استخدام ANImageBitmapRep الذي يعطي بكسل-الحصول على مستوى (القراءة/الكتابة).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top