ASCII-Photo-iOS-Lite
A watered down version of my ASCII Photo iOS app. I intend to use this project to sell myself to teams of iOS engineers for their own assessment of my skills as a developer, basically a “tech test”.
Reviewer info
- 100% SwiftUI
- Unit tests included for the
ImageModel
- iOS 16+ to allow for the use of newer APIs and tools such as Transferable
- Mainly uses architecture that SwiftUI enforces, i.e. Models are closely tied to Views via
StateObject
which react to changes inPublished
values and propergated through environment objects, any lower level processing (such as the image generation algorithm) are isolated and only the Model can directly interact with it - Implements async-await in the
Camera
object for assessing permissions, receiving image/video streams and processing captured photos. - Type safety is utilised where ever possible to help with API design, code maintenance and mitigates the risk of introducing regressions, e.g.
generateArt(with glyphs: Glyphs)
uses theGlyphs
type that has a private initialiser so the consumer has no choice but to use thestatic
constants (in this case.ascii
) to call the method.
Features
- Camera support
- Photo library support
- Drag and drop support
- Copy generated art to clipboard
- Image preview
- Generated art inversion
- Light and dark mode support
- Convert generated art to an actual image
- Better UI and UX for art preview
Demo output
Saturn in ASCII:
."I<+-[[[?~,
,<[(/frxrf/\\\||]
:+1/jjt\|)1(|rYXxft(/I
\<}/ft\|\/frnunj1!lrLuj/\!
"_)ff//jvUQZwqqqpppdp?^XUxt\.
"-\jjtrcJOZZOQLLLLLQ0ZOpO`nJrf_
^_\jjjuYQZOQLJUUUYXUJCLLOZpC:Jcj)
.>|rrrvJOZ0CYvxt|((\rccXJLLOOh}}Qrt\
I1jxxvJOZQYn|[>I,^``^^:]czULQ0dU>Luf"
.'. `_fnxvJ0ZLct[i"\''''\\`^"^:xXULQqZ+Yzf"
',I<+-[]?-]/uczYQZLz/_,' '\^^lvYLLww[vU/^
\;>-]}11(1[[1jvcYLO0Yr(?><!, .\^`(YJCwZ{vU('
\l_]}11(()1[]\ncYCOOCu/{?[{()(1?i\ '``-XJCqL}zY[
,~]}11()|)1]}tvXUQOQXj(]}|juvuxj/)1[<\ `\~XJLpX(Uvi
,+{11()|||1](jcYC0OLvt11tvJLLJzuxjt\)}{?l `\_XJ0qx/Ct^
`~]}1(||||1{)xzULOOJn\)tc0ww0JXcvvuxjt\|({[~`'`]UCm0/xJ?
l[}1()|||1{|nXULZ0Yr\/v0pkp0UXXXzcvunrf\(1{?-~;\JLwz\Xn:
>]}1))|)1{|uYJQOQXj\rCphhd0CJJJYzzcvxf/)1}{{[?_>cm0jrU{
~]{1)||1{|uYJQZQzf\rQkakdmLLLCJUYXvxt\)(((1}}{][~]U/zr,
<]{1))}]|uXUQOQzt(fLkabqwOLLLJJUXvr/\\|))(((1}}{][</X-
:[]1)}](nXULZQzt(/JbhpmmmOLLCJUznj/\\\\|||)))(1}{[?~?^
+]1}[1xzXLOQXt1|Xdhq00mmOQLCUcxf/\/\\\\\|||))(11{]-_`
^[{?]jzXJO0Yj((umkqQLOwwZ0LJcrt///\\\\/\\\||||)(1{[-+`
I?-/zzUOOUx)1jLbpQCQmwwZQJcrt///////////\////|)1{]?_>
:(vczQOCv|}/cmpOCLZmZO0Ccrt////\////////tt/|)(1{][_~I
IxzvJZQXt{1rJmZCCLQLJJUzrt////////////tff/\|)(1}{[-~<.
.|XrzO0Ux}[|uLZLUJJUYYUzxt////////tt//fff/||))(}{[?_>i^
~cufCZLz|?]\vCLYzXXXXzcxt///\/////tttfjf/\||)(1{]?-+<i"
`tYtvZ0Cr[_]|rXUvvcccvcnt\/\\\\\/////fjf/\|||(1}]?-+>il^
+Xu/LmCY[;~?1/nurxnuuuur\||\\\\\/////ff/||||(1}][-+~<iI'
'|Jtrm0Jc>\'^_1\f/ffjjrr/)))))|||\\\\/t/||))(1}][-+~>i!,
!vY)XqLJul\\ i{11)|//t)(((()))||||\//|))((1{][-+~><!:.
?Uu(QwCJnI\\ `>[}1()1}}}11(())))|\|(1(}}{[?-+><il,.
\)Cj|wZCUvl``. `i-]{[]{{}}}1111()(}}{]][--+>i!:`
:fC/|pOLUX-\^' .:!<~+_?]{{]]]{{[[[??-+~<l,'
!rC/)dOLJYj,"`'. .`l]t\|}~-??---_++>il;^'
<rJj]dZLLYz\"^"``\\''.'^;~1rU0ZOUnrx],
<rzz>ww0LCYcv-:^^^^";i_1fvCOZQYurrt?`
ljnQ<ubO0LLUzccr/|\/juzJQOZQXnrrf{;
^/jUnIwmZOLLLJUXYUUUCLOZOCzxjjf1i
}fxL(;dwOO0QLLLQQOZmmQYujfjf(<.
;/txCx'(pdppppqqm0Czxt/tjt}i'
_\tjvL/Ii1trrrf/\|\/ff|?;
+\)tfxXXx\))|/tfjf|]i`
}||\\\/frjft|{+I\
:>-[[?+>!,\
From the source image: