3D块摄像头
BlockCam是用于iOS和iPados的相机程序,可通过Avoundation拍摄图像,然后将这些图像转换为简单的3D场景。场景可以由用户旋转和缩放,并保存为平面图像。
BlockCam由Stuart Rankin撰写。
blockCAM的版本控制在Versioning.swift文件中维护,并自动更新每个构建作为前构建脚本步骤。更新包括构建ID,构建数字,时间和日期,但是当前必须手动更新版本号。下面的当前构建字符串也通过相同的机制维护。
版本管理程序当前未更新块cam项目文件的版本号。
最新构建: 0.9 Alpha,Build 3287,构建日期:2021年7月13日,16:06
有关版本和构建方式更新的信息,请参见GITHUB上的版本Updater存储库。
BlockCAM旨在尽可能包含用户提供的信息。每当使用用户可识别的信息时,BlockCam都会明确要求。通过设计,块状摄影机不会默认收集任何可识别的信息;用户必须采取主动步骤以允许收集此类信息。
| 可识别的信息 | 使用 | 贮存 |
|---|---|---|
| 用户名 | 用户的名称(用户输入)将存储在处理后的图像元数据中。 | 存储在UserDefaults中。 |
| 用户版权 | 用户的版权字符串(由用户输入)存储在处理后的图像元数据中。 | 存储在UserDefaults中。 |
当用户实例化块状摄像机时,它将在实时视图模式下打开(在主屏幕上显示相机的视图)。用户可以选择选择三种模式之一:
BlockCAM已在以下平台上进行了测试:
UIBezierPath添加更多形状。BlockCam有四个表演问题:
autoreleasepool块中的循环中,已经解决了大多数问题。如果事实证明这是不足的,则存在缓解计划:将所有刮擦图像保存到本地存储中,然后单独阅读它们,然后一次处理它们。这会减慢速度,但会降低记忆压力。BlockCAM通过Coreimage Filter CIPixellate将所拍摄的每个图像转换为像素图像。像素化后,处理算法然后计算确定高度 - 高度确定节点的大小或节点的挤出。然后,将来自像素图像的每个像素转换为3D形状(由用户设置),然后在3D视图中添加到当前场景中。
所有处理操作都使用相同的代码,但根据有效的用户模式,可能以不同的方式(或多次)调用。
获取图像用于处理。只要它是标准的iOS/iPados-prable图像,图像的来源就不重要。最常见的图像来源很可能是现场视图摄像头。其他来源是相册和视频帧。
以下图像是处理的来源。 (这是我在初冬拍摄我们花园的图像。)

鉴于转换图像的性能费用,用户可以选择通过将源图像调整到较小尺寸来减少完成的工作量。如果处理视频,则可能在没有用户干预的情况下发生这种情况。 (处理视频往往需要大量的内存,因此即使每张图像节省了几个百分点也会有助于使系统对系统的压力减轻。)某些图像也旋转到270°(如果愿意,则为-90°),并且需要正确旋转。这也是在图像调节步骤中完成的。
然后通过核心图像滤波器功能将处理的图像像素化。具体而言,最常见的过滤器块用途是CIPixellate (尽管其他像素过滤器的使用取决于最终形状)。每个像素化区域的大小取决于用户设置。尺寸越小,对整体性能的影响越大,尽管CIPixellate (和滤镜)仍然非常快。较小的像素化区域提高性能的原因是因为以后需要更多的3D节点。
下图显示了原始图像的像素化。请注意,每个像素的区域都是纯色,这意味着块车不必读取整个区域即可获得颜色 - 只有一个像素。

然后解析像素的图像。这需要获取每个像素化区域的颜色。这比预期的步骤要慢。从图像中获取单独的像素数据需要大量图像数据操作,以便将图像准备好进行查询。在此步骤结束时,不再使用图像。 2D颜色数据将传递给下一步。
在此步骤中,将像素的图像数据保存到本地文件存储中。这是为了简化用户后来要求的次要视觉更改。
最终节点形状是用户设置。 BlockCAM允许用户从多种形状之一中进行选择 - 内置形状往往比非构建形状更快(例如,球体比五角星更快)。使用指定的几何形状从图像解析步骤中为每种颜色生成一个3D节点。为了炫耀最终场景的3D度,节点在某种程度上被夸大了。例如,如果立方体是用户选择的形状,则长度将被夸大。夸张由颜色确定 - 颜色用于阴影节点的弥散表面以及确定高度。夸张由用户选择的决定因素确定:
创建节点后,将其添加到主节点。创建所有节点并放入主节点后,主节点本身就会放入3D场景中。
尽管这似乎是一个微不足道的一步,但转换视频时非常棘手。如果转换图像,则所有发生的就是更新3D场景并最终显示给用户(通常在0.5至2.0秒内)。对于视频,至关重要的是,正确的显示时间表:要转换视频,每个帧都通过这些步骤运行,然后对3D场景进行快照。如果在显示场景之前拍摄快照,则结果将是纯黑图像,这不是用户想要看到的。因此,BlockCAM必须参与SCNSceneRendererDelegate集合集,以了解用户何时可以看到场景。
以下图像是图像的最终处理版本。这是SCNView上的snapshot()调用的输出。该样本使用挤压块,并在默认摄像头方向上查看。

显示图像后,用户可以选择按原样保存或编辑某些视觉方面,或者旋转或放大或放大,然后保存(也许是)。对于视频,一旦捕获了3D场景的快照,场景就被处置了。
根据.SaveOriginalImageAction的值,将保存原始图像。当用户保存处理的图像时,元数据将与处理的图像一起保存。元数据由程序的名称和版本以及创建图像时有效的参数组成。
保存处理的文件是一个多步骤过程:
.jpg文件保存在/Scratch目录中。.jpg文件)重新保存。PHAssetCreationRequest - 这是需要的,因为更常见的方法将图像移至Photo loply Strips exif数据)。/Scratch目录中删除。BlockCam将元数据保存在处理的文件中。
| 团体 | 标签 | 存储的值 |
|---|---|---|
| tiff | 艺术家 | 如果用户启用了用户的名称。 |
| tiff | 版权 | 如果用户启用了用户的版权字符串。 |
| tiff | 软件 | BlockCam的名称,版本和构建数字。 |
| exif | 用户 | 用于生成处理的图像的参数列表。 |
另请参见隐私讨论。
图像处理的简化流程图如下所示。

由于预处理和像素化图像所需的时间,每次处理新图像时,像素化数据(由颜色数组组成)保存在设备的文件系统中。如果用户更改参数(例如3D形状),则已经完成预处理,并且重复使用像素数据。这可能会节省大量时间。
如果用户更改影响预处理的参数,则从一开始就重新处理图像。 (例如,更改块大小将导致执行完整的后处理周期。)
视频处理的简化流程图如下所示。立方体回到图像流。

当前,绿色框(“处理帧”)无法按预期/所需的功能,因此在当前写作时,不支持视频创建。
BlockCAM在运行时记录消息和状态到调试控制台(如果存在,并且在绝大多数实例中,则不会存在)和本地的SQLite数据库。如果需要,这允许在验尸后进行调试。
鉴于苹果公司对数据租赁的政策(更不用说欧盟的政策),对于任何已发布的块cam,它将完全删除(通过编译时标志)(通过编译时标志)。
所有用户设置(以及一些流程设置)均通过Settings类存储。该类封装了该程序其余部分看不见的存储机制。当前,存储机制是UserDefaults 。如果设置变得更加复杂,则将其迁移到数据库非常简单。
要访问设置,呼叫者必须使用Settings类提供的方法。这有助于确保数据类型的完整性。
Settings类还提供更改的设置级别通知(这是首先创建类的主要原因)。
BlockCAM设置如下所示。
| 象征 | 类型 | 默认 | 用法 |
|---|---|---|---|
| .Initialized | 细绳 | “初始化” | 确定设置是否已初始化的标志。当BlockCAM首次运行时,如果.Initialized为NIL或空,则假定它是第一次运行BlockCam,因此请写入所有设置的默认值。 |
| .blocksize | 整数 | 48 | 图像处理的块大小。这是每个像素化区域的平方尺寸。 |
| .ShapeType | 细绳 | “块” | 每个像素区域的3D对象的相同。从枚举中铸造。 |
| .InvertHeight | 布尔 | 错误的 | 反转高度/尺寸确定标志。 |
| .HeightSource | 细绳 | “亮度” | 用于确定高度/尺寸的颜色通道。从枚举中铸造。 |
| .imagesizeconstraints | 细绳 | “中等的” | 出于性能原因,确定图像大小的减少量。从枚举中铸造。在运行时解释实际值。 |
| .VerticalExaggeration | 细绳 | “中等的” | 挤出或扩大3D形状时要执行的垂直夸张量。从枚举中铸造。 |
| .InputQuality | 整数 | 2 | 表示输入质量的值。范围从0到3,3是最高质量(最慢的过程)。 |
| .CurrentCamera | 细绳 | “后退” | 最后一个相机的位置。前后。从枚举中铸造。 |
| .lightColor | 细绳 | “白色的” | 光的颜色名称。从枚举中铸造。以后可以将其转换为颜色库类型。 |
| .lighttype | 细绳 | “ Omni” | 用于照亮场景的光的名称。从枚举中铸造。 |
| 。灯强度 | 细绳 | “普通的” | 光的强度用于照亮场景。在运行时确定的实际值。从枚举中铸造。 |
| .fieldofview | 细绳 | “普通的” | 相机的视野。实际值在运行时确定。从枚举中铸造。 |
| 。示波组织图 | 布尔 | 错误的 | 显示直方图显示。目前尚未实施。 |
| .HistogramBucketCount | 整数 | 256 | 直方图显示中的颜色数量。目前尚未实施。 |
| .InitialView | 细绳 | “ Liveview” | 用户看到的最后一个视图(例如实时视图,专辑等)。 |
| .FullyExtrudeLetters | 布尔 | 真的 | 确定字母是完全挤出还是仅部分挤出。 |
| 。理齿 | 细绳 | “光滑的” | 确定在字母中创建曲线的顺利。高质量曲线的性能成本很高。在运行时确定的实际值。从枚举中铸造。 |
| .letterfont | 细绳 | “ futura” | 字体(和可选的重量)用于渲染挤出字母。如果系统上不存在字体,则块将输入未定义的状态。 |
| .RandomCharacterSource | 细绳 | “拉丁” | 指定字符的字符范围为挤出字符时随机字母的来源。可以通过用逗号将每个范围与其他范围分开来指定多个范围。 |
| .VideOfps | 整数 | 1 | 目前未使用。 |
| .VideoDimensions | 细绳 | “最小” | 生成视频时确定最终视频尺寸。在运行时确定的实际值。从枚举中铸造。 |
| .VideoBlockSize | 整数 | 48 | 视频处理的块大小。这是每个像素化区域的平方尺寸。 |
| .usemetal | 布尔 | 真的 | 告诉BlockCam使用金属而不是OpenGL的标志。 |
| .antialiasingmode | 整数 | 0 | 确定抗质量模式。 |
| .InitialBestFit | 布尔 | 错误的 | 如果是真的,则BlockCam将尝试尽可能紧密地将所有节点放入视图中。 |
| .saveoriginalimageaction | 细绳 | “总是” | 确定如何以及何时保存原始图像。从枚举中铸造。 |
| .NextSequentialInteger | 整数 | 0 | 用于文件名称。 |
| .LoopSequentialIntegerAfter | 整数 | 9999 | 确定使用顺序整数时何时循环到启动。 |
| .StartSequentialIntegerAt | 整数 | 1 | 顺序整数的起始值。 |
| .IncreaseStarApexesWithProminence | 布尔 | 错误的 | 如果是正确的话,随着颜色高度的突出,恒星形状的顶点数量会增加。 |
| .starapexcount | 整数 | 5 | 恒星的顶点数。如果.IncreaseStarApexesWithProminence是正确的,则这是顶点的起始数。 |
| .HaltWhenCriticalThermal | 布尔 | 真的 | 如果是正确的话,当BlockCam收到关键的热警报时,将其停止(通过fatalError呼叫)。这可能违反了苹果准则,并可能被删除。 |
| .haltonlowpower | 布尔 | 真的 | 如果是真的,则当块收到低功率警报时,块将停止(通过fatalError呼叫)。这可能违反了苹果准则,并可能被删除。 |
| .bestfitoffset | 双倍的 | 2.0 | 当.InitialBestFit为真时,可以用来备份相机的价值,以给图像提供更多的负空间。 |
| .lightingModel | 细绳 | “ phong” | 表面材料照明模型。从枚举中铸造。 |
| .cappedLineBalllocation | 细绳 | “顶部” | 球的位置(“盖”)用于上限线形状的节点。从枚举中铸造。 |
| .loggingEnabled | 布尔 | 错误的 | 启用记录标志。 |
| .fontsize | 整数 | 36 | 字母的字体大小。 |
| .enableuisounds | 布尔 | 真的 | 标记播放UI声音(例如按下按钮时)。如果此值是false ,则所有其他声音标志将被忽略。 |
| .EnableShutterSound | 布尔 | 错误的 | 按下相机按钮时,标志以播放快门声音。在某些地理位置中,这总是发生,设置此值将无效。 |
| .EnableImageProcessingSound | 布尔 | 真的 | 标志在图像处理的开始和结束时播放声音。由于图像处理时间很耗时,因此可以帮助用户了解何时完成图像。 |
| .EnableVideoRecordingSound | 布尔 | 真的 | 当用户启动并停止录制视频时,标志以播放声音。 |
| .enablebuttonpresssounds | 布尔 | 真的 | 当用户按按钮时,标志以播放声音。 |
| .enableOptionsElectSounds | 布尔 | 真的 | 当用户在屏幕设置显示中选择选项时,标志以播放声音。 |
| .EnableCrashSounds | 布尔 | 错误的 | 显示碰撞对话框时播放声音的标志。仅在以#debug模式进行编译时启用。 |
| .meshdotsize | 细绳 | “中等的” | 网格中心点的大小。如果不使用.None将不会显示中心点。从枚举中铸造。 |
| 。网林 | 细绳 | “中等的” | 网状线的厚度。从枚举中铸造。 |
| .RadiatingLineThickness | 细绳 | “中等的” | 辐射线形状的厚度。从枚举中铸造。 |
| .radiatinglinecount | 整数 | 8 | 辐射线形状的辐射线数。 4用于指向基本方向的线,在基本方向和介于两者之间进行8 ,在z平面中另外16条线。 |
| .blockchamfersize | 细绳 | “没有任何” | 倒角半径/边缘平滑度,用于块状。从枚举中铸造。 |
| 。末期词 | 整数 | 1024 | 图像的最大维度。如果要进行处理的图像更大,则将调整大小,以使最长的维度是该值。 |
| .adduserDatatoExif | 布尔 | 错误的 | 标志以将用户创建的信息添加到处理后的图像的Exif块中。如果以#debug模式编译,则此值默认为true。 |
| .username | 细绳 | “” | (默认值为空白。)添加到处理后图像的Exif块中添加的用户提供的名称。仅当.AddUserDataToExif为真时,才会发生这种情况。如果以#debug模式编译,则此值默认为“ Stuart Rankin”。 |
| .UserCopyright | 细绳 | “” | (默认值为空白。)用户提供的版权字符串被添加到处理后的图像的Exif块中。仅当.AddUserDataToExif为真时,才会发生这种情况。如果以#debug模式进行编译,则此值默认为“属性3.0 notported(cc by 3.0)”。 |
| .ConeIsInverted | 布尔 | 真的 | 确定锥形是否根据z深度倒置。 |
| .Conetoptions | 细绳 | .TopIsZero .rawValue | 确定锥体顶部半径的选项。 |
| .conbaseOptions | 细绳 | .BaseIsSide .RawValue | 确定锥体基本半径的选项。 |
| .showsplashscreen | 布尔 | 真的 | 标记确定在启动时是否显示飞溅屏幕的标志。 |
| .hueshapelist | 细绳 | “” | 色调变体形状类型的形状列表。 |
| .saturationshapelist | 细绳 | “” | 饱和变体形状类型的形状列表。 |
| .BrightnessShapeList | 细绳 | “” | 亮度变体形状类型的形状列表。 |
BlockCam使用3D处理,该处理可行,可行设备的图形芯片。如果用户指定最高质量的设置,则可能发生某些极端情况。为了帮助保护设备免受损坏,可以在发生这种情况时可以中止块状摄像机的执行。
| 事件 | 行动 | 控制设置 |
|---|---|---|
| 热的 | 如果热事件达到临界阶段(从字面上。在通知中.critical ),则如果设置为true ,则将产生致命的误差,以减少块cam产生的任何热应力。 | .HaltWhenTooHot |
| 电池 | 如果电池进入低功率状态,如果设置为true ,则将产生致命的错误,以帮助保留电池的寿命,然后再充电。 | .HaltOnLowPower |
BlockCam支持以下视觉效果:
目前支持(或计划支持)以下形状以进行挤压效应:
| 形状 | 本国的 | 笔记 |
|---|---|---|
| 块 | 是的 - SCNBox | 天然盒沿Z轴延长。 |
| 三角形 | 不 | 自定义等边三角形。 |
| 五角星 | 不 | 定制等法五角形形状。 |
| 六角形 | 不 | 定制等边形状形状。 |
| 八生 | 不 | 定制等边八角形状。 |
| 金字塔 | 是的 - SCNPyramid | 本地金字塔形状。 |
| 环形 | 是的 - SCNTorus | 本地圆环形状。 |
| 气缸 | 是的 - SCNCylinder | 天然圆柱形状 - 使圆形高架圆形。 |
| 球 | 是的 - SCNSphere | 本地球体形状。 |
| 胶囊 | 是的 - SCNCapsule | 本地胶囊形状。听起来不那么有趣。 |
| 四面体 | 不 | 自定义等边四面体固体。 |
| 星星 | 不 | 自定义星形形状(具有径向相等的顶点)。可以改变顶点的数量。 |
| 组合Forrgb | 是的 - 组合 | 组合球,圆环和胶囊。 |
| 联合FORHSB | 是的 - 组合 | 组合球,圆环和胶囊。 |
| 网眼 | 不 | 目前尚未实施。 |
| 信件 | 是的 - SCNText | 本地挤出文字。往往会非常缓慢,尤其是对于非拉丁语字母。 |
| 线 | 是的 - SCNCapsule | 非常薄的胶囊形状。 |
| 上限线 | 是的 - 组合 | 非常薄的胶囊形状,并根据用户设置放置在线的顶部,中或底部的球体。 |
| 辐射线 | 是的 - 组合 | 多条线从中心点辐射。用户可以指定多少行。这是性能较重的形状。 |
| huevarying | 变体 | 给定点的形状由像素化区域的色调确定,因此实际的最终形状将变化。 |
| 饱和度 | 变体 | 给定点的形状取决于像素化区域的饱和度,因此实际的最终形状将变化。 |
| 亮度范围 | 变体 | 给定点的形状取决于像素化区域的亮度,因此实际的最终形状会有所不同。 |
代表性像素区域的每个形状都被挤出或扩大。挤出深度或扩大尺寸的确定取决于像素区域的颜色。
| 颜色通道 | 用法 |
|---|---|
| 色调 | 颜色的色调决定了3D对象的深度/大小。请注意,色相值是周期性的(0.0基本上与1.0相同),因此在突出显示绿色时,红色像素往往会被屈服。 |
| 饱和 | 颜色饱和值确定深度/大小。更亮的颜色会更大。 |
| 亮度 | 颜色的亮度决定了深度/大小。这是默认值以及大多数人期望该程序的工作方式。 |
| 红色的 | 红色通道用于确定深度/大小。 |
| 绿色的 | 绿色通道用于确定深度/大小。 |
| 蓝色的 | 蓝色通道用于确定深度/大小。 |
| 青色 | 合成青色通道(来自CMYK)用于确定深度/尺寸。 |
| 品红 | 合成洋红色通道(来自CMYK)用于确定深度/大小。 |
| 黄色的 | 合成黄色通道(来自CMYK)用于确定深度/尺寸。 |
| 黑色的 | 合成黑通道(来自CMYK)用于确定深度/大小。 |
| YUV:Y | YUV转换的合成Y通道。 |
| YUV:U | 来自YUV转换的合成U通道。 |
| YUV:v | YUV转换的合成V通道。 |
BlockCam支持倒置的标志。这意味着,如果用户设置倒置,则深度/大小本身就是一个互惠,使黑暗的区域突出和柔和的区域柔和或隐藏。
阻滞剂支持更改光的颜色以及光的类型。目前,颜色仅限于一小部分预定义的颜色。灯的类型并行场景的标准,非参数化的灯(例如.omni和.spot )。
目前,用户无法调整灯的位置。
BlockCAM利用SCNView的allowsCameraControl标志,使用户通过手势放大,Shink或旋转(以三个轴为旋转)。
最初渲染时,结果似乎远离视图。 BlockCAM具有可将图像适合视图的用户定义标志。对于扩大和收缩,此功能倾向于混淆allowsCameraControl 。
本节将讨论各种实施级别的详细信息。
BlockCam用Xcode 11.3写在Swift 5中。
考虑到处理图像所需的时间很长,所有图像处理均在背景线程上完成。这需要所有通信以通过适当的线程调用来通过UI更新用户。
TBD
BlockCam是版权所有©2019,2020撰写的Stuart Rankin
日本语版«Google翻訳で翻訳»
3dブロックカメラ
blockcamはIOSおよびiPados 用のカメラプログラムで、 iPados 用のカメラプログラムで、 ios を介して画像を取得し、それらの画像を単纯な ios を介して画像を取得し、それらの画像を単纯な ios を介して画像を取得し、それらの画像を単纯な 3d シーンに変换します。シーンは、ユーザーによって回転および拡大缩小され、フラットイメージとして保存されます。
BlockcamはStuart Rankinによって作成されました。
blockcamのバージョン管理はVersioning.swiftファイルで管理され、ビルド前のスクリプトステップとしてビルドごとに自动的に更新されます。 ファイルで管理され、ビルド前のスクリプトステップとしてビルドごとに自动的に更新されます。更新にはビルド、ビルド番号、时刻、日付が含まれますが、现在、バージョン番号は手动で更新する必要があります。 、ビルド番号、时刻、日付が含まれますが、现在、バージョン番号は手动で更新する必要があります。 、ビルド番号、时刻、日付が含まれますが、现在、バージョン番号は手动で更新する必要があります。
现在、バージョン管理プログラムは blockcamプロジェクトファイルのバージョン番号を更新しません。
最新のビルド:バージョン情报については、英语のセクションを参照してください。
バージョンとビルドの更新方法については、 githubの[versionupdater](https://github.com/sjrankin/versionupdater)リポジトリを参照してください。
blockcam は、可能な限りユーザーが提供する情报を含むように设计されています。 blockcamはそれを明示的に要求します。はそれを明示的に要求します。はそれを明示的に要求します。はそれを明示的に要求します。はデフォルトでユーザーを特定できる情报を收集しません。はデフォルトでユーザーを特定できる情报を收集しません。はデフォルトでユーザーを特定できる情报を收集しません。はデフォルトでユーザーを特定できる情报を收集しません。
| 识别情报 | 使用 | 保管 |
|---|---|---|
| ユーザー名 | ((()。 | 「用户默认fefaults」に保存されます。 |
| ユーザー著作権 | ((()。 | 「用户默认fefaults」に保存されます。 |
ユーザーが(blockcam)(をインスタンス化すると、ライブビューモードで开きます(メイン画面にカメラのビューを表示)。ユーザーには、次の 3つのモードのいずれかを选択するオプションがあります。
阻滞は、次のプラットフォームでテストされています。
1.主な問題はパフォーマンスです。 古い携帯電話の大きなサイズの画像で使用すると、パフォーマンスが大幅に低下します。 ただし、セルフィーカメラは実際には非常に高速です。 BlockCamには、パフォーマンスの問題を軽減するのに役立つ特定の軽減策(ユーザー設定など)があります。 2. *漢字は非常に遅いです。*漢字を使用して押し出し画像を作成するには、古いiPhoneの場合、6分程度かかります。 3.以下でのみテスト済み:iPhone 6S +、iPhone 8、iPad Mini4。iPadPro 9.7。 4. MacCatalystは、MacカメラのAVFoundationの使用をサポートしていないため、非常に困難です。 MacCatalystバージョンでの作業は、その妨害のため現在のところ停止しています。 5.ヒストグラムはまだ実装されていません。 6.非組み込みの幾何学的図形は、組み込みの図形よりも大幅に遅いように見えます。 7. iPadOSおよびiOS 13には、混乱するデバッグセッションにつながるいくつかの追加のデバッグステートメントが残っているようです。具体的には、「BackgroundTaskを終了できません」メッセージです。
UIBezierPathを使用してさらにシェイプを追加します。 2.処理済みのライブビュー(現在の写真モードと同様)のみを表示する処理済みライブビューモードを追加します。 これはおそらく非常に電力を消費し、遅くなり、最新のハードウェアでのみ確実に動作する可能性があります。 3.ビデオを共有する-現在、画像のみを共有できます。 4.ピクセル化されたデータの使用を完全に実装します。 ほとんどのコードが配置されています。 この機能は、処理された画像データをピクセル化レベル(たとえば、各ピクセル領域の色)でユーザーのファイルシステム空間にファイルとして保存します。 利点は、形状や押し出しの深さなどの特定の設定をユーザーが変更したときに処理を高速化することです。 BlockCamには、パフォーマンスに関する4つの懸念事項があります。
BlockCamは、取り込まれた各画像をCoreImageフィルターCIPixellateを介してピクセル化された画像に変換します。 ピクセル化の後、処理アルゴリズムは高さの決定を計算します-高さはノードのサイズまたはノードの押し出しを決定します。 次に、ピクセル化された画像の各ピクセルが3D形状(ユーザーが設定)に変換され、3Dビューの現在のシーンに追加されます。
すべての処理操作は同じコードを使用しますが、有効なユーザー向けモードに応じて異なる方法(または複数回)で呼び出すことができます。
処理のために画像が取得されます。画像のソースは、iOS / iPadOSで読み取り可能な標準の画像である限り重要ではありません。画像の最も一般的なソースは、おそらくライブビューカメラです。他のソースは、フォトアルバムとビデオフレームです。
次の画像は、処理のソースです。 (これは私が初冬に庭で撮った画像です。)

画像を変換するためのパフォーマンスの犠牲を考えると、ユーザーはソース画像をより小さなサイズにサイズ変更することにより、実行される作業量を削減するオプションがあります。これは、ビデオが処理される場合、ユーザーの介入なしに発生することもあります。 (ビデオの処理は多くのメモリを消費する傾向があるため、画像ごとに数パーセントを保存してもシステムのストレスを軽減できます。)一部の画像は270°(または必要に応じて-90°)に回転され、正しく回転します。これは、画像調整ステップでも行われます。
処理された画像は、Core Imageフィルター関数を介してピクセル化されます。具体的には、BlockCamが使用する最も一般的なフィルターは「CIPixellate」です(ただし、最終的な形状に応じて他のピクセル化フィルターが使用されます)。各ピクセル化領域のサイズは、ユーザー設定によって異なります。サイズが小さいほど、全体的なパフォーマンスへの影響は大きくなりますが、「CIPixellate」(およびフィルターと同様)は依然として非常に高速です。ピクセル化された領域が小さくなるとパフォーマンスが向上する理由は、後でより多くの3Dノードが必要になるためです。
次の画像は、元の画像のピクセル化を示しています。各ピクセル化された領域は単色であることに注意してください。つまり、BlockCamは領域全体を読み取って色を取得する必要はなく、1ピクセルだけです。

次に、ピクセル化された画像が解析されます。これには、ピクセル化された各領域の色を取得する必要があります。これは予想よりも遅いステップです。画像から個々のピクセルデータを取得するには、画像を照会できるようにするためだけに大量の画像データ操作が必要です。この手順の最後に、画像は使用されなくなります。カラーデータの2D配列が次のステップに渡されます。
このステップでは、ピクセル化された画像データがローカルファイルストレージに保存されます。 これは、後でユーザーが要求する小さな視覚的な変更を簡素化するためです。
最終的なノード形状はユーザー設定です。 BlockCamを使用すると、ユーザーは多くの形状のいずれかを選択できます。組み込みの形状は、非組み込みの形状よりも速く動作する傾向があります(たとえば、球体は五角形よりも高速です)。指定したジオメトリを使用して、イメージ解析ステップから各色の3Dノードが生成されます。最終シーンの3D性を誇示するために、ノードはある次元で誇張されています。たとえば、キューブがユーザーが選択した形状である場合、長さは誇張されます。誇張は色によって決定されます-色は、ノードの拡散表面を陰影付けするために、また高さを決定するために使用されます。誇張は、ユーザーが選択可能な決定要因によって決定されます。
ノードが作成されると、そのノードはマスターノードに追加されます。すべてのノードが作成されてマスターノードに配置されると、マスターノード自体が3Dシーンに配置されます。
-マスターノードは、後のアニメーションを管理しやすくするために使用されます。
これは簡単な手順のように思えるかもしれませんが、ビデオを変換するときは非常に注意が必要です。画像を変換すると、3Dシーンが更新され、最終的にユーザーに表示されます(通常は0.5〜2.0秒以内)。ビデオの場合、ディスプレイのタイミングを正確にすることが重要です。ビデオを変換するには、各フレームをこれらの手順で実行し、3Dシーンのスナップショットを取得します。シーンが表示される前にスナップショットが撮られた場合、結果は純粋な黒のイメージになりますが、これはユーザーが見たいものではありません。したがって、BlockCamはSCNSceneRendererDelegate関数セットに参加して、シーンが実際にユーザーに表示されるタイミングを知る必要があります。
次の画像は、画像の最終的な処理済みバージョンです。これは、SCNViewでのsnapshot()呼び出しの出力です。サンプルは押し出しブロックを使用し、デフォルトのカメラの向きで表示されています。

画像が表示されると、ユーザーはそれをそのまま保存するか、いくつかの視覚的側面を編集するか、回転またはズームインまたはズームアウトしてから保存する(おそらくもう一度)オプションがあります。ビデオの場合、3Dシーンのスナップショットがキャプチャされると、シーンは破棄されます。
.SaveOriginalImageActionの値に応じて、元の画像が保存されます。 ユーザーが処理された画像を保存すると、メタデータは処理された画像とともに保存されます。 メタデータは、プログラムの名前とバージョン、およびイメージの作成時に有効なパラメーターで構成されます。
処理されたファイルの保存は、複数ステップのプロセスです。
.jpgファイルとして/Scratchディレクトリに保存されます。.jpgファイルとして)。PHAssetCreationRequestを使用します-写真ロールに画像を移動するより一般的な方法はExifデータを削除するためです)。/Scratchディレクトリから削除されます。BlockCamは、処理されたファイルにメタデータを保存します。
| グループ | タグ | 保存された値 |
|---|---|---|
| tiff | アーティスト | ユーザーが有効にした場合、ユーザーの名前。 |
| tiff | 著作権 | ユーザーが有効にした場合、ユーザーの著作権文字列。 |
| tiff | ソフトウェア | BlockCamの名前、バージョン、ビルド番号。 |
| Exif | UserComment | 処理済み画像の生成に使用されるパラメーターのリスト。 |
画像の前処理とピクセル化には時間がかかるため、新しい画像が処理されるたびに、ピクセル化データ(色の配列で構成される)がデバイスのファイルシステムに保存されます。 その後、ユーザーがパラメーター(3D形状など)を変更した場合、前処理は既に完了しており、ピクセル化データは再利用されます。 これにより、大幅に時間を節約できる可能性があります。
ユーザーが前処理に影響するパラメーターを変更すると、画像は最初から再処理されます。 (たとえば、ブロックサイズを変更すると、完全な再処理サイクルが実行されます。)
BlockCamは、実行時のメッセージとステータスをデバッグコンソール(存在する場合、大部分のインスタンスでは存在しない)とローカルSQLiteデータベースに記録します。 これにより 必要が生じた場合の事後デバッグ。
Appleのデータ保持に関するポリシー(EUのポリシーは言うまでもありません)を考えると、BlockCamのすべてのリリースバージョンのログは(コンパイル時フラグを介して)削除される可能性が高いです。
すべてのユーザー設定(およびいくつかのプロセス設定)は、 Settingsクラスを介して保存されます。 このクラスは、プログラムの残りの部分からは見えないストレージメカニズムをカプセル化します。 現在、ストレージメカニズムはUserDefaultsです。 設定がより複雑になった場合、これをデータベースに移行するのは簡単です。
設定にアクセスするには、呼び出し側はSettingsクラスの提供されたメソッドを使用する必要があります。 これにより、データ型の整合性を確保できます。
Settingsクラスは設定レベルの変更通知も提供します(これが最初にクラスを作成する主な理由でした)。
BlockCamの設定を以下に示します。
| 記号 | タイプ | デフォルト | 使用法 |
|---|---|---|---|
| .Initialized | 细绳 | "Initialized" | 設定が初期化されたかどうかを決定するフラグ。 BlockCamが最初に実行されるときに、 .Initializedがnilまたは空の場合、BlockCamが最初に実行されたと想定されるため、すべての設定のデフォルト値を書き込みます。 |
| .BlockSize | 整数 | 48 | 画像処理のブロックサイズ。これは、ピクセル化された各領域の正方形のサイズです。 |
| .ShapeType | 细绳 | "Blocks" | 各ピクセル化領域の3Dオブジェクトと同じ。列挙型からキャストします。 |
| .InvertHeight | 布尔 | 错误的 | 反転高さ/サイズ決定フラグ。 |
| .HeightSource | 细绳 | “亮度” | 高さ/サイズを決定するために使用するカラーチャンネル。列挙型からキャストします。 |
| .ImageSizeConstraints | 细绳 | “中等的” | パフォーマンス上の理由から、処理する前に行う画像のサイズの縮小量を決定します。列挙型からキャストします。実行時に解釈される実際の値。 |
| .VerticalExaggeration | 细绳 | “中等的” | 3D形状を押し出しまたは拡大するときに実行する垂直方向の誇張の量。列挙型からキャストします。 |
| .InputQuality | Integer | 2 | 入力品質を示す値。 0から3の範囲で、3が最高品質(および処理が最も遅い)です。 |
| .CurrentCamera | 细绳 | “后退” | 最後に使用したカメラの位置。前面または背面。列挙型からキャストします。 |
| .LightColor | 细绳 | “白色的” | ライトの色の名前。列挙型からキャストします。後でカラーライブラリタイプの色に変換できます。 |
| .LightType | 细绳 | "Omni" | シーンの照明に使用されるライトのタイプの名前。列挙型からキャストします。 |
| .LightIntensity | 细绳 | “普通的” | シーンを照らすために使用される光の強度。実行時に決定される実際の値。列挙型からキャストします。 |
| .FieldOfView | 细绳 | “普通的” | カメラの視野。実際の値は実行時に決定されます。列挙型からキャストします。 |
| .ShowHistogram | 布尔 | 错误的 | ヒストグラム表示を表示します。現在実装されていません。 |
| .HistogramBucketCount | 整数 | 256 | ヒストグラム表示の色数。現在実装されていません。 |
| .InitialView | 细绳 | "LiveView" | ユーザーが最後に表示したビュー(ライブビュー、アルバムなど)。 |
| .FullyExtrudeLetters | 布尔 | 真的 | 文字が完全に押し出されるか、部分的にのみ押し出されるかを決定します。 |
| .LetterSmoothness | 细绳 | “光滑的” | 文字の曲線をどれだけスムーズに作成するかを決定します。高品質の曲線には、大きなパフォーマンスコストがかかります。実行時に決定される実際の値。列挙型からキャストします。 |
| .LetterFont | 细绳 | "Futura" | 押し出された文字のレンダリングに使用するフォント(およびオプションの太さ)。フォントがシステムに存在しない場合、BlockCamは未定義の状態に入ります。 |
| .RandomCharacterSource | 细绳 | “拉丁” | 文字を押し出すときにランダムな文字のソースとして使用する名前付きUnicode範囲。複数の範囲を指定するには、それぞれをコンマで区切ります。 |
| .VideoFPS | 整数 | 1 | 現在使用されていません。 |
| .VideoDimensions | 细绳 | "Smallest" | ビデオを生成するときの最終的なビデオサイズを決定します。実行時に決定される実際の値。列挙型からキャストします。 |
| .VideoBlockSize | 整数 | 48 | ビデオ処理のブロックサイズ。これは、ピクセル化された各領域の正方形のサイズです。 |
| .UseMetal | 布尔 | 真的 | OpenGLではなくMetalを使用するようにBlockCamに指示するフラグ。 |
| .AntialiasingMode | 整数 | 0 | アンチエイリアスモードを決定します。 |
| .InitialBestFit | 布尔 | 错误的 | trueの場合、BlockCamは、すべてのノードをビューにできるだけ厳密に合わせようとします。 |
| .SaveOriginalImageAction | 细绳 | “总是” | 元の画像を保存する方法とタイミングを決定します。列挙型からキャストします。 |
| .NextSequentialInteger | Integer | 0 | ファイル名の生成に使用。 |
| .LoopSequentialIntegerAfter | Integer | 9999 | 連続する整数を使用する場合、いつループを開始するかを決定します。 |
| .StartSequentialIntegerAt | Integer | 1 | 連続整数の開始値。 |
| .IncreaseStarApexesWithProminence | 布尔 | 错误的 | trueの場合、星形の頂点の数は色の高さが顕著になるにつれて増加します。 |
| .StarApexCount | 整数 | 5 | 星の頂点の数。 .IncreaseStarApexesWithProminenceがtrueの場合、これは頂点の開始数です。 |
| .HaltWhenCriticalThermal | 布尔 | 真的 | trueの場合、BlockCamは重大な温度アラートを受信すると停止します( fatalError呼び出しを介して)。これはAppleのガイドラインに違反する可能性があり、削除される可能性があります。 |
| .HaltOnLowPower | 布尔 | 真的 | trueの場合、BlockCamは低電力アラートを受信すると停止します( fatalError呼び出しを介して)。これはAppleのガイドラインに違反する可能性があり、削除される可能性があります。 |
| .BestFitOffset | 双倍的 | 2.0 | .InitialBestFitがtrueの場合にカメラを後退させて、画像にもう少しネガティブなスペースを与えるために使用する値。 |
| .LightingModel | 细绳 | "Phong" | 表面マテリアル照明モデル。列挙型からキャストします。 |
| .CappedLineBallLocation | 细绳 | “顶部” | CappedLine形状のノードのボール(「キャップ」)の位置。列挙型からキャストします。 |
| .LoggingEnabled | 布尔 | 错误的 | ロギングフラグを有効にします。 |
| .FontSize | 整数 | 36 | 押し出された文字のフォントサイズ。 |
| .EnableUISounds | 布尔 | 真的 | Flagは、UIサウンドを再生します(ボタンが押されたときなど)。 この値が「false」の場合、他のすべてのサウンドフラグは無視されます。 |
| .EnableShutterSound | 布尔 | 错误的 | Flagは、カメラボタンが押されたときにシャッター音を再生します。 一部の地理的な場所では、これは常に発生し、この値を設定しても効果はありません。 |
| .EnableImageProcessingSound | 布尔 | 真的 | Flagは、画像処理の開始時と終了時に音声を再生します。 画像処理には時間がかかるため、ユーザーは画像がいつ完成するかを理解するのに役立ちます。 |
| .EnableVideoRecordingSound | 布尔 | 真的 | ユーザーがビデオの記録を開始および停止したときに音を再生するフラグ。 |
| .EnableButtonPressSounds | 布尔 | 真的 | ユーザーがボタンを押したときに音を再生するフラグ。 |
| .EnableOptionSelectSounds | 布尔 | 真的 | ユーザーが画面上の設定画面でオプションを選択したときに音を再生するフラグ。 |
| .EnableCrashSounds | 布尔 | 错误的 | フラグは、クラッシュダイアログが表示されたときにサウンドを再生します。 #DEBUGモードでコンパイルされた場合のみ有効です。 |
| .MeshDotSize | 细绳 | “中等的” | メッシュの中心ドットのサイズ。 .Noneが使用される場合、中央のドットは表示されません。 列挙型からキャストします。 |
| .MeshLineThickness | 细绳 | “中等的” | メッシュラインの太さ。 列挙型からキャストします。 |
| .RadiatingLineThickness | 细绳 | “中等的” | 放射線形状の太さ。 列挙型からキャストします。 |
| .RadiatingLineCount | 整数 | 8 | 放射ライン形状の放射ラインの数。 「4」は基線方向を指す線、「8」は基線方向とその中間、および「16」はz平面のさらに8本の線を示します。 |
| .BlockChamferSize | 细绳 | “没有任何” | ブロック形状の面取り半径/エッジの滑らかさ。 列挙型からキャストします。 |
| .MaxImageDimension | 整数 | 1024 | 画像の最大寸法。 処理する画像が大きい場合、最長寸法がこの値になるようにサイズ変更されます。 |
| .AddUserDataToExif | 布尔 | 错误的 | Flagは、ユーザーが作成した情報を処理済み画像のExifブロックに追加します。 |
| .UserName | 细绳 | “” | (デフォルトは空白です。)処理された画像のExifブロックに追加されるユーザー指定の名前。 これは、 .AddUserDataToExifがtrueの場合にのみ発生します。 |
| .UserCopyright | 细绳 | “” | (デフォルトは空白です。)処理された画像のExifブロックに追加されるユーザー指定の著作権文字列。 これは、 .AddUserDataToExifがtrueの場合にのみ発生します |
BlockCamは次のビジュアルをサポートしています。
現在、押し出し効果では次の形状がサポートされています(またはサポートされる予定です)。
| 形状 | ネイティブ | メモ |
|---|---|---|
| ブロック | はい- SCNBox | Z軸に沿って長くなったネイティブボックスの形状。 |
| 三角形 | いいえ | カスタム正三角形の形状。 |
| 五角形 | いいえ | カスタム正五角形。 |
| 六角形 | いいえ | カスタム正六角形。 |
| オクトゴン | いいえ | カスタム正八角形。 |
| ピラミッド | はい- SCNPyramid | ネイティブのピラミッド形状。 |
| トロイド | はい- SCNTorus | ネイティブトーラス形状。 |
| シリンダー | はい- SCNCylinder | 自然なシリンダー形状-すてきな高架円になります。 |
| 球 | はい- SCNSphere | ネイティブの球形。 |
| カプセル | はい- SCNCapsule | ネイティブカプセルの形状。聞こえるほど面白くない。 |
| 四面体 | いいえ | カスタム正四面体ソリッド。 |
| 星 | いいえ | カスタム星形(半径方向に等しい頂点を持つ)。頂点の数を変えることができます。 |
| CombinedForRGB | はい-組み合わせ | 球体、トーラス、カプセルの組み合わせ。 |
| CombinedForHSB | はい-組み合わせ | 球体、トーラス、カプセルの組み合わせ。 |
| メッシュ | いいえ | 現在実装されていません。 |
| レター | はい- SCNText | ネイティブの押し出しテキスト。特に非ラテン系のアルファベットでは、非常に遅くなる傾向があります。 |
| 行 | はい- SCNCapsule | 非常に薄いカプセル形状。 |
| CappedLines | はい-組み合わせ | ユーザー設定に応じて、行の上部、中間、または下部に球体を配置した非常に薄いカプセル形状。 |
| RadiatingLines | はい-組み合わせ | 中心点から放射状に広がる複数の線。 ユーザーは行数を指定できます。 これはパフォーマンス重視の形状です。 |
代表的なピクセル化領域の各形状は、押し出しまたは拡大されます。押し出しの深さまたは拡大サイズの決定は、ピクセル化された領域の色に依存します。
| カラーチャンネル | 使用方法 |
|---|---|
| 色调 | 色の色相は、3Dオブジェクトの深さ/サイズを決定します。色相値は周期的であることに注意してください(0.0は基本的に1.0と同じです)。したがって、緑が強調表示されている間、赤みを帯びたピクセルは抑制される傾向があります。 |
| 彩度 | 彩度の値は深さ/サイズを決定します。明るい色は大きくなります。 |
| 明るさ | 色の明るさが深さ/サイズを決定します。これはデフォルト値であり、ほとんどの人がプログラムが機能することを期待する方法です。 |
| 赤 | 赤チャネルは深さ/サイズを決定するために使用されます。 |
| 緑 | 緑のチャネルは深さ/サイズを決定するために使用されます。 |
| 青 | 青チャンネルは深さ/サイズを決定するために使用されます。 |
| シアン | (CMYKからの)合成シアンチャンネルを使用して、深度/サイズを決定します。 |
| マゼンタ | 深さ/サイズを決定するために、CMYKからの合成マゼンタチャネルが使用されます。 |
| 黄色 | 合成の黄色チャンネル(CMYKから)を使用して深さ/サイズを決定します。 |
| 黒 | 深さ/サイズを決定するために、CMYKからの合成黒チャンネルが使用されます。 |
BlockCamは反転フラグをサポートしています。これは、ユーザーが反転を設定した場合、深度/サイズはそれ自体の比isであり、暗い領域を目立たせ、明るい領域を抑制または非表示にすることを意味します。
BlockCamは、ライトの色とライトの種類の変更をサポートしています。 色は現在、事前定義された色の小さなセットに制限されています。 ライトのタイプは、SceneKitの標準のパラメータ化されていないライト( .omniや.spotなど)に対応しています。
現在、ライトの位置はユーザーが調整することはできません。
BlockCamは、 SCNViewのallowsCameraControlフラグを使用して、ユーザーがジェスチャによって拡大、光沢、回転(3軸)できるようにします。
最初にレンダリングしたとき、結果はビューから比較的遠くにあるように見える場合があります。 BlockCamには、画像をビューに合わせるためのユーザー設定可能なフラグがあります。 この機能は、拡大と縮小に関してallowsCameraControlを混同する傾向があります。
すべてのユーザー設定(およびいくつかのプロセス設定)は、 Settingsクラスを介して保存されます。このクラスは、プログラムの残りの部分からは見えないストレージメカニズムをカプセル化します。現在、ストレージメカニズムはUserDefaultsです。設定がより複雑になった場合、これをデータベースに移行するのは簡単です。
設定にアクセスするには、呼び出し側はSettingsクラスの提供されたメソッドを使用する必要があります。これにより、データ型の整合性を確保できます。
Settingsクラスは設定レベルの変更通知も提供します(これが最初にクラスを作成する主な理由でした)。
BlockCamは3D処理を使用し、デバイスのグラフィックチップを実行します。ユーザーが最高品質の設定を指定した場合、特定の極端な条件が発生する可能性があります。デバイスを損傷から保護するために、そのような場合にBlockCamの実行を中止する設定を使用できます。
| イベント | アクション | 設定の制御 |
|---|---|---|
| 热的 | サーマルイベントがクリティカルステージ(通知では文字通り.critical )に達すると、設定がtrueの場合、BlockCamによって作成される熱ストレスを減らす致命的なエラーが生成されます。 | .HaltWhenTooHot |
| バッテリー | バッテリーが低電力状態になった場合、設定がtrueの場合、再充電前にバッテリーの寿命を保つために致命的なエラーが生成されます。 | .HaltOnLowPower |
BlockCamの著作権©2019, 2020 by Stuart Rankin