কীভাবে ইউআইআইমেজ (কোকোয়া টাচ) বা সিজিআইমেজ (কোর গ্রাফিক্স) থেকে পিক্সেল ডেটা পাবেন?


200

আমার একটি ইউআইআইমেজ (কোকো টাচ) রয়েছে। সেখান থেকে, আমি সিজিআইমেজ বা অন্য যে কোনও কিছু উপলভ্য হতে পেরে আমি খুশি। আমি এই ফাংশনটি লিখতে চাই:

- (int)getRGBAFromImage:(UIImage *)image atX:(int)xx andY:(int)yy {
  // [...]
  // What do I want to read about to help
  // me fill in this bit, here?
  // [...]

  int result = (red << 24) | (green << 16) | (blue << 8) | alpha;
  return result;
}

উত্তর:


249

এফওয়াইআই, আমি কেরেমকের উত্তরটি আমার মূল রূপরেখার সাথে সংযুক্ত করেছি, টাইপগুলি সাফ করে দিয়েছি, এটিকে রঙিনের একটি অ্যারে ফিরিয়ে দিতে সাধারণীকরণ করেছি এবং সংকলনের জন্য পুরো জিনিসটি পেয়েছি। ফলাফল এখানে:

+ (NSArray*)getRGBAsFromImage:(UIImage*)image atX:(int)x andY:(int)y count:(int)count
{
    NSMutableArray *result = [NSMutableArray arrayWithCapacity:count];

    // First get the image into your data buffer
    CGImageRef imageRef = [image CGImage];
    NSUInteger width = CGImageGetWidth(imageRef);
    NSUInteger height = CGImageGetHeight(imageRef);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    unsigned char *rawData = (unsigned char*) calloc(height * width * 4, sizeof(unsigned char));
    NSUInteger bytesPerPixel = 4;
    NSUInteger bytesPerRow = bytesPerPixel * width;
    NSUInteger bitsPerComponent = 8;
    CGContextRef context = CGBitmapContextCreate(rawData, width, height,
                    bitsPerComponent, bytesPerRow, colorSpace,
                    kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
    CGColorSpaceRelease(colorSpace);

    CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
    CGContextRelease(context);

    // Now your rawData contains the image data in the RGBA8888 pixel format.
    NSUInteger byteIndex = (bytesPerRow * y) + x * bytesPerPixel;
    for (int i = 0 ; i < count ; ++i)
    {
        CGFloat alpha = ((CGFloat) rawData[byteIndex + 3] ) / 255.0f;
        CGFloat red   = ((CGFloat) rawData[byteIndex]     ) / alpha;
        CGFloat green = ((CGFloat) rawData[byteIndex + 1] ) / alpha;
        CGFloat blue  = ((CGFloat) rawData[byteIndex + 2] ) / alpha;
        byteIndex += bytesPerPixel;

        UIColor *acolor = [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
        [result addObject:acolor];
    }

  free(rawData);

  return result;
}

4
রংগুলি নজিরবিহীন বলতে ভুলবেন না। এছাড়াও, 1 দ্বারা এই গুণগুলি কিছুই করে না।
পিটার হোসি

2
এমনকি যদি এটি সঠিক হয়। যখন গণনাটি একটি বৃহত সংখ্যা হয় (যেমন চিত্রের একটি সারির দৈর্ঘ্য বা পুরো চিত্রের আকারের মতো!) আমি এই পদ্ধতির পারফরম্যান্সটি খুব ভাল করব না কারণ অনেকগুলি ইউআইসিক্লোর অবজেক্ট থাকা সত্যিই ভারী। সত্যিকারের জীবনে যখন আমার পিক্সেল লাগবে তখন ইউআইকোলার ঠিক আছে, (ইউনিকোলারগুলির একটি এনএসআরই আমার পক্ষে অনেক বেশি)। এবং যখন আপনার একগুচ্ছ রঙের প্রয়োজন হবে আমি ইউআইসিএলআর ব্যবহার করব না কারণ আমি সম্ভবত ওপেনএল, ইত্যাদি ব্যবহার করব। আমার মতে এই পদ্ধতির কোনও বাস্তব জীবনের ব্যবহার নেই তবে শিক্ষামূলক উদ্দেশ্যে এটি খুব ভাল।
nacho4d

4
ওয়ে খুব জটিল ম্যালোক কেবল একটি পিক্সেল পড়ার জন্য একটি বিশাল জায়গা।
রাগেরিয়ানস

46
কল অফ ইনস্টল করুন মলকের !!!! আমি নির্দিষ্ট কোড পিক্সেল স্বচ্ছ কিনা তা পরীক্ষা করার জন্য আমি এই কোডটি ব্যবহার করছিলাম এবং পিক্সেলগুলি স্বচ্ছ বলে বোঝানো হয়েছিল যেখানে আমি বোগাসের তথ্য ফিরে পেয়েছিলাম কারণ মেমরিটি প্রথমে পরিষ্কার হয়নি। কলোক ব্যবহার করে (প্রস্থ * উচ্চতা, 4) ম্যালোকের পরিবর্তে কৌশলটি করেছে। বাকি কোডটি দুর্দান্ত, ধন্যবাদ!
ডোনালিয়া

5
এটা অসাধারণ. ধন্যবাদ। ব্যবহারে দ্রষ্টব্য: এক্স এবং ওয়াই হ'ল আরবিজিএ পেতে আরম্ভ করার জন্য চিত্রের মধ্যে স্থানাঙ্ক এবং 'গণনা' সেই পয়েন্ট থেকে পিক্সেল সংখ্যা, বাম থেকে ডানে এবং পরে সারি সারি। উদাহরণস্বরূপ ব্যবহার: একটি সম্পূর্ণ চিত্রের getRGBAsFromImage:image atX:0 andY:0 count:image.size.width*image.size.height জন্য আরজিবিএ পেতে: একটি চিত্রের শেষ সারির জন্য আরজিবিএ পেতে: getRGBAsFromImage:image atX:0 andY:image.size.height-1 count:image.size.width
হ্যারিস

49

এটি করার একটি উপায় হ'ল বিটম্যাপ প্রসঙ্গে ছবিটি আঁকুন যা প্রদত্ত রঙিনক্ষেত্রের জন্য প্রদত্ত বাফার দ্বারা ব্যাক করা আছে (এই ক্ষেত্রে এটি আরজিবি): (নোট করুন এটি চিত্রটির ডেটা সেই বাফারে অনুলিপি করবে, তাই আপনি করবেন প্রতিবার পিক্সেল মান পাওয়ার প্রয়োজন হলে এই অপারেশনটি করার পরিবর্তে এটি ক্যাশে করতে চান)

একটি নমুনা হিসাবে নীচে দেখুন:

// First get the image into your data buffer
CGImageRef image = [myUIImage CGImage];
NSUInteger width = CGImageGetWidth(image);
NSUInteger height = CGImageGetHeight(image);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
unsigned char *rawData = malloc(height * width * 4);
NSUInteger bytesPerPixel = 4;
NSUInteger bytesPerRow = bytesPerPixel * width;
NSUInteger bitsPerComponent = 8;
CGContextRef context = CGBitmapContextCreate(rawData, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);

CGContextDrawImage(context, CGRectMake(0, 0, width, height));
CGContextRelease(context);

// Now your rawData contains the image data in the RGBA8888 pixel format.
int byteIndex = (bytesPerRow * yy) + xx * bytesPerPixel;
red = rawData[byteIndex];
green = rawData[byteIndex + 1];
blue = rawData[byteIndex + 2];
alpha = rawData[byteIndex + 3];

আমি আমার অ্যাপে অনুরূপ কিছু করেছি। একটি স্বেচ্ছাসেবক পিক্সেল উত্তোলন করতে, আপনি কেবলমাত্র 1x1 বিটম্যাপটি একটি পরিচিত বিটম্যাপ ফর্ম্যাট সহ আঁকুন, সিজিবিটম্যাপকন্টেক্সটটির উত্স যথাযথভাবে সামঞ্জস্য করুন।
মার্ক বেসে

5
এই স্মৃতি ফাঁস। কাঁচাডাটা প্রকাশ করুন: ফ্রি (কাঁচাডাটা);
অ্যাডাম ওয়েট

5
CGContextDrawImageতিনটি যুক্তি প্রয়োজন এবং উপরের দুটি মাত্র দেওয়া হয়েছে ... আমার মনে হয় এটি হওয়া উচিতCGContextDrawImage(context, CGRectMake(0, 0, width, height), image)
11114456

25

অ্যাপলের প্রযুক্তিগত প্রশ্নোত্তর কিউএ1509 নিম্নলিখিত সহজ পদ্ধতির দেখায়:

CFDataRef CopyImagePixels(CGImageRef inImage)
{
    return CGDataProviderCopyData(CGImageGetDataProvider(inImage));
}

CFDataGetBytePtrআসল বাইটে পেতে ব্যবহার করুন (এবং CGImageGet*কীভাবে তা ব্যাখ্যা করবেন তা বোঝার জন্য বিভিন্ন পদ্ধতি)।


10
এটি দুর্দান্ত পদ্ধতির নয় কারণ পিক্সেল ফর্ম্যাট প্রতি চিত্রে অনেকগুলি পরিবর্তিত হয়। ১ টি চিত্রের ওরিয়েন্টেশন ২. আলফা উপাদানটির ফর্ম্যাট এবং ৩. আরজিবি-র বাইট ক্রম সহ কয়েকটি পরিবর্তন করতে পারে। কীভাবে এটি করা যায় সে সম্পর্কে আমি ব্যক্তিগতভাবে অ্যাপলের ডক্সকে ডিকোড করার চেষ্টা করে কিছু সময় ব্যয় করেছি, তবে আমি নিশ্চিত নই যে এটির পক্ষে এটি উপযুক্ত। আপনি যদি এটি দ্রুত সম্পন্ন করতে চান তবে কেবল কেরেমকের সমাধান।
টাইলার

1
এই চিত্রটি সর্বদা আমাকে বিজিআর ফর্ম্যাট দেয় যদিও আমি চিত্রটি সংরক্ষণ করি (রঙিন জায়গার আরজিবিএতে আমার অ্যাপের মধ্যে থেকে)
সৌম্যজিৎ

1
@ সৌম্যলজিৎ এটি সিজিআইমেজরিফ ডেটা মূলত যে ফর্ম্যাটটিতে সংরক্ষিত ছিল সে ফর্ম্যাটে ডেটা অনুলিপি করতে চলেছে। বেশিরভাগ ক্ষেত্রে এটি বিজিআরএ হতে চলেছে, তবে এটি ইউইউভিও হতে পারে।
ক্যামেরন লোয়েল পামার

18

বিশ্বাস করা যায়নি যে এখানে একটিও সঠিক উত্তর নেই। পয়েন্টার বরাদ্দ করার প্রয়োজন নেই, এবং অমীমাংসিত মানগুলি এখনও স্বাভাবিক করতে হবে। ধাওয়া কাটাতে, এখানে সুইফট ৪-এর সঠিক সংস্করণ is UIImageকেবল ব্যবহারের জন্য .cgImage

extension CGImage {
    func colors(at: [CGPoint]) -> [UIColor]? {
        let colorSpace = CGColorSpaceCreateDeviceRGB()
        let bytesPerPixel = 4
        let bytesPerRow = bytesPerPixel * width
        let bitsPerComponent = 8
        let bitmapInfo: UInt32 = CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.byteOrder32Big.rawValue

        guard let context = CGContext(data: nil, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo),
            let ptr = context.data?.assumingMemoryBound(to: UInt8.self) else {
            return nil
        }

        context.draw(self, in: CGRect(x: 0, y: 0, width: width, height: height))

        return at.map { p in
            let i = bytesPerRow * Int(p.y) + bytesPerPixel * Int(p.x)

            let a = CGFloat(ptr[i + 3]) / 255.0
            let r = (CGFloat(ptr[i]) / a) / 255.0
            let g = (CGFloat(ptr[i + 1]) / a) / 255.0
            let b = (CGFloat(ptr[i + 2]) / a) / 255.0

            return UIColor(red: r, green: g, blue: b, alpha: a)
        }
    }
}

আপনাকে প্রথমে চিত্রটি বাফারে আঁকতে / রূপান্তর করতে হবে কারণ চিত্রগুলির বিভিন্ন ফর্ম্যাট থাকতে পারে। আপনি পড়তে পারেন এমন একটি ধারাবাহিক বিন্যাসে রূপান্তর করতে এই পদক্ষেপের প্রয়োজন।


আমি কীভাবে এই চিত্রটি আমার চিত্রের জন্য ব্যবহার করতে পারি? চলুন চিত্র ওবজ = ইউআইআইজেজ (নাম দেওয়া হয়েছে: "সবুজ রঙের আইএমজি.পিএনজি")
সাগর সুকোড

let imageObj = UIImage(named:"greencolorImg.png"); imageObj.cgImage?.colors(at: [pt1, pt2])
এরিক অাইগনার

যে মনে রাখা pt1এবং pt2হয় CGPointভেরিয়েবল।
অ্যানবিস

আমার দিন বাঁচিয়েছে :)
দারি

1
@ ইরাকএইগনার কি কাজ করবে যদি আমি কোনও চিত্রের প্রতিটি পিক্সেলের রঙ পেতে চাই? পারফরম্যান্স ব্যয় কত?
অমিত ধস

9

এখানে একটি এসও থ্রেড দেওয়া হয়েছে যেখানে @ ম্যাট চিত্রটি স্থানচ্যুত করে কেবল কাঙ্ক্ষিত পিক্সেলটিকে 1x1 প্রসঙ্গে রেন্ডার করে যাতে পছন্দসই পিক্সেল প্রসঙ্গে একটি পিক্সেলের সাথে প্রান্তিক হয়।


9
NSString * path = [[NSBundle mainBundle] pathForResource:@"filename" ofType:@"jpg"];
UIImage * img = [[UIImage alloc]initWithContentsOfFile:path];
CGImageRef image = [img CGImage];
CFDataRef data = CGDataProviderCopyData(CGImageGetDataProvider(image));
const unsigned char * buffer =  CFDataGetBytePtr(data);

আমি এটি পোস্ট করেছি এবং এটি আমার জন্য কাজ করেছে, তবে বাফার থেকে আবার কোনও ইউআইআইজেমে ফিরে যাচ্ছি আমি এখনও বুঝতে পারি না, কোনও ধারণা?
নিদাল ফখৌরি

8

ইউআইআইমেজ একটি মোড়ক যা বাইটগুলি হ'ল সিজিআইমেজ বা সিআইআইমেজ

মতে UIImage উপর অ্যাপল রেফারেন্স বস্তু অপরিবর্তনীয় এবং আপনি ব্যাকিং বাইট কোন এক্সেস আছে। এটি সত্য যে আপনি সিজিআইমেজ ডেটা অ্যাক্সেস করতে পারবেন যদি আপনি UIImageএকটি CGImage(স্পষ্টভাবে বা সুস্পষ্টভাবে) দিয়ে জনবসতি স্থাপন করেন NULLতবে এটি যদি UIImageকোনও CIImageএবং তদ্বিপরীত দ্বারা ব্যাক হয় তবে তা ফিরে আসবে ।

চিত্র অবজেক্টগুলি তাদের অন্তর্নিহিত চিত্রের ডেটাতে সরাসরি অ্যাক্সেস সরবরাহ করে না। তবে আপনি নিজের অ্যাপ্লিকেশনটিতে ব্যবহারের জন্য অন্যান্য ফর্ম্যাটে চিত্রের ডেটা পুনরুদ্ধার করতে পারেন। বিশেষত, আপনি সিগ্রিমেজ এবং সিআইজেজ বৈশিষ্ট্যগুলি যথাক্রমে কোর গ্রাফিক্স এবং কোর চিত্রের সাথে সামঞ্জস্যপূর্ণ চিত্রটির সংস্করণগুলি পুনরুদ্ধার করতে ব্যবহার করতে পারেন। আপনি পিএনজি বা জেপিইজি ফর্ম্যাটে চিত্রের ডেটা সম্বলিত এনএসডাটা অবজেক্ট তৈরি করতে ইউআইআইমেজপিএনজিআরসিপ্রেসিয়েশন ( :) এবং ইউআইআইজেজজেপিপিগ্রিপ্রেসিয়েশন ( : _ :) ফাংশনও ব্যবহার করতে পারেন ।

এই সমস্যাটি সম্পর্কে সাধারণ কৌশলগুলি around

আপনার বিকল্পগুলি যেমন বলেছে

  • ইউআইআইমেজ পিএনজি সম্প্রসারণ বা জেপিইজি
  • চিত্রটিতে সিজিআইমেজ বা সিআইআইমেজ ব্যাকিং ডেটা রয়েছে কিনা তা নির্ধারণ করুন এবং এটি সেখানে পাবেন

এআরজিবি, পিএনজি, বা জেপিজি ডেটা নয় এবং ডেটা ইতিমধ্যে সিআইআইমেজ সমর্থন করে না এমন আউটপুট চাইলে এগুলির মধ্যে বিশেষত কোনও ভাল কৌশল নয়।

আমার প্রস্তাবনা, সিআইআইমেজ চেষ্টা করে দেখুন

আপনার প্রকল্পটি বিকাশের সময় আপনার পক্ষে পুরোপুরি ইউআইআইজিএজ এড়ানো এবং অন্য কিছু চয়ন করা আরও বুদ্ধিমান হতে পারে। ইউআইআইমেজ, ওবজ-সি চিত্রের মোড়ক হিসাবে, সিজিআইমেজ দ্বারা প্রায়শই সমর্থন করা হয় যেখানে আমরা এটি মর্যাদার জন্য গ্রহণ করি। সিআইআইমেজ একটি আরও ভাল মোড়ক বিন্যাস হতে পারে যে আপনি একটি সিআইসেক্সটেক্সট ব্যবহার করতে পারেন এটি তৈরি কীভাবে জানেন না তা ছাড়াই আপনি যে ফর্ম্যাটটি চান তা বের করার জন্য । আপনার ক্ষেত্রে, বিটম্যাপটি পাওয়া কল করার বিষয়

- রেন্ডার: টু বিটম্যাপ: সারি বাইটস: সীমা: ফর্ম্যাট: কালারস্পেস:

একটি যুক্ত বোনাস হিসাবে আপনি ইমেজটিতে ফিল্টার শৃঙ্খলাবদ্ধ করে ইমেজটিতে সুন্দর ম্যানিপুলেশনগুলি শুরু করতে পারেন। এটি চিত্রটি বিপরীতমুখী হওয়া বা ঘোরানো / ছোট করতে হবে ইত্যাদি সমস্যাগুলির অনেকগুলি সমাধান করে


6

অলি এবং অ্যালগালের উত্তরের উপর ভিত্তি করে, এখানে সুইফ্ট 3-র একটি আপডেট করা উত্তর

public func getRGBAs(fromImage image: UIImage, x: Int, y: Int, count: Int) -> [UIColor] {

var result = [UIColor]()

// First get the image into your data buffer
guard let cgImage = image.cgImage else {
    print("CGContext creation failed")
    return []
}

let width = cgImage.width
let height = cgImage.height
let colorSpace = CGColorSpaceCreateDeviceRGB()
let rawdata = calloc(height*width*4, MemoryLayout<CUnsignedChar>.size)
let bytesPerPixel = 4
let bytesPerRow = bytesPerPixel * width
let bitsPerComponent = 8
let bitmapInfo: UInt32 = CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.byteOrder32Big.rawValue

guard let context = CGContext(data: rawdata, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo) else {
    print("CGContext creation failed")
    return result
}

context.draw(cgImage, in: CGRect(x: 0, y: 0, width: width, height: height))

// Now your rawData contains the image data in the RGBA8888 pixel format.
var byteIndex = bytesPerRow * y + bytesPerPixel * x

for _ in 0..<count {
    let alpha = CGFloat(rawdata!.load(fromByteOffset: byteIndex + 3, as: UInt8.self)) / 255.0
    let red = CGFloat(rawdata!.load(fromByteOffset: byteIndex, as: UInt8.self)) / alpha
    let green = CGFloat(rawdata!.load(fromByteOffset: byteIndex + 1, as: UInt8.self)) / alpha
    let blue = CGFloat(rawdata!.load(fromByteOffset: byteIndex + 2, as: UInt8.self)) / alpha
    byteIndex += bytesPerPixel

    let aColor = UIColor(red: red, green: green, blue: blue, alpha: alpha)
    result.append(aColor)
}

free(rawdata)

return result
}


3

সুইফট 5 সংস্করণ

এখানে প্রদত্ত উত্তরগুলি পুরানো বা ভুল কারণ তারা নিম্নলিখিতটি বিবেচনা করে না:

  1. চিত্রটির পিক্সেল আকার তার পয়েন্ট আকার থেকে পৃথক হতে পারে যা image.size.width/ দ্বারা ফেরত আসেimage.size.height
  2. চিত্রটিতে পিক্সেল উপাদানগুলি ব্যবহার করে বিভিন্ন লেআউট থাকতে পারে যেমন বিজিআরএ, এবিজিআর, এআরজিবি ইত্যাদি বা বিজিআর এবং আরজিবি এর মতো কোনও আলফা উপাদান নেই। উদাহরণস্বরূপ, UIView.drawHierarchy(in:afterScreenUpdates:)পদ্ধতিটি বিজিআরএ চিত্র তৈরি করতে পারে।
  3. চিত্রের সমস্ত পিক্সেলের জন্য রঙের উপাদানগুলি আলফা দ্বারা প্রিম্টিপ্লিট করা যেতে পারে এবং আসল রঙটি পুনরুদ্ধার করতে আলফা দ্বারা বিভাজন করা প্রয়োজন।
  4. ব্যবহৃত মেমরি অপ্টিমাইজেশনের জন্য CGImage, বাইটে পিক্সেল সারির আকার 4 দ্বারা পিক্সেলের প্রস্থের কেবল গুনের চেয়ে বেশি হতে পারে।

এই UIColorজাতীয় সমস্ত বিশেষ ক্ষেত্রে একটি পিক্সেল পেতে নীচে কোডটি সর্বজনীন সুইফট 5 সমাধান সরবরাহ করতে হবে । কোড ব্যবহারযোগ্যতা এবং স্পষ্টতার জন্য অনুকূলিত হয়েছে, পারফরম্যান্সের জন্য নয়

public extension UIImage {

    var pixelWidth: Int {
        return cgImage?.width ?? 0
    }

    var pixelHeight: Int {
        return cgImage?.height ?? 0
    }

    func pixelColor(x: Int, y: Int) -> UIColor {
        assert(
            0..<pixelWidth ~= x && 0..<pixelHeight ~= y,
            "Pixel coordinates are out of bounds")

        guard
            let cgImage = cgImage,
            let data = cgImage.dataProvider?.data,
            let dataPtr = CFDataGetBytePtr(data),
            let colorSpaceModel = cgImage.colorSpace?.model,
            let componentLayout = cgImage.bitmapInfo.componentLayout
        else {
            assertionFailure("Could not get a pixel of an image")
            return .clear
        }

        assert(
            colorSpaceModel == .rgb,
            "The only supported color space model is RGB")
        assert(
            cgImage.bitsPerPixel == 32 || cgImage.bitsPerPixel == 24,
            "A pixel is expected to be either 4 or 3 bytes in size")

        let bytesPerRow = cgImage.bytesPerRow
        let bytesPerPixel = cgImage.bitsPerPixel/8
        let pixelOffset = y*bytesPerRow + x*bytesPerPixel

        if componentLayout.count == 4 {
            let components = (
                dataPtr[pixelOffset + 0],
                dataPtr[pixelOffset + 1],
                dataPtr[pixelOffset + 2],
                dataPtr[pixelOffset + 3]
            )

            var alpha: UInt8 = 0
            var red: UInt8 = 0
            var green: UInt8 = 0
            var blue: UInt8 = 0

            switch componentLayout {
            case .bgra:
                alpha = components.3
                red = components.2
                green = components.1
                blue = components.0
            case .abgr:
                alpha = components.0
                red = components.3
                green = components.2
                blue = components.1
            case .argb:
                alpha = components.0
                red = components.1
                green = components.2
                blue = components.3
            case .rgba:
                alpha = components.3
                red = components.0
                green = components.1
                blue = components.2
            default:
                return .clear
            }

            // If chroma components are premultiplied by alpha and the alpha is `0`,
            // keep the chroma components to their current values.
            if cgImage.bitmapInfo.chromaIsPremultipliedByAlpha && alpha != 0 {
                let invUnitAlpha = 255/CGFloat(alpha)
                red = UInt8((CGFloat(red)*invUnitAlpha).rounded())
                green = UInt8((CGFloat(green)*invUnitAlpha).rounded())
                blue = UInt8((CGFloat(blue)*invUnitAlpha).rounded())
            }

            return .init(red: red, green: green, blue: blue, alpha: alpha)

        } else if componentLayout.count == 3 {
            let components = (
                dataPtr[pixelOffset + 0],
                dataPtr[pixelOffset + 1],
                dataPtr[pixelOffset + 2]
            )

            var red: UInt8 = 0
            var green: UInt8 = 0
            var blue: UInt8 = 0

            switch componentLayout {
            case .bgr:
                red = components.2
                green = components.1
                blue = components.0
            case .rgb:
                red = components.0
                green = components.1
                blue = components.2
            default:
                return .clear
            }

            return .init(red: red, green: green, blue: blue, alpha: UInt8(255))

        } else {
            assertionFailure("Unsupported number of pixel components")
            return .clear
        }
    }

}

public extension UIColor {

    convenience init(red: UInt8, green: UInt8, blue: UInt8, alpha: UInt8) {
        self.init(
            red: CGFloat(red)/255,
            green: CGFloat(green)/255,
            blue: CGFloat(blue)/255,
            alpha: CGFloat(alpha)/255)
    }

}

public extension CGBitmapInfo {

    enum ComponentLayout {

        case bgra
        case abgr
        case argb
        case rgba
        case bgr
        case rgb

        var count: Int {
            switch self {
            case .bgr, .rgb: return 3
            default: return 4
            }
        }

    }

    var componentLayout: ComponentLayout? {
        guard let alphaInfo = CGImageAlphaInfo(rawValue: rawValue & Self.alphaInfoMask.rawValue) else { return nil }
        let isLittleEndian = contains(.byteOrder32Little)

        if alphaInfo == .none {
            return isLittleEndian ? .bgr : .rgb
        }
        let alphaIsFirst = alphaInfo == .premultipliedFirst || alphaInfo == .first || alphaInfo == .noneSkipFirst

        if isLittleEndian {
            return alphaIsFirst ? .bgra : .abgr
        } else {
            return alphaIsFirst ? .argb : .rgba
        }
    }

    var chromaIsPremultipliedByAlpha: Bool {
        let alphaInfo = CGImageAlphaInfo(rawValue: rawValue & Self.alphaInfoMask.rawValue)
        return alphaInfo == .premultipliedFirst || alphaInfo == .premultipliedLast
    }

}

ওরিয়েন্টেশন পরিবর্তন সম্পর্কে কি? আপনার পাশাপাশি ইউআইআইমেজ.ও ওরিয়েন্টেশন পরীক্ষা করার দরকার নেই?
এন্ডাভিড

এছাড়াও, componentLayoutযখন কেবলমাত্র আলফা থাকে তখন আপনার কেসটি অনুপস্থিত .alphaOnly
এন্ডাভিড

@endavid "কেবলমাত্র আলফা" সমর্থিত নয় (খুব বিরল কেস হওয়ার জন্য)। চিত্রের ওরিয়েন্টেশনটি এই কোডের আওতার বাইরে, তবে একটির অরিয়েন্টেশনকে কীভাবে স্বাভাবিক করা যায় সে সম্পর্কে প্রচুর সংস্থান রয়েছে UIImageযা এর পিক্সেল রঙগুলি পড়া শুরু করার আগে আপনি যা করবেন।
ডেসমন্ড হিউম

2

বিভিন্ন উত্তর উপর নির্ভর করে কিন্তু প্রধানত উপর এই , এই কি আমি প্রয়োজন জন্য কাজ করে:

UIImage *image1 = ...; // The image from where you want a pixel data
int pixelX = ...; // The X coordinate of the pixel you want to retrieve
int pixelY = ...; // The Y coordinate of the pixel you want to retrieve

uint32_t pixel1; // Where the pixel data is to be stored
CGContextRef context1 = CGBitmapContextCreate(&pixel1, 1, 1, 8, 4, CGColorSpaceCreateDeviceRGB(), kCGImageAlphaNoneSkipFirst);
CGContextDrawImage(context1, CGRectMake(-pixelX, -pixelY, CGImageGetWidth(image1.CGImage), CGImageGetHeight(image1.CGImage)), image1.CGImage);
CGContextRelease(context1);

এই লাইনের ফলস্বরূপ, আপনার কাছে AARRGGBB ফর্ম্যাটে একটি পিক্সেল থাকবে যা আলফা সর্বদা 4 বাইট স্বাক্ষরযুক্ত পূর্ণসংখ্যায় এফএফ সেট করে pixel1


1

সুইফট 5-এ কোনও ইউআইআইমেজের কাঁচা আরজিবি মানগুলি অ্যাক্সেস করতে অন্তর্নিহিত সিজিআইমেজ এবং এর ডেটাপ্রোভাইডার ব্যবহার করুন:

import UIKit

let image = UIImage(named: "example.png")!

guard let cgImage = image.cgImage,
    let data = cgImage.dataProvider?.data,
    let bytes = CFDataGetBytePtr(data) else {
    fatalError("Couldn't access image data")
}
assert(cgImage.colorSpace?.model == .rgb)

let bytesPerPixel = cgImage.bitsPerPixel / cgImage.bitsPerComponent
for y in 0 ..< cgImage.height {
    for x in 0 ..< cgImage.width {
        let offset = (y * cgImage.bytesPerRow) + (x * bytesPerPixel)
        let components = (r: bytes[offset], g: bytes[offset + 1], b: bytes[offset + 2])
        print("[x:\(x), y:\(y)] \(components)")
    }
    print("---")
}

https://www.ralfebert.de/ios/examples/image-processing/uiimage-raw-pixels/

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.