| 4099 | } |
| 4100 | |
| 4101 | static unsigned unfilterScanline(unsigned char* recon, const unsigned char* scanline, const unsigned char* precon, |
| 4102 | size_t bytewidth, unsigned char filterType, size_t length) { |
| 4103 | /* |
| 4104 | For PNG filter method 0 |
| 4105 | unfilter a PNG image scanline by scanline. when the pixels are smaller than 1 byte, |
| 4106 | the filter works byte per byte (bytewidth = 1) |
| 4107 | precon is the previous unfiltered scanline, recon the result, scanline the current one |
| 4108 | the incoming scanlines do NOT include the filtertype byte, that one is given in the parameter filterType instead |
| 4109 | recon and scanline MAY be the same memory address! precon must be disjoint. |
| 4110 | */ |
| 4111 | |
| 4112 | size_t i; |
| 4113 | switch(filterType) { |
| 4114 | case 0: |
| 4115 | for(i = 0; i != length; ++i) recon[i] = scanline[i]; |
| 4116 | break; |
| 4117 | case 1: |
| 4118 | for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i]; |
| 4119 | for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + recon[i - bytewidth]; |
| 4120 | break; |
| 4121 | case 2: |
| 4122 | if(precon) { |
| 4123 | for(i = 0; i != length; ++i) recon[i] = scanline[i] + precon[i]; |
| 4124 | } else { |
| 4125 | for(i = 0; i != length; ++i) recon[i] = scanline[i]; |
| 4126 | } |
| 4127 | break; |
| 4128 | case 3: |
| 4129 | if(precon) { |
| 4130 | for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i] + (precon[i] >> 1u); |
| 4131 | for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + ((recon[i - bytewidth] + precon[i]) >> 1u); |
| 4132 | } else { |
| 4133 | for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i]; |
| 4134 | for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + (recon[i - bytewidth] >> 1u); |
| 4135 | } |
| 4136 | break; |
| 4137 | case 4: |
| 4138 | if(precon) { |
| 4139 | for(i = 0; i != bytewidth; ++i) { |
| 4140 | recon[i] = (scanline[i] + precon[i]); /*paethPredictor(0, precon[i], 0) is always precon[i]*/ |
| 4141 | } |
| 4142 | |
| 4143 | /* Unroll independent paths of the paeth predictor. A 6x and 8x version would also be possible but that |
| 4144 | adds too much code. Whether this actually speeds anything up at all depends on compiler and settings. */ |
| 4145 | if(bytewidth >= 4) { |
| 4146 | for(; i + 3 < length; i += 4) { |
| 4147 | size_t j = i - bytewidth; |
| 4148 | unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1], s2 = scanline[i + 2], s3 = scanline[i + 3]; |
| 4149 | unsigned char r0 = recon[j + 0], r1 = recon[j + 1], r2 = recon[j + 2], r3 = recon[j + 3]; |
| 4150 | unsigned char p0 = precon[i + 0], p1 = precon[i + 1], p2 = precon[i + 2], p3 = precon[i + 3]; |
| 4151 | unsigned char q0 = precon[j + 0], q1 = precon[j + 1], q2 = precon[j + 2], q3 = precon[j + 3]; |
| 4152 | recon[i + 0] = s0 + paethPredictor(r0, p0, q0); |
| 4153 | recon[i + 1] = s1 + paethPredictor(r1, p1, q1); |
| 4154 | recon[i + 2] = s2 + paethPredictor(r2, p2, q2); |
| 4155 | recon[i + 3] = s3 + paethPredictor(r3, p3, q3); |
| 4156 | } |
| 4157 | } else if(bytewidth >= 3) { |
| 4158 | for(; i + 2 < length; i += 3) { |
no test coverage detected