 
 : png-component ( loading-png -- obj )
     bit-depth>> {
+        { 1 [ ubyte-components ] }
+        { 2 [ ubyte-components ] }
+        { 4 [ ubyte-components ] }
         { 8 [ ubyte-components ] }
         { 16 [ ushort-components ] }
         [ unknown-component-type ]
     } case ;
 
+: scale-factor ( n -- n' )
+    {
+        { 1 [ 255 ] }
+        { 2 [ 127 ] }
+        { 4 [ 17 ] }
+        { 8 [ 1 ] }
+    } case ;
+
+: scale-greyscale ( byte-array loading-png -- byte-array' )
+    [ bit-depth>> ] [ color-type>> ] bi {
+        { greyscale [
+            dup 16 = [
+                drop
+            ] [
+                scale-factor '[ _ * ] B{ } map-as
+            ] if
+        ] }
+        { greyscale-alpha [
+            [ 8 group ] dip '[
+                [ [ 0 5 ] dip <slice> [ _ * ] change-each ] keep
+            ] map B{ } concat-as
+        ] }
+    } case ;
+
+: decode-greyscale ( loading-png -- byte-array )
+    [ raw-bytes ] keep scale-greyscale ;
+ 
+ERROR: invalid-color-type/bit-depth loading-png ;
+
+: validate-bit-depth ( loading-png seq -- loading-png )
+    [ dup bit-depth>> ] dip member?
+    [ invalid-color-type/bit-depth ] unless ;
+
+: validate-greyscale ( loading-png -- loading-png )
+    { 1 2 4 8 16 } validate-bit-depth ;
+
+: validate-truecolor ( loading-png -- loading-png )
+    { 8 16 } validate-bit-depth ;
+
+: validate-indexed-color ( loading-png -- loading-png )
+    { 1 2 4 8 } validate-bit-depth ;
+
+: validate-greyscale-alpha ( loading-png -- loading-png )
+    { 8 16 } validate-bit-depth ;
+
+: validate-truecolor-alpha ( loading-png -- loading-png )
+    { 8 16 } validate-bit-depth ;
+
+: loading-png>bitmap ( loading-png -- bytes component-order )
+    dup color-type>> {
+        { greyscale [
+            validate-greyscale decode-greyscale L
+        ] }
+        { truecolor [
+            validate-truecolor raw-bytes RGB
+        ] }
+        { indexed-color [
+            validate-indexed-color unimplemented-color-type
+        ] }
+        { greyscale-alpha [
+            validate-greyscale-alpha decode-greyscale LA
+        ] }
+        { truecolor-alpha [
+            validate-truecolor-alpha raw-bytes RGBA
+        ] }
+        [ unknown-color-type ]
+    } case ;
+
 : loading-png>image ( loading-png -- image )
     [ image new ] dip {
-        [ png-image-bytes >>bitmap ]
+        [ loading-png>bitmap [ >>bitmap ] [ >>component-order ] bi* ]
         [ [ width>> ] [ height>> ] bi 2array >>dim ]
         [ png-component >>component-type ]
     } cleave ;
-
-: decode-greyscale ( loading-png -- image )
-    unimplemented-color-type ;
-
-: decode-truecolor ( loading-png -- image )
-    loading-png>image RGB >>component-order ;
-    
-: decode-indexed-color ( loading-png -- image )
-    unimplemented-color-type ;
-
-: decode-greyscale-alpha ( loading-png -- image )
-    unimplemented-color-type ;
-
-: decode-truecolor-alpha ( loading-png -- image )
-    loading-png>image RGBA >>component-order ;
-
-ERROR: invalid-color-type/bit-depth loading-png ;
-
-: validate-bit-depth ( loading-png seq -- loading-png )
-    [ dup bit-depth>> ] dip member?
-    [ invalid-color-type/bit-depth ] unless ;
-
-: validate-greyscale ( loading-png -- loading-png )
-    { 1 2 4 8 16 } validate-bit-depth ;
-
-: validate-truecolor ( loading-png -- loading-png )
-    { 8 16 } validate-bit-depth ;
-
-: validate-indexed-color ( loading-png -- loading-png )
-    { 1 2 4 8 } validate-bit-depth ;
-
-: validate-greyscale-alpha ( loading-png -- loading-png )
-    { 8 16 } validate-bit-depth ;
-
-: validate-truecolor-alpha ( loading-png -- loading-png )
-    { 8 16 } validate-bit-depth ;
-
-: png>image ( loading-png -- image )
-    dup color-type>> {
-        { greyscale [ validate-greyscale decode-greyscale ] }
-        { truecolor [ validate-truecolor decode-truecolor ] }
-        { indexed-color [ validate-indexed-color decode-indexed-color ] }
-        { greyscale-alpha [ validate-greyscale-alpha decode-greyscale-alpha ] }
-        { truecolor-alpha [ validate-truecolor-alpha decode-truecolor-alpha ] }
-        [ unknown-color-type ]
-    } case ;
 
 : load-png ( stream -- loading-png )
     [

        { filter-up [ [| n | n x nth n b nth + 256 wrap n x set-nth ] each ] }
        { filter-average [ [| n | n x nth n a nth n b nth + 2/ + 256 wrap n x set-nth ] each ] }
        { filter-paeth [ [| n | n x nth n a nth n b nth n c nth paeth + 256 wrap n x set-nth ] each ] }
    } case 
    curr width tail ;

:: reverse-png-filter ( lines n -- byte-array )

        { interlace-none [ ] }
        { interlace-adam7 [ unimplemented-interlace ] }
        [ unimplemented-interlace ]
    } case bs:<msb0-bit-reader> ;

: uncompress-bytes ( loading-png -- bitstream )
    [ inflate-data ] [ interlace-method>> ] bi reverse-interlace ;

:: raw-bytes ( loading-png -- array )
    loading-png uncompress-bytes :> bs
    loading-png width>> :> width
    loading-png height>> :> height
