@@ -575,22 +575,59 @@ proc encodePng*(
575575
576576 # Add IDAT
577577 # Add room for 1 byte before each row for the filter type.
578- var filtered = newString (width * height * channels + height)
578+ var
579+ filtered = newString (width * height * channels + height)
580+ upRow = newSeq [uint8 ](width * channels)
581+ subRow = newSeq [uint8 ](width * channels)
582+ avgRow = newSeq [uint8 ](width * channels)
579583 for y in 0 ..< height:
580- filtered[ y * width * channels + y] = 2 . char # Up filter type
584+ let rowStart = y * width * channels
581585 for x in 0 ..< width * channels:
582586 # Move through the image data byte-by-byte
583- let
584- dataPos = y * width * channels + x
585- filteredPos = y * width * channels + y + 1 + x
586- var up: uint8
587+ let dataPos = rowStart + x
588+ var left, up: uint8
589+ if x - channels >= 0 :
590+ left = data[dataPos - channels]
587591 if y - 1 >= 0 :
588592 up = data[(y - 1 ) * width * channels + x]
589- filtered[filteredPos] = (data[dataPos] - up).char
593+ upRow[x] = data[dataPos] - up.uint8
594+ subRow[x] = data[dataPos] - left.uint8
595+ let avg = ((left.int + up.int ) div 2 ).uint8
596+ avgRow[x] = data[dataPos] - avg
597+
598+ var upRowSum, subRowSum, avgRowSum: uint64
599+ for i in 0 ..< upRow.len:
600+ upRowSum += upRow[i]
601+ subRowSum += subRow[i]
602+ avgRowSum += avgRow[i]
603+
604+ let minRowSum = min (min (upRowSum, subRowSum), avgRowSum)
605+
606+ if upRowSum == minRowSum:
607+ filtered[rowStart + y] = 2 .char # Up filter type
608+ copyMem (
609+ filtered[rowStart + y + 1 ].addr ,
610+ upRow[0 ].addr ,
611+ upRow.len
612+ )
613+ elif subRowSum == minRowSum:
614+ filtered[rowStart + y] = 1 .char # Sub filter type
615+ copyMem (
616+ filtered[rowStart + y + 1 ].addr ,
617+ subRow[0 ].addr ,
618+ subRow.len
619+ )
620+ else :
621+ filtered[rowStart + y] = 3 .char # Average filter type
622+ copyMem (
623+ filtered[rowStart + y + 1 ].addr ,
624+ avgRow[0 ].addr ,
625+ avgRow.len
626+ )
590627
591628 let compressed =
592629 try :
593- compress (filtered, BestSpeed , dfZlib)
630+ compress (filtered, DefaultCompression , dfZlib)
594631 except ZippyError :
595632 raise newException (
596633 PixieError , " Unexpected error compressing PNG image data"
0 commit comments