@@ -669,52 +669,35 @@ def dither_primary(image: Image.Image) -> Image.Image:
669669 """
670670 if image .mode != "RGB" :
671671 image = image .convert ("RGB" )
672- width , height = image .size
673-
674- src = image .load ()
675- out = Image .new ("RGB" , (width , height ))
676- dst = out .load ()
677-
678- # Step 1: primary color reduction
679- assert src is not None
680- for x in range (width ):
681- for y in range (height ):
682- px = src [x , y ]
683- assert isinstance (px , tuple )
684- r , g , b = px
685- src [x , y ] = (
686- 255 if r > 127 else 0 ,
687- 255 if g > 127 else 0 ,
688- 255 if b > 127 else 0 ,
689- )
690-
691- # Step 2: ordered dithering (2x2 blocks)
692- assert dst is not None
693- for x in range (0 , width - 1 , 2 ):
694- for y in range (0 , height - 1 , 2 ):
695- p1 = src [x , y ]
696- p2 = src [x , y + 1 ]
697- p3 = src [x + 1 , y ]
698- p4 = src [x + 1 , y + 1 ]
699-
700- assert isinstance (p1 , tuple )
701- assert isinstance (p2 , tuple )
702- assert isinstance (p3 , tuple )
703- assert isinstance (p4 , tuple )
704- red = (p1 [0 ] + p2 [0 ] + p3 [0 ] + p4 [0 ]) / 4
705- green = (p1 [1 ] + p2 [1 ] + p3 [1 ] + p4 [1 ]) / 4
706- blue = (p1 [2 ] + p2 [2 ] + p3 [2 ] + p4 [2 ]) / 4
707-
708- r1 = [_dither_saturation (red , q ) for q in range (4 )]
709- g1 = [_dither_saturation (green , q ) for q in range (4 )]
710- b1 = [_dither_saturation (blue , q ) for q in range (4 )]
711-
712- dst [x , y ] = (r1 [0 ], g1 [0 ], b1 [0 ])
713- dst [x , y + 1 ] = (r1 [1 ], g1 [1 ], b1 [1 ])
714- dst [x + 1 , y ] = (r1 [2 ], g1 [2 ], b1 [2 ])
715- dst [x + 1 , y + 1 ] = (r1 [3 ], g1 [3 ], b1 [3 ])
716672
717- return out
673+ bands = []
674+ for band in image .split ():
675+ # Step 1: primary color reduction
676+ band = band .point (lambda x : 255 if x > 127 else 0 )
677+ bands .append (band )
678+
679+ # Step 2: ordered dithering (2x2 blocks)
680+ px = band .load ()
681+ assert px is not None
682+ for x in range (0 , band .width - 1 , 2 ):
683+ for y in range (0 , band .height - 1 , 2 ):
684+ p1 = px [x , y ]
685+ p2 = px [x , y + 1 ]
686+ p3 = px [x + 1 , y ]
687+ p4 = px [x + 1 , y + 1 ]
688+
689+ assert isinstance (p1 , (int , float ))
690+ assert isinstance (p2 , (int , float ))
691+ assert isinstance (p3 , (int , float ))
692+ assert isinstance (p4 , (int , float ))
693+
694+ value = (p1 + p2 + p3 + p4 ) / 4
695+
696+ px [x , y ] = _dither_saturation (value , 0 )
697+ px [x , y + 1 ] = _dither_saturation (value , 1 )
698+ px [x + 1 , y ] = _dither_saturation (value , 2 )
699+ px [x + 1 , y + 1 ] = _dither_saturation (value , 3 )
700+ return Image .merge ("RGB" , bands )
718701
719702
720703def posterize (image : Image .Image , bits : int ) -> Image .Image :
0 commit comments