Структура обработки изображений на основе металла.
MTIImageMTIImageMTIImageCVPixelBufferSwiftAppleSiliconMetalpetal-это структура обработки изображений, основанная на металле, предназначенной для обеспечения обработки в реальном времени для неподвижных изображений и видео с простыми в использовании интерфейсов программирования.
Эта глава охватывает ключевые концепции металлической и поможет вам лучше понять его дизайн, реализацию, последствия для производительности и лучшие практики.
Metalpetal разработан с учетом следующих целей.
Простой в использовании API
Обеспечивает удобство API и избегает общих ловушек.
Производительность
Эффективно используйте процессор, графический процессор и память.
Расширяемость
Легко создавать пользовательские фильтры, а также подключить пользовательский блок обработки изображений.
Свифти
Обеспечивает жидкий опыт для программистов Swift.
Некоторые из основных концепций металлической, очень похожи на конструкции в основной структуре изображения Apple.
Обеспечивает контекст оценки для рендеринга MTIImage s. В нем также хранится много кешей и информации о состоянии, поэтому, когда это возможно, более эффективно использовать контекст.
Объект MTIImage - это представление изображения, которое для обработки или произведения. Вместо этого он напрямую представляет данные растрового изображения, он имеет всю информацию, необходимую для создания изображения или, точнее, MTLTexture . Он состоит из двух частей, рецепта того, как создать текстуру ( MTIImagePromise ) и другую информацию, такую как то, как контекст кэширует изображение ( cachePolicy ), и как следует отобрать текстуру ( samplerDescriptor ).
MTIFilter представляет эффект обработки изображения и любые параметры, которые управляют этим эффектом. Он производит объект MTIImage в качестве вывода. Чтобы использовать фильтр, вы создаете объект фильтра, устанавливаете его входные изображения и параметры, а затем получают доступ к его выходному изображению. Как правило, класс фильтров владеет статическим ядром ( MTIKernel ), когда вы получаете доступ к его свойству outputImage , он просит ядро с входными изображениями и параметрами для получения выходного MTIImage .
MTIKernel представляет собой процедуру обработки изображений. MTIKernel отвечает за создание соответствующего рендеринга или вычислительного состояния трубопровода для фильтра, а также для создания MTIImagePromise для MTIImage .
Metalpetal делает для вас много оптимизации под капюшоном.
Он автоматически кэширует функции, состояния ядра, состояния пробоотборника и т. Д.
В нем используются металлические функции, такие как программируемое смешивание, целевые показатели рендеринга без памяти, кучи ресурсов и металлические шейдеры, чтобы сделать рендеринг быстро и эффективным. На macOS металлический, также может воспользоваться преимуществами архитектуры TBDR яблочного кремния.
Перед рендерингом Metalpetal может изучить ваш график рендеринга изображения и выяснить минимальное количество промежуточных текстур, необходимых для выполнения рендеринга, сохранения памяти, энергии и времени.
Он также может реорганизовать график рендеринга изображения, если могут быть объединены несколько «рецептов» для устранения избыточных проходов рендеринга. ( MTIContext.isRenderGraphOptimizationEnabled )
Объекты MTIImage неизменны, что означает, что их можно безопасно обмениваться среди потоков.
Тем не менее, объекты MTIFilter являются изменчивыми и, следовательно, не могут быть безопасно поделиться между потоками.
MTIContext содержит много состояний и кэшей. Для объектов MTIContext есть механизм, защищенный от потока, что делает безопасным делиться объектом MTIContext среди потоков.
Полностью настраиваемые функции вершины и фрагмента.
MRT (множество целей рендеринга) Поддержка.
Вообще лучшая производительность. (Подробные контрольные данные необходимы)
Цветная матрица
Поиск цвета
Использует таблицу поиска цветов, чтобы переназначить цвета в изображении.
Непрозрачность
Контакт
Насыщенность
Яркость
Контраст
Цвет инвертирует
Вибрация
Регулирует насыщение изображения, сохраняя приятные оттенки кожи.
Кривая тона RGB
Смесительные режимы
Смешайте с маской
Преобразование
Обрезать
Пикселлат
Многослойный композит
Депутаты свертки
Депутаты Гауссоны Blur
Определение депутатов
Депутаты Собел
Депутаты без посадки маски
Депутаты Box Blur
Сглаживание кожи высокого прохода
CLAHE (адаптивная выравнивание гистограммы с ограниченной сроком
Размытие линз (шестиугольное Bokeh Blur)
Поверхностное размытие
Выпуклое искажение
Ключевая смесь Chroma
Цветный полуфтона
Точечный экран
Круглый угол (круговая/непрерывная кривая)
Все основные фильтры изображения
MTIImage Вы можете создать объект MTIImage практически из любого источника данных изображения, включая:
URL S ссылается на файлы изображений, которые будут загруженыCVImageBufferRef или CVPixelBufferRef )CIImage COUREMDLTexture Objects 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 имеет безопасную API 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
} Вы можете подключить унарные фильтры ( 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 ( )Экспорт видео:
Видеоаологическое видео требуется для следующих примеров.
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 - это свойство Compute.
Каждый раз, когда вы спрашиваете фильтр для его выходного изображения, фильтр может дать вам новый объект выходного изображения, даже если входные данные идентичны предыдущему вызову. Так что повторно используйте выходные изображения, когда это возможно.
Например,
// ╭→ 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 |
|---|---|---|
| плавать | Плавать | плавать |
| инт | Int32 | инт |
| uint | Uint32 | uint |
| буль | Буль | буль |
| simd (float2, float4, float4x4, int4 и т. Д.) | SIMD (с MetalPetal/Swift ) / Mtivector | Mtivector |
| структура | Данные / Mtidatabuffer | Nsdata / mtidatabuffer |
| Другое (float *, struct *и т. Д.) Неизримое | Данные / Mtidatabuffer | Nsdata / mtidatabuffer |
| Другой (float *, struct *и т. Д.) изменен | Mtidatabuffer | Mtidatabuffer |
Чтобы построить пользовательский уникальный фильтр, вы можете подкласс 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 ), а затем примените ядро к входному изображению. Примеры: 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 ] )Вы также можете создать несколько выходных дескрипторов для вывода нескольких изображений в одном проходе рендеринга (см. Https://en.wikipedia.org/wiki/multiple_render_targets).
Когда MTIVertex не может соответствовать вашим потребностям, вы можете реализовать протокол MTIGeometry , чтобы предоставить ваши пользовательские данные вершины для командного энкодера.
Используйте API MTIRenderCommand , чтобы выдать вызовы Draw и передавать пользовательскую MTIGeometry .
В редких сценариях вы можете напрямую получить доступ к базовой текстуре, использовать несколько ядра MPS в одном проходе рендеринга, выполнять 3D -рендеринг или сами кодировать команды рендеринга.
Протокол MTIImagePromise обеспечивает прямой доступ к базовой текстуре и контексту рендеринга для шага в металлической.
Вы можете создавать новые источники ввода или полностью пользовательские единицы обработки, внедрив протокол MTIImagePromise . Вам нужно будет импортировать дополнительный модуль для этого.
Объектив-c
@import MetalPetal.Extension;
Быстрый
// CocoaPods
import MetalPetal.Extension
// Swift Package Manager
import MetalPetalObjectiveC.Extension
См. Реализацию MTIComputePipelineKernel , MTICLAHELUTRecipe или MTIImage , например.
Если в изображении используется альфа -канал, доступны два общих представления: беспрепятственные (прямые/незаслуженные) альфа -альфа и председательную (связанную) альфа.
Благодаря беспрепятственной альфа, компоненты RGB представляют собой цвет пикселя, игнорируя его непрозрачность.
С предварительной альфа -альфа, компоненты RGB представляют собой цвет пикселя, скорректированный для его непрозрачности путем умножения.
Металлические ручки альфа -типа явно. Вы несете ответственность за предоставление правильного альфа -типа во время создания изображения.
Есть три альфа -типа в металлической.
MTIAlphaType.nonPremultiplied : альфа -значение на изображении не предсказано.
MTIAlphaType.premultiplied : альфа -значение на изображении предсказано.
MTIAlphaType.alphaIsOne : на изображении нет альфа -канала или изображение непрозрачна.
Как правило, объекты CGImage , CVPixelBuffer и CIImage имеют необычные альфа -каналы. MTIAlphaType.alphaIsOne настоятельно рекомендуется, если изображение непрозрачна, например, CVPixelBuffer от подачи камеры или CGImage загруженный из файла jpg .
Вы можете назвать unpremultiplyingAlpha() или premultiplyingAlpha() на MTIImage , чтобы преобразовать альфа -тип изображения.
По причинам производительности проверка альфа -типа происходит только в сборке отладки.
Большинство фильтров в металлическом панели принимают беспрепятственные альфа -изображения и непрозрачные изображения и выходные альфа -изображения.
Фильтры со свойством outputAlphaType принимают входные данные всех типов альфа. И вы можете использовать outputAlphaType для указания альфа -типа выходного изображения.
Например, MTIBlendFilter , MTIMultilayerCompositingFilter , MTICoreImageUnaryFilter , MTIRGBColorSpaceConversionFilter
Фильтры, которые на самом деле не модифицируют цвета, имеют правило альфа -обработки, что означает, что альфа -типы выходных изображений одинаковы с входными изображениями.
Например, MTITransformFilter , MTICropFilter , MTIPixellateFilter , MTIBulgeDistortionFilter
Для получения дополнительной информации об альфа -типах и альфа -композитинге, пожалуйста, обратитесь к этой удивительной интерактивной статье Bartosz Ciechanowski.
Цветные пространства жизненно важны для обработки изображений. Числовые значения красных, зеленых и синих компонентов не имеют смысла без цветового пространства.
Прежде чем продолжить то, как металлические цветные пространства обрабатывают цветные пространства, вы можете узнать, что такое цветовое пространство и как оно влияет на представление значений цвета. В Интернете есть много статей, объясняющих цветные пространства, чтобы начать, предложение - цветные пространства - от Bartosz Ciechanowski.
Различные мягкие и рамки имеют разные способы обработки цветовых пространств. Например, Photoshop имеет по умолчанию SRGB IEC61966-2.1 Рабочее цветовое пространство, в то время как ядро изображение по умолчанию использует линейное рабочее цветовое пространство SRGB.
Металлические текстуры не хранят с ними информацию о цветовом пространстве. Большая часть обработки цветового пространства в металлической темпеле происходит во время ввода ( MTIImage(...) ) и выхода ( MTIContext.render... ) данных изображения.
Указание цветового пространства для ввода означает, что металлическая темпала должна преобразовать значения цвета источника в указанное цветовое пространство во время создания текстуры.
При загрузке из 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 Device, когда не указано в выходном цветовом пространстве.
CVPixelBuffer Metalpetal использует CVMetalTextureCache и IOSurface для непосредственной карты CVPixelBuffer S в металлические текстуры. Таким образом, вы не можете указать цветовое пространство для загрузки или рендеринга в CVPixelBuffer . Однако вы можете указать, использовать ли текстуру с форматом пикселя SRGB для отображения.
В металле, если имя формата пикселя имеет суффикс _sRGB , то при чтении и написании значений цвета в пикселе применяются гамма -сжатие и декомпрессия SRGB. Это означает текстуру с пиксельным форматом _sRGB предполагает, что значения цвета, которые он сохраняет, искажены SRGB Gamma, когда значения цвета считываются в шейдере, выполняются SRGB в линейные конверсии RGB. Когда значения цвета записываются в шейдере, выполняются линейные преобразования RGB в SRGB.
Вы можете использовать MTIRGBColorSpaceConversionFilter для выполнения преобразования цветового пространства. Функции преобразования цветового пространства также доступны в MTIShaderLib.h .
metalpetal::sRGBToLinear (Srgb IEC61966-2.1 для линейного Srgb)metalpetal::linearToSRGB (линейный srgb до srgb iec61966-2.1)metalpetal::linearToITUR709 (линейный Srgb to ITU-R 709)metalpetal::ITUR709ToLinear (ITU-R 709 до линейного SRGB) Вы можете использовать MTISCNSceneRenderer для генерации MTIImage s из SCNScene . Возможно, вы захотите справиться с линейным цветовым пространством RGB Scenekit Renderer, см. Выпуск № 76 Изображение от Scenekit темнее, чем обычно.
Вы можете использовать MTISKSceneRenderer для генерации MTIImage s из SKScene .
Вы можете создать MTIImage s из CIImage s.
Вы можете привести к тому, MTIImage вы можете привести к CIImage , используя MTIContext .
Вы можете использовать CIFilter напрямую с MTICoreImageKernel или классом MTICoreImageUnaryFilter . (Только быстрый)
Смотрите Metalpetaljs
С помощью MetalPetalJS вы можете создавать рендеринговые трубопроводы и фильтры, используя JavaScript, что позволяет загружать ваши фильтры/визуализации из «Облака».
Рекомендуется использовать API, которые принимают MTICGImageLoadingOptions для загрузки CGImage s и изображений из URL , вместо использования API, которые принимают MTKTextureLoaderOption .
Когда вы используете API, которые принимают MTKTextureLoaderOption , Metalpetal, по умолчанию, использует MTIDefaultTextureLoader для загрузки CGImage S, изображений из URL и названных изображений. MTIDefaultTextureLoader использует MTKTextureLoader Internal и имеет некоторые обходные пути для несоответствий и ошибок MTKTextureLoader за небольшие затраты на производительность. Вы также можете создать свой собственный текстурный загрузчик, реализовав протокол MTITextureLoader . Затем назначьте свой класс Texture Loader на MTIContextOptions.textureLoaderClass при создании MTIContext .
Вы можете использовать кокопод для установки последней версии.
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-специфические дополнения и модификации API Objective-C для улучшения их отображения в Swift. Настоятельно рекомендуется, если вы используете Swift.
AppleSiliconПредоставляет библиотеку шейдеров по умолчанию, составленную на металлическом языке затенения v2.3, которая необходима для обеспечения программируемой поддержки смешивания на Apple Silicon Mac.
Добавление зависимостей пакета в ваше приложение
Metalpetal может работать на симуляторе с Xcode 11+ и MacOS 10.15+.
MetalPerformanceShaders.framework не доступен на симуляторе, поэтому фильтры, которые полагаются на MetalPerformanceShaders , такие как MTIMPSGaussianBlurFilter , MTICLAHEFilter , не работают.
Симулятор поддерживает меньше функций или различных пределов реализации, чем фактический графический процессор Apple. См. Разработка металлических приложений, которые работают в симуляторе для деталей.
Если вы быстро посмотрите на MTIImage , он покажет вам график изображений, который вы построили для создания этого изображения.

Почему объектив-C?
Спасибо за рассмотрение внесения вклад в Metalpetal. Пожалуйста, прочитайте наши рекомендации.
Металпеталь лицензирован MIT. ЛИЦЕНЗИЯ
Файлы в каталоге /MetalPetalExamples лицензированы по отдельной лицензии. Лицензия.md
Документация лицензирована CC-BY 4.0.