Examples
Input: (['a.png', 'b.png'], {'a.png': 2, 'b.png': 5}, [[('ADD', 3), ('MUL', 2)], [('NEG',), ('SUB', 4)]], 'out')
Expected Output: [('out/img0_pipe0.png', 10), ('out/img0_pipe1.png', -6), ('out/img1_pipe0.png', 16), ('out/img1_pipe1.png', -9)]
Explanation: For `a.png` (value 2), pipeline 0 gives `(2 + 3) * 2 = 10` and pipeline 1 gives `-2 - 4 = -6`. For `b.png` (value 5), the results are 16 and -9.
Input: (['x', 'x', 'y'], {'x': -3, 'y': 0}, [[], [('MUL', -1), ('ADD', 2)], [('SUB', 5), ('NEG',)]], 'res')
Expected Output: [('res/img0_pipe0.png', -3), ('res/img0_pipe1.png', 5), ('res/img0_pipe2.png', 8), ('res/img1_pipe0.png', -3), ('res/img1_pipe1.png', 5), ('res/img1_pipe2.png', 8), ('res/img2_pipe0.png', 0), ('res/img2_pipe1.png', 2), ('res/img2_pipe2.png', 5)]
Explanation: The first pipeline is empty, so it leaves values unchanged. The same path `x` appears twice, so outputs are produced twice with different image indices.
Input: ([], {}, [[('ADD', 1)]], 'tmp')
Expected Output: []
Explanation: There are no images, so no outputs are generated.
Input: (['z'], {'z': 4}, [[('ADD', 1), ('MUL', 3), ('NEG',), ('SUB', 2)]], 'tmp/')
Expected Output: [('tmp/img0_pipe0.png', -17)]
Explanation: The operations are applied in order: `4 -> 5 -> 15 -> -15 -> -17`. A trailing slash in `output_dir` should not change the final file name format.