إطار معالجة الصور على أساس المعدن.
MTIImageMTIImageMTIImageCVPixelBufferSwift الفرعيةAppleSilicon الفرعيMetalpetal هو إطار معالجة الصور يعتمد على المعدن المصمم لتوفير المعالجة في الوقت الفعلي للصور والفيديو الثابتة مع واجهات البرمجة السهلة إلى استخدامها.
يغطي هذا الفصل المفاهيم الرئيسية لـ Metalpetal ، وسيساعدك على فهم أفضل لتصميمه وتنفيذه وآثار الأداء وأفضل الممارسات.
تم تصميم Metalpetal مع وضع الأهداف التالية في الاعتبار.
سهل الاستخدام API
يوفر واجهات برمجة التطبيقات الراحة ويتجنب المزالق الشائعة.
أداء
استخدم وحدة المعالجة المركزية و GPU والذاكرة بكفاءة.
قابلية التوسيع
من السهل إنشاء مرشحات مخصصة بالإضافة إلى مكون إضافي وحدة معالجة الصور المخصصة.
swifty
يوفر تجربة السوائل للمبرمجين السريعين.
تشبه بعض المفاهيم الأساسية للمعدنية المعدنية إلى حد كبير تلك الموجودة في إطار الصورة الأساسي لشركة Apple.
يوفر سياق تقييم لتقديم MTIImage s. كما أنه يخزن الكثير من ذاكرة التخزين المؤقت ومعلومات الدولة ، لذلك من المفيد إعادة استخدام السياق كلما كان ذلك ممكنًا.
كائن MTIImage هو تمثيل صورة يتم معالجتها أو إنتاجها. إنه يمثل مباشرة بيانات صورة الصورة النقطية بدلاً من ذلك ، فهو يحتوي على جميع المعلومات اللازمة لإنتاج صورة أو بدقة أكثر بدقة MTLTexture . يتكون من جزأين ، وصفة لكيفية إنتاج الملمس ( MTIImagePromise ) وغيرها من المعلومات مثل كيفية تخزين السياق إلى الصورة ( cachePolicy ) ، وكيف يجب أخذ عينات الملمس ( samplerDescriptor ).
يمثل MTIFilter تأثير معالجة الصور وأي معلمات تتحكم في هذا التأثير. ينتج كائن MTIImage كإخراج. لاستخدام مرشح ، يمكنك إنشاء كائن مرشح ، وتعيين صور الإدخال والمعلمات ، ثم الوصول إلى صورة الإخراج الخاصة به. عادةً ما تمتلك فئة المرشح نواة ثابتة ( MTIKernel ) ، عند الوصول إلى خاصية outputImage الخاصة بها ، فإنها تطلب kernel مع صور الإدخال والمعلمات لإنتاج مخرج MTIImage .
يمثل MTIKernel روتين معالجة الصور. MTIKernel مسؤول عن إنشاء حالة خط أنابيب العرض المقابلة أو حساب المرشح ، وكذلك بناء MTIImagePromise ل MTIImage .
يقوم Metalpetal بالكثير من التحسينات لك تحت الغطاء.
إنه يخلع تلقائيًا وظائف ، حالات kernel ، حالات أخذ العينات ، إلخ.
يستخدم ميزات معدنية مثل المزج القابل للبرمجة ، وأهداف التجسيد بدون ذكرى ، وأكوام الموارد ، وتظليل الأداء المعدني لجعل العرض سريعًا وفعالًا. على MacOS ، يمكن أن يستفيد Metalpetal أيضًا من بنية TBDR لسيليكون Apple.
قبل التقديم ، يمكن للمعدني أن ينظر إلى رسم بياني للصور الخاص بك ومعرفة الحد الأدنى من القوام الوسيط اللازم للقيام بالعرض وتوفير الذاكرة والطاقة والوقت.
يمكنه أيضًا إعادة تنظيم رسم بياني لإحداث الصورة إذا كان من الممكن تسلسل "وصفات" متعددة للتخلص من تمريرات العرض الزائدة عن الحاجة. ( MTIContext.isRenderGraphOptimizationEnabled )
كائنات MTIImage غير قابلة للتغيير ، مما يعني أنها يمكن مشاركتها بأمان بين المواضيع.
ومع ذلك ، فإن كائنات MTIFilter قابلة للتغيير وبالتالي لا يمكن مشاركتها بأمان بين المواضيع.
يحتوي MTIContext على الكثير من الحالات وذاكرة التخزين المؤقت. هناك آلية آمنة من مؤشرات الترابط لكائنات MTIContext ، مما يجعل من الآمن مشاركة كائن MTIContext بين مؤشرات الترابط.
قمة قابلة للتخصيص بالكامل وشظايا وظائف.
MRT (أهداف عرض متعددة).
بشكل عام أداء أفضل. (البيانات القياسية التفصيلية المطلوبة)
مصفوفة اللون
بحث اللون
يستخدم جدول بحث اللون لإعادة تجديد الألوان في الصورة.
الغضب
التعرض
التشبع
سطوع
مقابلة
لون العكس
الاهتزاز
يضبط تشبع الصورة مع الحفاظ على نغمات البشرة.
منحنى لهجة RGB
يمزج أوضاع
مزج مع قناع
تحول
اقتصاص
Pixellate
مركب متعدد الطبقات
الالتفاف النواب
نواب غاوسي ضبابية
تعريف النواب
MPS Sobel
MPS قناع UNSHARP
نواب مربع طمس
ارتفاع تنعيم البشرة
clahe (معادلة الرسم البياني التكيفي المحدودة على النقيض)
طمس العدسة (طمس الخوخ السداسي)
طمس السطح
انتفاخ تشويه
Chroma Key Blend
لون نصفه
شاشة نقطة
زاوية مستديرة (منحنى دائري/مستمر)
جميع مرشحات الصور الأساسية
MTIImage يمكنك إنشاء كائن MTIImage من أي مصدر لبيانات الصورة تقريبًا ، بما في ذلك:
URL S المرجعية ملفات الصور المراد تحميلهاCVImageBufferRef أو CVPixelBufferRef )CIImageMDLTexture let imageFromCGImage = MTIImage ( cgImage : cgImage , isOpaque : true )
let imageFromCIImage = MTIImage ( ciImage : ciImage )
let imageFromCoreVideoPixelBuffer = MTIImage ( cvPixelBuffer : pixelBuffer , alphaType : . alphaIsOne )
let imageFromContentsOfURL = MTIImage ( contentsOf : url )
// unpremultiply alpha if needed
let unpremultipliedAlphaImage = image . unpremultiplyingAlpha ( ) let inputImage = ...
let filter = MTISaturationFilter ( )
filter . saturation = 0
filter . inputImage = inputImage
let outputImage = filter . outputImageMTIImage let options = MTIContextOptions ( )
guard let device = MTLCreateSystemDefaultDevice ( ) , let context = try ? MTIContext ( device : device , options : options ) else {
return
}
let image : MTIImage = ...
do {
try context . render ( image , to : pixelBuffer )
//context.makeCIImage(from: image)
//context.makeCGImage(from: image)
} catch {
print ( error )
}MTIImage let imageView = MTIImageView ( frame : self . view . bounds )
// You can optionally assign a `MTIContext` to the image view. If no context is assigned and `automaticallyCreatesContext` is set to `true` (the default value), a `MTIContext` is created automatically when the image view renders its content.
imageView . context = ...
imageView . image = image إذا كنت ترغب في نقل عملية ترميز أوامر GPU خارج الموضوع الرئيسي ، فيمكنك استخدام MTIThreadSafeImageView . يمكنك تعيين MTIImage إلى MTIThreadSafeImageView في أي موضوع.
يحتوي Metalpetal على واجهة برمجة تطبيقات Swift Swift الآمنة لتوصيل المرشحات. يمكنك استخدام => المشغل في وظيفة FilterGraph.makeImage لتوصيل المرشحات والحصول على صورة الإخراج.
فيما يلي بعض الأمثلة:
let image = try ? FilterGraph . makeImage { output in
inputImage => saturationFilter => exposureFilter => output
} let image = try ? FilterGraph . makeImage { output in
inputImage => saturationFilter => exposureFilter => contrastFilter => blendFilter . inputPorts . inputImage
exposureFilter => blendFilter . inputPorts . inputBackgroundImage
blendFilter => output
} يمكنك توصيل مرشحات Unary ( MTIUnaryFilter ) مباشرة باستخدام => .
للحصول على مرشح مع مدخلات متعددة ، تحتاج إلى الاتصال بأحد inputPorts .
=> يعمل المشغل فقط في طريقة FilterGraph.makeImage .
يمكن توصيل إخراج مرشح واحد واحد فقط output .
العمل مع AVPlayer :
let context = try MTIContext ( device : device )
let asset = AVAsset ( url : videoURL )
let composition = MTIVideoComposition ( asset : asset , context : context , queue : DispatchQueue . main , filter : { request in
return FilterGraph . makeImage { output in
request . anySourceImage! => filterA => filterB => output
} !
}
let playerItem = AVPlayerItem ( asset : asset )
playerItem . videoComposition = composition . makeAVVideoComposition ( )
player . replaceCurrentItem ( with : playerItem )
player . play ( )تصدير الفيديو:
مطلوب Videoio للأمثلة التالية.
import VideoIO
var configuration = AssetExportSession . Configuration ( fileType : . mp4 , videoSettings : . h264 ( videoSize : composition . renderSize ) , audioSettings : . aac ( channels : 2 , sampleRate : 44100 , bitRate : 128 * 1000 ) )
configuration . videoComposition = composition . makeAVVideoComposition ( )
self . exporter = try ! AssetExportSession ( asset : asset , outputURL : outputURL , configuration : configuration )
exporter . export ( progress : { progress in
} , completion : { error in
} )مطلوب Videoio لهذا المثال.
import VideoIO
// Setup Image View
let imageView = MTIImageView ( frame : self . view . bounds )
...
// Setup Camera
let camera = Camera ( captureSessionPreset : . hd1920x1080 , configurator : . portraitFrontMirroredVideoOutput )
try camera . enableVideoDataOutput ( on : DispatchQueue . main , delegate : self )
camera . videoDataOutput ? . videoSettings = [ kCVPixelBufferPixelFormatTypeKey as String : kCVPixelFormatType_420YpCbCr8BiPlanarFullRange ]
...
// AVCaptureVideoDataOutputSampleBufferDelegate
let filter = MTIColorInvertFilter ( )
func captureOutput ( _ output : AVCaptureOutput , didOutput sampleBuffer : CMSampleBuffer , from connection : AVCaptureConnection ) {
guard let pixelBuffer = CMSampleBufferGetImageBuffer ( sampleBuffer ) else {
return
}
let inputImage = MTIImage ( cvPixelBuffer : pixelBuffer , alphaType : . alphaIsOne )
filter . inputImage = inputImage
self . imageView . image = filter . outputImage
} يرجى الرجوع إلى CameraFilterView.swift في مشروع المثال لمعرفة المزيد حول معاينة وتسجيل الفيديو المباشر المصفى.
إعادة استخدام MTIContext كلما كان ذلك ممكنا.
السياقات عبارة عن كائنات ثقيلة الوزن ، لذلك إذا قمت بإنشاء واحدة ، فقم بذلك في أقرب وقت ممكن ، وقم بإعادة استخدامها في كل مرة تحتاج إلى تقديم صورة.
استخدم MTIImage.cachePolicy بحكمة.
استخدم MTIImageCachePolicyTransient عندما لا ترغب في الحفاظ على نتيجة عرض الصورة ، على سبيل المثال عندما تكون الصورة مجرد نتيجة وسيطة في سلسلة مرشح ، وبالتالي يمكن إعادة استخدام الملمس الأساسي لنتيجة العرض. هذا هو الخيار الأكثر كفاءة في الذاكرة. ومع ذلك ، عندما تطلب من السياق تقديم صورة تم تقديمها مسبقًا ، قد يعيد تقديم هذه الصورة منذ إعادة استخدام نسيجها الأساسي.
بشكل افتراضي ، فإن صورة إخراج المرشح لها سياسة transient .
استخدم MTIImageCachePolicyPersistent عندما تريد إعادة استخدام الملمس الأساسي.
بشكل افتراضي ، فإن الصور التي تم إنشاؤها من مصادر خارجية لها السياسة persistent .
فهم أن MTIFilter.outputImage هو خاصية حساب.
في كل مرة تطلب فيها مرشحًا لصورة الإخراج الخاصة به ، قد يمنحك المرشح كائن صورة إخراج جديد حتى لو كانت المدخلات متطابقة مع المكالمة السابقة. لذا أعد استخدام صور الإخراج كلما كان ذلك ممكنًا.
على سبيل المثال،
// ╭→ filterB
// filterA ─┤
// ╰→ filterC
//
// filterB and filterC use filterA's output as their input.في هذه الحالة ، الحل التالي:
let filterOutputImage = filterA . outputImage
filterB . inputImage = filterOutputImage
filterC . inputImage = filterOutputImageأفضل من:
filterB . inputImage = filterA . outputImage
filterC . inputImage = filterA . outputImage إذا كنت ترغب في تضمين MTIShaderLib.h في ملف .metal الخاص بك ، فأنت بحاجة إلى إضافة مسار ملف MTIShaderLib.h إلى Metal Compiler - Header Search Paths ( MTL_HEADER_SEARCH_PATHS ).
على سبيل المثال ، إذا كنت تستخدم cocoapods ، فيمكنك تعيين MTL_HEADER_SEARCH_PATHS على ${PODS_CONFIGURATION_BUILD_DIR}/MetalPetal/MetalPetal.framework/Headers ${PODS_ROOT}/MetalPetal/Frameworks/MetalPetal/Shaders . إذا كنت تستخدم Swift Package Manager ، فقم بتعيين MTL_HEADER_SEARCH_PATHS إلى $(HEADER_SEARCH_PATHS)
يحتوي Metalpetal على آلية مدمجة لترميز وسيطات وظيفة التظليل لك. يمكنك تمرير وسيطات دالة التظليل name: value إلى MTIRenderPipelineKernel.apply(toInputImages:parameters:outputDescriptors:) ، MTIRenderCommand(kernel:geometry:images:parameters:) ، إلخ.
على سبيل المثال ، يمكن أن يكون قاموس المعلمة لوظيفة المعادن vibranceAdjust :
// Swift
let amount : Float = 1.0
let vibranceVector = float4 ( 1 , 1 , 1 , 1 )
let parameters = [ " amount " : amount ,
" vibranceVector " : MTIVector ( value : vibranceVector ) ,
" avoidsSaturatingSkinTones " : true ,
" grayColorTransform " : MTIVector ( value : float3 ( 0 , 0 , 0 ) ) ] // vibranceAdjust metal function
fragment float4 vibranceAdjust (...,
constant float & amount [[ buffer( 0 ) ]],
constant float4 & vibranceVector [[ buffer( 1 ) ]],
constant bool & avoidsSaturatingSkinTones [[ buffer( 2 ) ]],
constant float3 & grayColorTransform [[ buffer( 3 ) ]])
{
...
}
يتم سرد أنواع وسيطة دالة التظليل والأنواع المقابلة لاستخدامها في قاموس المعلمة أدناه.
| نوع الوسيطة وظيفة تظليل | سريع | الهدف-C |
|---|---|---|
| يطفو | يطفو | يطفو |
| int | int32 | int |
| uint | uint32 | uint |
| بول | بول | بول |
| Simd (Float2 ، Float4 ، Float4x4 ، Int4 ، إلخ) | SIMD (مع MetalPetal/Swift ) / MTivector | Mtivector |
| بنية | البيانات / mtidatabuffer | NSDATA / MTIDATABUFFER |
| أخرى (تعويم *، بنية *، إلخ) غير قابلة للتغيير | البيانات / mtidatabuffer | NSDATA / MTIDATABUFFER |
| أخرى (تعويم *، بنية *، إلخ) قابلة للتغيير | mtidatabuffer | mtidatabuffer |
لإنشاء مرشح UNARY مخصص ، يمكنك الفئة الفرعية MTIUnaryImageRenderingFilter وتجاوز الأساليب في فئة SubclassingHooks . أمثلة: MTIPixellateFilter ، MTIVibranceFilter ، MTIUnpremultiplyAlphaFilter ، MTIPremultiplyAlphaFilter ، إلخ.
// Objective-C
@interface MTIPixellateFilter : MTIUnaryImageRenderingFilter
@property ( nonatomic ) float fractionalWidthOfAPixel;
@end
@implementation MTIPixellateFilter
- ( instancetype ) init {
if (self = [ super init ]) {
_fractionalWidthOfAPixel = 0.05 ;
}
return self;
}
+ (MTIFunctionDescriptor *) fragmentFunctionDescriptor {
return [[MTIFunctionDescriptor alloc ] initWithName: @" pixellateEffect " libraryURL: [bundle URLForResource: @" default " withExtension: @" metallib " ]];
}
- ( NSDictionary <NSString *,id> *) parameters {
return @{ @" fractionalWidthOfAPixel " : @(self. fractionalWidthOfAPixel )};
}
@end //Swift
class MTIPixellateFilter : MTIUnaryImageRenderingFilter {
var fractionalWidthOfAPixel : Float = 0.05
override var parameters : [ String : Any ] {
return [ " fractionalWidthOfAPixel " : fractionalWidthOfAPixel ]
}
override class func fragmentFunctionDescriptor ( ) -> MTIFunctionDescriptor {
return MTIFunctionDescriptor ( name : " pixellateEffect " , libraryURL : MTIDefaultLibraryURLForBundle ( Bundle . main ) )
}
} لإنشاء مرشحات أكثر تعقيدًا ، كل ما عليك فعله هو إنشاء نواة ( MTIRenderPipelineKernel / MTIComputePipelineKernel / MTIMPSKernel ) ، ثم قم بتطبيق kernel على صورة (صور) الإدخال. أمثلة: MTIChromaKeyBlendFilter ، MTIBlendWithMaskFilter ، MTIColorLookupFilter ، إلخ.
@interface MTIChromaKeyBlendFilter : NSObject <MTIFilter>
@property ( nonatomic , strong , nullable ) MTIImage *inputImage;
@property ( nonatomic , strong , nullable ) MTIImage *inputBackgroundImage;
@property ( nonatomic ) float thresholdSensitivity;
@property ( nonatomic ) float smoothing;
@property ( nonatomic ) MTIColor color;
@end
@implementation MTIChromaKeyBlendFilter
@synthesize outputPixelFormat = _outputPixelFormat;
+ (MTIRenderPipelineKernel *) kernel {
static MTIRenderPipelineKernel *kernel;
static dispatch_once_t onceToken;
dispatch_once (&onceToken, ^{
kernel = [[MTIRenderPipelineKernel alloc ] initWithVertexFunctionDescriptor: [[MTIFunctionDescriptor alloc ] initWithName: MTIFilterPassthroughVertexFunctionName] fragmentFunctionDescriptor: [[MTIFunctionDescriptor alloc ] initWithName: @" chromaKeyBlend " ]];
});
return kernel;
}
- ( instancetype ) init {
if (self = [ super init ]) {
_thresholdSensitivity = 0.4 ;
_smoothing = 0.1 ;
_color = MTIColorMake ( 0.0 , 1.0 , 0.0 , 1.0 );
}
return self;
}
- (MTIImage *) outputImage {
if (!self. inputImage || !self. inputBackgroundImage ) {
return nil ;
}
return [ self .class.kernel applyToInputImages: @[ self .inputImage, self .inputBackgroundImage]
parameters: @{ @" color " : [MTIVector vectorWithFloat4: (simd_float4){self. color . red , self. color . green , self. color . blue ,self. color . alpha }],
@" thresholdSensitivity " : @(self. thresholdSensitivity ),
@" smoothing " : @(self. smoothing )}
outputTextureDimensions: MTITextureDimensionsMake2DFromCGSize ( self .inputImage.size)
outputPixelFormat: self .outputPixelFormat];
}
@end يمكنك استخدام MTIRenderCommand لإصدار مكالمات سحب متعددة في تمريرة واحدة.
// Create a draw call with kernelA, geometryA, and imageA.
let renderCommandA = MTIRenderCommand ( kernel : self . kernelA , geometry : self . geometryA , images : [ imageA ] , parameters : [ : ] )
// Create a draw call with kernelB, geometryB, and imageB.
let renderCommandB = MTIRenderCommand ( kernel : self . kernelB , geometry : self . geometryB , images : [ imageB ] , parameters : [ : ] )
// Create an output descriptor
let outputDescriptor = MTIRenderPassOutputDescriptor ( dimensions : MTITextureDimensions ( width : outputWidth , height : outputHeight , depth : 1 ) , pixelFormat : . bgra8Unorm , loadAction : . clear , storeAction : . store )
// Get the output images, the output image count is equal to the output descriptor count.
let images = MTIRenderCommand . images ( byPerforming : [ renderCommandA , renderCommandB ] , outputDescriptors : [ outputDescriptor ] )يمكنك أيضًا إنشاء واصفات إخراج متعددة لإخراج صور متعددة في تمريرة واحدة (MRT ، راجع https://en.wikipedia.org/wiki/Multiple_Render_Targets).
عندما لا يتمكن MTIVertex من تناسب احتياجاتك ، يمكنك تنفيذ بروتوكول MTIGeometry لتوفير بيانات قمة الرأس المخصصة إلى تشفير الأوامر.
استخدم واجهة برمجة تطبيقات MTIRenderCommand لإصدار مكالمات السحب وتمرير قياس MTIGeometry المخصص.
في السيناريوهات النادرة ، قد ترغب في الوصول إلى الملمس الأساسي مباشرةً ، واستخدام نواة MPS متعددة في تمريرة واحدة ، أو القيام بالعرض ثلاثي الأبعاد ، أو تشفير أوامر العرض بنفسك.
يوفر بروتوكول MTIImagePromise وصولاً مباشرًا إلى الملمس الأساسي وسياق تقديم خطوة في Metalpetal.
يمكنك إنشاء مصادر إدخال جديدة أو وحدات معالجة مخصصة بالكامل من خلال تنفيذ بروتوكول MTIImagePromise . ستحتاج إلى استيراد وحدة إضافية للقيام بذلك.
الهدف-C
@import MetalPetal.Extension;
سريع
// CocoaPods
import MetalPetal.Extension
// Swift Package Manager
import MetalPetalObjectiveC.Extension
راجع تنفيذ MTIComputePipelineKernel أو MTICLAHELUTRecipe أو MTIImage على سبيل المثال.
إذا تم استخدام قناة ألفا في صورة ما ، فهناك تمثيلان شائعان متاحان: ألفا غير مستقيمة (مستقيمة/غير مرتبطة) ، و alpha premultiplied (المرتبطة).
مع alpha غير المستقرة ، تمثل مكونات RGB لون البكسل ، وتجاهل عتامها.
مع Alpha premultiplied ، تمثل مكونات RGB لون البكسل ، تم تعديلها من أجل التعتيم عن طريق الضرب.
مقابض Metalpetal نوع ألفا بشكل صريح. أنت مسؤول عن توفير نوع ألفا الصحيح أثناء إنشاء الصورة.
هناك ثلاثة أنواع ألفا في Metalpetal.
MTIAlphaType.nonPremultiplied : قيمة ألفا في الصورة ليست مسبقة.
MTIAlphaType.premultiplied : قيمة ألفا في الصورة مسبقة.
MTIAlphaType.alphaIsOne : لا توجد قناة ألفا في الصورة أو الصورة غير شفافة.
عادةً ما تكون كائنات CGImage و CVPixelBuffer و CIImage لها قنوات ألفا مسبقة. MTIAlphaType.alphaIsOne يوصى بشدة إذا كانت الصورة غير شفافة ، مثل CVPixelBuffer من تغذية الكاميرا ، أو CGImage محملة من ملف jpg .
يمكنك استدعاء unpremultiplyingAlpha() أو premultiplyingAlpha() على MTIImage لتحويل نوع ألفا من الصورة.
لأسباب الأداء ، يحدث التحقق من صحة نوع ألفا فقط في بناء التصحيح.
معظم المرشحات في Metalpetal تقبل صور ألفا غير المعدنية والمعتمة وإخراج صور ألفا غير المستقرة.
مرشحات مع خاصية outputAlphaType تقبل مدخلات جميع أنواع ألفا. ويمكنك استخدام outputAlphaType لتحديد نوع ألفا لصورة الإخراج.
مثل MTIBlendFilter ، MTIMultilayerCompositingFilter ، MTICoreImageUnaryFilter ، MTIRGBColorSpaceConversionFilter
المرشحات التي لا تعدل الألوان في الواقع لها قاعدة معالجة ألفا ، وهذا يعني أن أنواع ألفا من صور الإخراج هي نفسها مع صور الإدخال.
مثل MTITransformFilter ، MTICropFilter ، MTIPixellateFilter ، MTIBulgeDistortionFilter
لمزيد من المعلومات حول أنواع ألفا وتكوين ألفا ، يرجى الرجوع إلى هذه المقالة التفاعلية المذهلة من تأليف بارتوس Ciechanowski.
مساحات الألوان حيوية لمعالجة الصور. القيم الرقمية للمكونات الحمراء والأخضر والأزرق ليس لها معنى بدون مساحة لون.
قبل المتابعة في كيفية تعامل Metalpetal Color Paces ، قد ترغب في معرفة مساحة الألوان وكيف تؤثر على تمثيل قيم الألوان. هناك العديد من المقالات على الويب التي تشرح مساحات الألوان ، للبدء ، والاقتراح هو مساحات الألوان - بواسطة Bartosz Ciechanowski.
البرامج والأطر المختلفة لديها طرق مختلفة للتعامل مع مساحات الألوان. على سبيل المثال ، لدى Photoshop مساحة عمل SRGB IEC61966-2.1 ، في حين تستخدم الصورة الأساسية ، بشكل افتراضي ، مساحة ألوان العمل SRGB الخطية.
لا تقوم القوام المعدني بتخزين أي معلومات مساحة ملونة معهم. يحدث معظم معالجة مساحة الألوان في Metalpetal أثناء الإدخال ( MTIImage(...) ) والإخراج ( MTIContext.render... ) من بيانات الصورة.
يعني تحديد مساحة اللون للإدخال أن Metalpetal يجب أن يحول قيم اللون المصدر إلى مساحة اللون المحددة أثناء إنشاء الملمس.
عند التحميل من URL أو CGImage ، يمكنك تحديد مساحة الألوان التي ترغب في أن تكون بيانات الملمس فيها ، باستخدام MTICGImageLoadingOptions . إذا لم تحدد أي خيارات عند تحميل صورة ، فسيتم استخدام مساحة ألوان الجهاز RGB ( MTICGImageLoadingOptions.default ). nil مساحة اللون لا تقلل من مطابقة الألوان ، وهذا هو ما يعادل استخدام مساحة لون صورة الإدخال لإنشاء MTICGImageLoadingOptions . إذا لم يكن نموذج مساحة اللون المحددة RGB ، فسيتم استخدام مساحة ألوان الجهاز RGB كاحتفال.
عند التحميل من CIImage ، يمكنك تحديد مساحة الألوان التي ترغب في أن تكون بيانات الملمس فيها ، باستخدام MTICIImageRenderingOptions . إذا لم تحدد أي خيارات عند تحميل CIImage ، فسيتم استخدام مساحة ألوان الجهاز RGB ( MTICIImageRenderingOptions.default ). تزعج مساحة اللون nil مطابقة الألوان ، يتم تحميل قيم الألوان في مساحة لون العمل في CIContext .
عند تحديد مساحة لون للإخراج ، تخدم مساحة اللون أشبه بعلامة تستخدم للتواصل مع بقية النظام حول كيفية تمثيل قيم الألوان في الإخراج. لا يوجد تحويل مسافة لون فعلي.
يمكنك تحديد مساحة لون الإخراج CGImage باستخدام MTIContext.makeCGImage... أو MTIContext.startTaskTo... طرق مع معلمة colorSpace .
يمكنك تحديد مساحة لون CIImage الإخراج باستخدام MTICIImageCreationOptions .
يفترض Metalpetal أن قيم ألوان الإخراج موجودة في مساحة لون RGB عند عدم تحديد مساحة لون الإخراج.
CVPixelBuffer يستخدم Metalpetal CVMetalTextureCache و IOSurface لخريطة CVPixelBuffer مباشرة إلى القوام المعدني. لذلك لا يمكنك تحديد مساحة ألوان للتحميل من أو تقديم CVPixelBuffer . ومع ذلك ، يمكنك تحديد ما إذا كنت تريد استخدام نسيج بتنسيق Pixel SRGB للرسم البياني.
في المعدن ، إذا كان اسم تنسيق البكسل يحتوي على لاحقة _sRGB ، فسيتم تطبيق ضغط Gamma SRGB وإزالة الضغط أثناء قراءة وكتابة قيم الألوان في البكسل. هذا يعني أن نسيجًا بتنسيق Pixel _sRGB يفترض أن قيم الألوان التي تخزنها هي SRGB Gamma تصحيحها ، عندما تتم قراءة قيم الألوان في تظليل ، يتم إجراء تحويلات RGB الخطية. عندما تتم كتابة قيم الألوان في تظليل ، يتم إجراء تحويلات RGB الخطية إلى SRGB.
يمكنك استخدام MTIRGBColorSpaceConversionFilter لإجراء تحويلات مساحة الألوان. تتوفر وظائف تحويل مساحة الألوان أيضًا في MTIShaderLib.h .
metalpetal::sRGBToLinear (SRGB IEC61966-2.1 إلى SRGB الخطي)metalpetal::linearToSRGB (SRGB الخطي إلى SRGB IEC61966-2.1)metalpetal::linearToITUR709 (SRGB الخطي إلى ITU-R 709)metalpetal::ITUR709ToLinear (ITU-R 709 إلى SRGB الخطي) يمكنك استخدام MTISCNSceneRenderer لإنشاء MTIImage من SCNScene . قد ترغب في التعامل مع مساحة ألوان RGB الخطي للعارض المشهد ، انظر المشكلة #76 الصورة من Scenekit أغمق من المعتاد.
يمكنك استخدام MTISKSceneRenderer لإنشاء MTIImage من SKScene .
يمكنك إنشاء MTIImage s من CIImage s.
يمكنك تقديم MTIImage إلى CIImage باستخدام MTIContext .
يمكنك استخدام CIFilter مباشرة مع MTICoreImageKernel أو فئة MTICoreImageUnaryFilter . (سريع فقط)
انظر metalpetaljs
باستخدام Metalpetaljs ، يمكنك إنشاء خطوط أنابيب ومرشحات باستخدام JavaScript ، مما يجعل من الممكن تنزيل المرشحات/العارضين من "The Cloud".
يوصى باستخدام واجهات برمجة التطبيقات التي تقبل MTICGImageLoadingOptions لتحميل CGImage s والصور من URL ، بدلاً من استخدام واجهات برمجة التطبيقات التي تقبل MTKTextureLoaderOption .
عندما تستخدم واجهات برمجة التطبيقات التي تقبل MTKTextureLoaderOption ، يستخدم Metalpetal ، افتراضيًا ، MTIDefaultTextureLoader لتحميل CGImage ، الصور من URL ، والصور المسماة. يستخدم MTIDefaultTextureLoader MTKTextureLoader داخليًا ولديه بعض الحلول للتناقضات والأخطاء في MTKTextureLoader بتكلفة أداء صغيرة. يمكنك أيضًا إنشاء محمل الملمس الخاص بك عن طريق تطبيق بروتوكول MTITextureLoader . ثم قم بتعيين فئة Loader الملمس الخاصة بك إلى MTIContextOptions.textureLoaderClass عند إنشاء MTIContext .
يمكنك استخدام Cocoapods لتثبيت أحدث إصدار.
use_frameworks!
pod 'MetalPetal'
# Required if you are using Swift.
pod 'MetalPetal/Swift'
# Recommended if you'd like to run MetalPetal on Apple silicon Macs.
pod 'MetalPetal/AppleSilicon'
Swift الفرعيةيوفر الإضافات والتعديلات الخاصة بـ SWIFT الخاصة بآبار واجهة برمجة تطبيقات COBSEIVE-C لتحسين تعيينها إلى سريع. موصى به للغاية إذا كنت تستخدم Swift.
AppleSilicon الفرعييوفر مكتبة التظليل الافتراضية التي تم تجميعها في Language Language V2.3 المطلوب لتمكين دعم المزج القابل للبرمجة على Macs Silicon Apple.
إضافة تبعيات الحزمة إلى تطبيقك
يمكن تشغيل Metalpetal على محاكاة مع Xcode 11+ و MacOS 10.15+.
MetalPerformanceShaders.framework غير متوفر على محاكاة ، لذلك لا تعمل المرشحات التي تعتمد على MetalPerformanceShaders ، مثل MTIMPSGaussianBlurFilter ، MTICLAHEFilter ،.
يدعم Simulator عددًا أقل من الميزات أو حدود التنفيذ المختلفة عن وحدة معالجة الرسومات Apple الفعلية. راجع تطوير تطبيقات المعادن التي تعمل في محاكاة للحصول على التفاصيل.
إذا ألقيت نظرة سريعة على MTIImage ، فسوف يوضح لك الرسم البياني للصورة الذي أنشأته لإنتاج تلك الصورة.

لماذا الهدف-C؟
شكرا لك على النظر في المساهمة في Metalpetal. يرجى قراءة إرشاداتنا المساهمة.
Metalpetal هو مرخص له معهد ماساتشوستس للتكنولوجيا. رخصة
يتم ترخيص الملفات في دليل /MetalPetalExamples بموجب ترخيص منفصل. ترخيص
الوثائق مرخصة CC-By-44.