OSDN Git Service

Fix rounding bug that was causing PNG files getting darker.
authorMartin Renold <martinxyz@gmx.ch>
Sun, 24 May 2009 21:16:55 +0000 (21:16 +0000)
committerMartin Renold <martinxyz@gmx.ch>
Sun, 24 May 2009 21:16:55 +0000 (21:16 +0000)
But we still can't load-save-load-save give the same PNG,
because the undefined colors (in transparent areas) tend to change.

svn://svn.gna.org/svn/mypaint/trunk@345

lib/pixbufsurface.py
lib/tiledsurface.py
test_mypaintlib.py

index 7acc106..f1255b1 100644 (file)
@@ -88,6 +88,8 @@ class Surface:
             dst[:,:,:] = data
 
     def blit_tile_into(self, dst, tx, ty):
+        # (used mainly for loading)
+        # conversion 8bit RGBA ==> 16bit premultiplied
         assert dst.dtype == 'uint16', '16 bit dst expected'
         tmp = self.tile_memory_dict[(tx, ty)]
         assert tmp.shape[2] == 4, 'alpha required'
index 64f631e..6f61c5c 100644 (file)
@@ -91,13 +91,14 @@ class Surface(mypaintlib.TiledSurface):
                 yield tx*N, ty*N, rgba[y_start:y_end,x_start:y_end]
 
     def blit_tile_into(self, dst, tx, ty):
-        # rarely used
+        # used mainly for saving (transparent PNG)
         assert dst.shape[2] == 4
         tmp = self.get_tile_memory(tx, ty, readonly=True)
         tmp = tmp.astype('float32') / (1<<15)
         tmp[:,:,0:3] /= tmp[:,:,3:].clip(0.0001, 1.0) # un-premultiply alpha
         tmp = tmp.clip(0.0,1.0)
-        dst[:,:,:] = tmp * 255.0
+        tmp *= 255.0 + 0.5 # correct rounding (important)
+        dst[:,:,:] = tmp
 
     def composite_tile_over(self, dst, tx, ty):
         """
index d3e6543..6882b6c 100755 (executable)
@@ -46,6 +46,37 @@ def brushPaint():
 def files_equal(a, b):
     return open(a, 'rb').read() == open(b, 'rb').read()
 
+def pngs_equal(a, b):
+    if files_equal(a, b):
+        return True
+    diff = imread(b) - imread(a)
+
+    print a, 'and', b, 'are different, analyzing whether it is just the undefined colors...'
+    print 'Average difference (255=white): (R, G, B, A)'
+    print mean(mean(diff, 0), 0) * 255
+    print 'Average difference with premultiplied alpha (255=white): (R, G, B, A)'
+    diff2 = diff[:,:,0:3] * imread(a)[:,:,3:4]
+    res = mean(mean(diff2, 0), 0) * 255
+    print res
+
+    res = max(abs(res)) < 0.1
+    if res == False:
+        print 'Not equal enough!'
+        figure(1)
+        title('Combined')
+        imshow(diff)
+        figure(2)
+        title('Green')
+        colorbar()
+        imshow(diff[:,:,1])
+        figure(3)
+        title('Alpha')
+        colorbar()
+        imshow(diff[:,:,3])
+        show()
+
+    return res
+
 def docPaint():
     b1 = brush.Brush_Lowlevel()
     b1.load_from_string(open('brushes/s008.myb').read())
@@ -85,7 +116,7 @@ def docPaint():
 
     doc.layers[0].surface.save('test_docPaint_a.png')
     doc.layers[0].surface.save('test_docPaint_a1.png')
-    assert files_equal('test_docPaint_a.png', 'test_docPaint_a1.png')
+    assert pngs_equal('test_docPaint_a.png', 'test_docPaint_a1.png')
 
     # test save/load
     f1 = StringIO()
@@ -96,14 +127,20 @@ def docPaint():
     # TODO: fix this one?!
     #assert doc.get_bbox() == doc2.get_bbox()
     doc2.layers[0].surface.save('test_docPaint_b.png')
-    assert files_equal('test_docPaint_a.png', 'test_docPaint_b.png')
+    assert pngs_equal('test_docPaint_a.png', 'test_docPaint_b.png')
     doc2.save('test_f2.ora')
-    assert files_equal('test_f1.ora', 'test_f2.ora')
-
-    doc2.layers[0].surface.save('test_docPaint_c.png')
-    assert files_equal('test_docPaint_a.png', 'test_docPaint_c.png')
+    #check not possible, because PNGs not exactly equal:
+    #assert files_equal('test_f1.ora', 'test_f2.ora')
+
+    # less strict test than above (just require load-save-load-save not to alter the file)
+    doc3 = document.Document()
+    doc3.load('test_f2.ora')
+    assert doc2.get_bbox() == doc3.get_bbox()
+    doc3.layers[0].surface.save('test_docPaint_c.png')
+    assert pngs_equal('test_docPaint_b.png', 'test_docPaint_c.png')
     doc2.save('test_f3.ora')
-    assert files_equal('test_f1.ora', 'test_f3.ora')
+    #check not possible, because PNGs not exactly equal:
+    #assert files_equal('test_f2.ora', 'test_f3.ora')
 
     # note: this is not supposed to be strictly reproducible because
     # of different random seeds [huh? what does that mean?]