ioscore-imagecifilterporter-duffcompositing

Expected behavior when using CIAdditionCompositing to add pure black?


I am attempting to understand how CIAdditionCompositing works.

As part of my testing, I have created a square mid-gray image:

and a square black image:

When I combined these two square images using a CIAdditionCompositing patch, I expected to see a gray square whose color matched the original mid-gray square exactly (because all color components of the black image have value 0). However, the final result is actually brighter than the original gray image:

I don't understand how this result is produced. What am I misunderstanding about how CIAdditionCompositing works?


Solution

  • So here is how I experimented with this. I generated images using Python PIL and numpy using below

    from PIL import Image
    import numpy as np
    
    np.zeros(shape=(1,1,4))
    
    for i in range(0, 176):
        data[0][0] = [i, i, i, 255]
        Image.fromarray(data).save("{}.png".format(i))
    

    Then I wrote a XCode code to check your filter

    let folder =  "/Users/tarun.lalwani/Desktop/tarunlalwani.com/tarunlalwani/workshop/ub16/so/imagecompose/PS/"
    let black_png = folder + "1.png";
    let black_image = CIImage(image: UIImage(contentsOfFile: black_png)!)
    
    for index in 1...175 {
        let grey_png = folder + String(index) + ".png";
        let grey_image = CIImage(image: UIImage(contentsOfFile: grey_png)!)
    
        let combined_image = CIFilter(name: "CIAdditionCompositing", withInputParameters: ["inputImage":black_image!, "inputBackgroundImage":grey_image])
        let context = CIContext() // Prepare for create CGImage
        let cgimg = context.createCGImage((combined_image?.outputImage)!, from: (combined_image?.outputImage?.extent)!)
        let output = UIImage(cgImage: cgimg!)
        if let data = UIImagePNGRepresentation(output) {
            do {
                try data.write(to: (URL(fileURLWithPath: folder + "output" + String(index) + ".png")))
            } catch {
                print("Unexpected error: \(error).")
            }
        }
    
    }
    

    And then I ran below code in python to print the pixel values

    for i in range(1, 176):
        data = np.array(Image.open("output{}.png".format(i)))
        print (data[0][0][0])
    

    After that I plotted them all in an excel sheet. And here is my observation

    Now the delta that I added is nearly equivalent to ROUNDUP((<sum of pixels>-16)/2-1,0). I say nearly because I could workout an 100% exact formula

    So if A is the background image and B is the foreground image then below is the data from excel. The excel formula that I used was IF(ROUNDUP((D2-16)/2-1,0) <0, 0,ROUNDUP((D2-16)/2-1,0) )

    +-------+-------+-------+-------+-------+---------+-------+
    |   A   |   B   |   C   |  A+B  | A+B-C | Formula |   E   |
    +-------+-------+-------+-------+-------+---------+-------+
    |     1 |     1 |     2 |     2 |     0 |       0 |     0 |
    |     2 |     1 |     3 |     3 |     0 |       0 |     0 |
    |     3 |     1 |     4 |     4 |     0 |       0 |     0 |
    |     4 |     1 |     5 |     5 |     0 |       0 |     0 |
    |     5 |     1 |     6 |     6 |     0 |       0 |     0 |
    |     6 |     1 |     7 |     7 |     0 |       0 |     0 |
    |     7 |     1 |     8 |     8 |     0 |       0 |     0 |
    |     8 |     1 |     9 |     9 |     0 |       0 |     0 |
    |     9 |     1 |    10 |    10 |     0 |       0 |     0 |
    |    10 |     1 |    11 |    11 |     0 |       0 |     0 |
    |    11 |     1 |    12 |    12 |     0 |       0 |     0 |
    |    12 |     1 |    13 |    13 |     0 |       0 |     0 |
    |    13 |     1 |    14 |    14 |     0 |       0 |     0 |
    |    14 |     1 |    15 |    15 |     0 |       0 |     0 |
    |    15 |     1 |    17 |    16 |     1 |       0 |    -1 |
    |    16 |     1 |    18 |    17 |     1 |       0 |    -1 |
    |    17 |     1 |    19 |    18 |     1 |       0 |    -1 |
    |    18 |     1 |    21 |    19 |     2 |       1 |    -1 |
    |    19 |     1 |    22 |    20 |     2 |       1 |    -1 |
    |    20 |     1 |    24 |    21 |     3 |       2 |    -1 |
    |    21 |     1 |    25 |    22 |     3 |       2 |    -1 |
    |    22 |     1 |    27 |    23 |     4 |       3 |    -1 |
    |    23 |     1 |    28 |    24 |     4 |       3 |    -1 |
    |    24 |     1 |    30 |    25 |     5 |       4 |    -1 |
    |    25 |     1 |    31 |    26 |     5 |       4 |    -1 |
    |    26 |     1 |    33 |    27 |     6 |       5 |    -1 |
    |    27 |     1 |    34 |    28 |     6 |       5 |    -1 |
    |    28 |     1 |    36 |    29 |     7 |       6 |    -1 |
    |    29 |     1 |    37 |    30 |     7 |       6 |    -1 |
    |    30 |     1 |    39 |    31 |     8 |       7 |    -1 |
    |    31 |     1 |    40 |    32 |     8 |       7 |    -1 |
    |    32 |     1 |    42 |    33 |     9 |       8 |    -1 |
    |    33 |     1 |    43 |    34 |     9 |       8 |    -1 |
    |    34 |     1 |    44 |    35 |     9 |       9 |     0 |
    |    35 |     1 |    46 |    36 |    10 |       9 |    -1 |
    |    36 |     1 |    47 |    37 |    10 |      10 |     0 |
    |    37 |     1 |    49 |    38 |    11 |      10 |    -1 |
    |    38 |     1 |    50 |    39 |    11 |      11 |     0 |
    |    39 |     1 |    52 |    40 |    12 |      11 |    -1 |
    |    40 |     1 |    53 |    41 |    12 |      12 |     0 |
    |    41 |     1 |    55 |    42 |    13 |      12 |    -1 |
    |    42 |     1 |    56 |    43 |    13 |      13 |     0 |
    |    43 |     1 |    58 |    44 |    14 |      13 |    -1 |
    |    44 |     1 |    59 |    45 |    14 |      14 |     0 |
    |    45 |     1 |    61 |    46 |    15 |      14 |    -1 |
    |    46 |     1 |    62 |    47 |    15 |      15 |     0 |
    |    47 |     1 |    64 |    48 |    16 |      15 |    -1 |
    |    48 |     1 |    65 |    49 |    16 |      16 |     0 |
    |    49 |     1 |    67 |    50 |    17 |      16 |    -1 |
    |    50 |     1 |    68 |    51 |    17 |      17 |     0 |
    |    51 |     1 |    70 |    52 |    18 |      17 |    -1 |
    |    52 |     1 |    71 |    53 |    18 |      18 |     0 |
    |    53 |     1 |    73 |    54 |    19 |      18 |    -1 |
    |    54 |     1 |    74 |    55 |    19 |      19 |     0 |
    |    55 |     1 |    76 |    56 |    20 |      19 |    -1 |
    |    56 |     1 |    77 |    57 |    20 |      20 |     0 |
    |    57 |     1 |    79 |    58 |    21 |      20 |    -1 |
    |    58 |     1 |    80 |    59 |    21 |      21 |     0 |
    |    59 |     1 |    82 |    60 |    22 |      21 |    -1 |
    |    60 |     1 |    83 |    61 |    22 |      22 |     0 |
    |    61 |     1 |    85 |    62 |    23 |      22 |    -1 |
    |    62 |     1 |    86 |    63 |    23 |      23 |     0 |
    |    63 |     1 |    88 |    64 |    24 |      23 |    -1 |
    |    64 |     1 |    89 |    65 |    24 |      24 |     0 |
    |    65 |     1 |    91 |    66 |    25 |      24 |    -1 |
    |    66 |     1 |    92 |    67 |    25 |      25 |     0 |
    |    67 |     1 |    94 |    68 |    26 |      25 |    -1 |
    |    68 |     1 |    95 |    69 |    26 |      26 |     0 |
    |    69 |     1 |    97 |    70 |    27 |      26 |    -1 |
    |    70 |     1 |    98 |    71 |    27 |      27 |     0 |
    |    71 |     1 |   100 |    72 |    28 |      27 |    -1 |
    |    72 |     1 |   101 |    73 |    28 |      28 |     0 |
    |    73 |     1 |   103 |    74 |    29 |      28 |    -1 |
    |    74 |     1 |   104 |    75 |    29 |      29 |     0 |
    |    75 |     1 |   106 |    76 |    30 |      29 |    -1 |
    |    76 |     1 |   107 |    77 |    30 |      30 |     0 |
    |    77 |     1 |   109 |    78 |    31 |      30 |    -1 |
    |    78 |     1 |   110 |    79 |    31 |      31 |     0 |
    |    79 |     1 |   112 |    80 |    32 |      31 |    -1 |
    |    80 |     1 |   113 |    81 |    32 |      32 |     0 |
    |    81 |     1 |   115 |    82 |    33 |      32 |    -1 |
    |    82 |     1 |   116 |    83 |    33 |      33 |     0 |
    |    83 |     1 |   118 |    84 |    34 |      33 |    -1 |
    |    84 |     1 |   119 |    85 |    34 |      34 |     0 |
    |    85 |     1 |   121 |    86 |    35 |      34 |    -1 |
    |    86 |     1 |   122 |    87 |    35 |      35 |     0 |
    |    87 |     1 |   124 |    88 |    36 |      35 |    -1 |
    |    88 |     1 |   125 |    89 |    36 |      36 |     0 |
    |    89 |     1 |   127 |    90 |    37 |      36 |    -1 |
    |    90 |     1 |   128 |    91 |    37 |      37 |     0 |
    |    91 |     1 |   129 |    92 |    37 |      37 |     0 |
    |    92 |     1 |   131 |    93 |    38 |      38 |     0 |
    |    93 |     1 |   132 |    94 |    38 |      38 |     0 |
    |    94 |     1 |   134 |    95 |    39 |      39 |     0 |
    |    95 |     1 |   135 |    96 |    39 |      39 |     0 |
    |    96 |     1 |   137 |    97 |    40 |      40 |     0 |
    |    97 |     1 |   138 |    98 |    40 |      40 |     0 |
    |    98 |     1 |   140 |    99 |    41 |      41 |     0 |
    |    99 |     1 |   141 |   100 |    41 |      41 |     0 |
    |   100 |     1 |   143 |   101 |    42 |      42 |     0 |
    |   101 |     1 |   144 |   102 |    42 |      42 |     0 |
    |   102 |     1 |   146 |   103 |    43 |      43 |     0 |
    |   103 |     1 |   147 |   104 |    43 |      43 |     0 |
    |   104 |     1 |   149 |   105 |    44 |      44 |     0 |
    |   105 |     1 |   150 |   106 |    44 |      44 |     0 |
    |   106 |     1 |   152 |   107 |    45 |      45 |     0 |
    |   107 |     1 |   153 |   108 |    45 |      45 |     0 |
    |   108 |     1 |   155 |   109 |    46 |      46 |     0 |
    |   109 |     1 |   156 |   110 |    46 |      46 |     0 |
    |   110 |     1 |   158 |   111 |    47 |      47 |     0 |
    |   111 |     1 |   159 |   112 |    47 |      47 |     0 |
    |   112 |     1 |   161 |   113 |    48 |      48 |     0 |
    |   113 |     1 |   162 |   114 |    48 |      48 |     0 |
    |   114 |     1 |   164 |   115 |    49 |      49 |     0 |
    |   115 |     1 |   165 |   116 |    49 |      49 |     0 |
    |   116 |     1 |   167 |   117 |    50 |      50 |     0 |
    |   117 |     1 |   168 |   118 |    50 |      50 |     0 |
    |   118 |     1 |   170 |   119 |    51 |      51 |     0 |
    |   119 |     1 |   171 |   120 |    51 |      51 |     0 |
    |   120 |     1 |   173 |   121 |    52 |      52 |     0 |
    |   121 |     1 |   174 |   122 |    52 |      52 |     0 |
    |   122 |     1 |   176 |   123 |    53 |      53 |     0 |
    |   123 |     1 |   177 |   124 |    53 |      53 |     0 |
    |   124 |     1 |   179 |   125 |    54 |      54 |     0 |
    |   125 |     1 |   180 |   126 |    54 |      54 |     0 |
    |   126 |     1 |   182 |   127 |    55 |      55 |     0 |
    |   127 |     1 |   183 |   128 |    55 |      55 |     0 |
    |   128 |     1 |   185 |   129 |    56 |      56 |     0 |
    |   129 |     1 |   186 |   130 |    56 |      56 |     0 |
    |   130 |     1 |   188 |   131 |    57 |      57 |     0 |
    |   131 |     1 |   189 |   132 |    57 |      57 |     0 |
    |   132 |     1 |   191 |   133 |    58 |      58 |     0 |
    |   133 |     1 |   192 |   134 |    58 |      58 |     0 |
    |   134 |     1 |   194 |   135 |    59 |      59 |     0 |
    |   135 |     1 |   195 |   136 |    59 |      59 |     0 |
    |   136 |     1 |   197 |   137 |    60 |      60 |     0 |
    |   137 |     1 |   198 |   138 |    60 |      60 |     0 |
    |   138 |     1 |   200 |   139 |    61 |      61 |     0 |
    |   139 |     1 |   201 |   140 |    61 |      61 |     0 |
    |   140 |     1 |   203 |   141 |    62 |      62 |     0 |
    |   141 |     1 |   204 |   142 |    62 |      62 |     0 |
    |   142 |     1 |   206 |   143 |    63 |      63 |     0 |
    |   143 |     1 |   207 |   144 |    63 |      63 |     0 |
    |   144 |     1 |   209 |   145 |    64 |      64 |     0 |
    |   145 |     1 |   210 |   146 |    64 |      64 |     0 |
    |   146 |     1 |   212 |   147 |    65 |      65 |     0 |
    |   147 |     1 |   213 |   148 |    65 |      65 |     0 |
    |   148 |     1 |   215 |   149 |    66 |      66 |     0 |
    |   149 |     1 |   216 |   150 |    66 |      66 |     0 |
    |   150 |     1 |   218 |   151 |    67 |      67 |     0 |
    |   151 |     1 |   219 |   152 |    67 |      67 |     0 |
    |   152 |     1 |   221 |   153 |    68 |      68 |     0 |
    |   153 |     1 |   222 |   154 |    68 |      68 |     0 |
    |   154 |     1 |   224 |   155 |    69 |      69 |     0 |
    |   155 |     1 |   225 |   156 |    69 |      69 |     0 |
    |   156 |     1 |   227 |   157 |    70 |      70 |     0 |
    |   157 |     1 |   228 |   158 |    70 |      70 |     0 |
    |   158 |     1 |   230 |   159 |    71 |      71 |     0 |
    |   159 |     1 |   231 |   160 |    71 |      71 |     0 |
    |   160 |     1 |   233 |   161 |    72 |      72 |     0 |
    |   161 |     1 |   234 |   162 |    72 |      72 |     0 |
    |   162 |     1 |   236 |   163 |    73 |      73 |     0 |
    |   163 |     1 |   237 |   164 |    73 |      73 |     0 |
    |   164 |     1 |   239 |   165 |    74 |      74 |     0 |
    |   165 |     1 |   240 |   166 |    74 |      74 |     0 |
    |   166 |     1 |   242 |   167 |    75 |      75 |     0 |
    |   167 |     1 |   243 |   168 |    75 |      75 |     0 |
    |   168 |     1 |   245 |   169 |    76 |      76 |     0 |
    |   169 |     1 |   246 |   170 |    76 |      76 |     0 |
    |   170 |     1 |   248 |   171 |    77 |      77 |     0 |
    |   171 |     1 |   249 |   172 |    77 |      77 |     0 |
    |   172 |     1 |   251 |   173 |    78 |      78 |     0 |
    |   173 |     1 |   252 |   174 |    78 |      78 |     0 |
    |   174 |     1 |   254 |   175 |    79 |      79 |     0 |
    |   175 |     1 |   255 |   176 |    79 |      79 |     0 |
    +-------+-------+-------+-------+-------+---------+-------+
    

    So unfortunately, they do say they use the formula described in

    https://keithp.com/~keithp/porterduff/p253-porter.pdf

    But the delta function is custom. Also I believe the formula from that PDF will come into picture when there is a custom alpha channel in the image that you use