احصل على وحدات البكسل والألوان من Nsimage
سؤال
لقد قمت بإنشاء كائن nsimage ، وأود بشكل مثالي تحديد عدد كل لون البكسل الذي يحتوي عليه. هل هذا ممكن؟
المحلول
أقترح إنشاء خاص بك سياق نقطية, ، لفها في أ سياق الرسومات ووضع ذلك على أنه السياق الحالي ، إخبار الصورة برسم نفسها, ، ثم الوصول إلى بيانات البيكسل وراء سياق النقطية مباشرة.
سيكون هذا رمزًا أكثر ، ولكنه سيوفر لك رحلة من خلال تمثيل TIFF وإنشاء آلاف أو ملايين الكائنات nscolor. إذا كنت تعمل مع صور من أي حجم ملموس ، فستضيف هذه النفقات بسرعة.
نصائح أخرى
هذا الرمز يجعل NSImage
الى CGBitmapContext
:
- (void)updateImageData {
if (!_image)
return;
// Dimensions - source image determines context size
NSSize imageSize = _image.size;
NSRect imageRect = NSMakeRect(0, 0, imageSize.width, imageSize.height);
// Create a context to hold the image data
CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
CGContextRef ctx = CGBitmapContextCreate(NULL,
imageSize.width,
imageSize.height,
8,
0,
colorSpace,
kCGImageAlphaPremultipliedLast);
// Wrap graphics context
NSGraphicsContext* gctx = [NSGraphicsContext graphicsContextWithCGContext:ctx flipped:NO];
// Make our bitmap context current and render the NSImage into it
[NSGraphicsContext setCurrentContext:gctx];
[_image drawInRect:imageRect];
// Calculate the histogram
[self computeHistogramFromBitmap:ctx];
// Clean up
[NSGraphicsContext setCurrentContext:nil];
CGContextRelease(ctx);
CGColorSpaceRelease(colorSpace);
}
بالنظر إلى سياق صورة نقطية ، يمكننا الوصول إلى بيانات الصورة الخام مباشرة ، وحساب الرسوم البيانية لكل قناة ملونة:
- (void)computeHistogramFromBitmap:(CGContextRef)bitmap {
// NB: Assumes RGBA 8bpp
size_t width = CGBitmapContextGetWidth(bitmap);
size_t height = CGBitmapContextGetHeight(bitmap);
uint32_t* pixel = (uint32_t*)CGBitmapContextGetData(bitmap);
for (unsigned y = 0; y < height; y++)
{
for (unsigned x = 0; x < width; x++)
{
uint32_t rgba = *pixel;
// Extract colour components
uint8_t red = (rgba & 0x000000ff) >> 0;
uint8_t green = (rgba & 0x0000ff00) >> 8;
uint8_t blue = (rgba & 0x00ff0000) >> 16;
// Accumulate each colour
_histogram[kRedChannel][red]++;
_histogram[kGreenChannel][green]++;
_histogram[kBlueChannel][blue]++;
// Next pixel!
pixel++;
}
}
}
@end
لقد نشرت مشروعًا كاملاً ، وهو تطبيق عينة من الكاكاو ، والذي يتضمن ما سبق.
احصل على NSBitmapImageRep
منك NSImage
. ثم يمكنك الوصول إلى وحدات البكسل.
NSImage* img = ...;
NSBitmapImageRep* raw_img = [NSBitmapImageRep imageRepWithData:[img TIFFRepresentation]];
NSColor* color = [raw_img colorAtX:0 y:0];
ربما يكون هذا نهجًا أكثر تبسيطًا للبعض ويقلل من تعقيد الانخفاض في إدارة الذاكرة.
https://github.com/koher/asyimagy
عينة الكودhttps://github.com/koher/asyimagycamerasample
import EasyImagy
let image = Image<RGBA<UInt8>>(nsImage: "test.png") // N.B. init with nsImage
print(image[x, y])
image[x, y] = RGBA(red: 255, green: 0, blue: 0, alpha: 127)
image[x, y] = RGBA(0xFF00007F) // red: 255, green: 0, blue: 0, alpha: 127
// Iterates over all pixels
for pixel in image {
// ...
}
//// Gets a pixel by subscripts Gets a pixel by
let pixel = image[x, y]
// Sets a pixel by subscripts
image[x, y] = RGBA(0xFF0000FF)
image[x, y].alpha = 127
// Safe get for a pixel
if let pixel = image.pixelAt(x: x, y: y) {
print(pixel.red)
print(pixel.green)
print(pixel.blue)
print(pixel.alpha)
print(pixel.gray) // (red + green + blue) / 3
print(pixel) // formatted like "#FF0000FF"
} else {
// `pixel` is safe: `nil` is returned when out of bounds
print("Out of bounds")
}
ابحث عن "الرسم البياني" في وثائق الصورة الأساسية.
استخدام colorAtX
مع NSBitmapImageRep
لا يؤدي دائمًا إلى اللون الصحيح الدقيق.
تمكنت من الحصول على اللون الصحيح مع هذا الرمز البسيط:
[yourImage lockFocus]; // yourImage is just your NSImage variable
NSColor *pixelColor = NSReadPixel(NSMakePoint(1, 1)); // Or another point
[yourImage unlockFocus];