Ticket #3324: m4ri_png.patch

File m4ri_png.patch, 6.9 kB (added by malb, 7 months ago)

new patch addresses review

  • a/sage/matrix/matrix_mod2_dense.pyx

    old new  
    106106from sage.misc.functional import log 
    107107 
    108108from sage.misc.misc import verbose, get_verbose, cputime 
     109 
     110cdef extern from "gd.h": 
     111    ctypedef struct gdImagePtr "gdImagePtr": 
     112        pass 
     113     
     114    gdImagePtr gdImageCreateFromPng(FILE *f) 
     115    gdImagePtr gdImageCreateFromPngPtr(int size, void *s) 
     116    gdImagePtr gdImageCreate(int x, int y) 
     117    void gdImagePng(gdImagePtr im, FILE *out) 
     118    void *gdImagePngPtr(gdImagePtr im, int *size) 
     119    void gdImageDestroy(gdImagePtr im) 
     120    int gdImageSX(gdImagePtr im) 
     121    int gdImageSY(gdImagePtr im) 
     122    int gdImageGetPixel(gdImagePtr im, int x, int y) 
     123    void gdImageSetPixel(gdImagePtr im, int x, int y, int value) 
     124    int gdImageColorAllocate(gdImagePtr im, int r, int g, int b) 
     125    void gdImageFilledRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color) 
     126    void gdFree(void *m) 
    109127 
    110128## from sage.libs.linbox.linbox cimport Linbox_mod2_dense 
    111129## cdef Linbox_mod2_dense linbox 
     
    12041222        A._entries = mzd_submatrix(A._entries, self._entries, lowr, lowc, highr, highc) 
    12051223        return A 
    12061224 
     1225    def __reduce__(self): 
     1226        r""" 
     1227        Serialize \code{self}. 
     1228 
     1229        EXAMPLE: 
     1230            sage: A = random_matrix(GF(2),10,10) 
     1231            sage: f,s = A.__reduce__() 
     1232            sage: f(*s) == A 
     1233            True 
     1234        """ 
     1235        cdef int i,j, r,c, size 
     1236 
     1237        r, c = self.nrows(), self.ncols() 
     1238        if r == 0 or c == 0: 
     1239            return unpickle_matrix_mod2_dense_v1, (r, c, None, 0) 
     1240 
     1241        _sig_on 
     1242        cdef gdImagePtr im = gdImageCreate(c, r) 
     1243        _sig_off 
     1244        cdef int black = gdImageColorAllocate(im, 0, 0, 0) 
     1245        cdef int white = gdImageColorAllocate(im, 255, 255, 255) 
     1246        gdImageFilledRectangle(im, 0, 0, c-1, r-1, white) 
     1247        for i from 0 <= i < r: 
     1248            for j from 0 <= j < c: 
     1249                if mzd_read_bit(self._entries, i, j): 
     1250                    gdImageSetPixel(im, j, i, black ) 
     1251 
     1252        cdef char *buf = <char*>gdImagePngPtr(im, &size) 
     1253 
     1254        data = [buf[i] for i in range(size)] 
     1255        gdFree(buf) 
     1256        return unpickle_matrix_mod2_dense_v1, (r,c, data, size) 
     1257 
     1258def unpickle_matrix_mod2_dense_v1(r, c, data, size): 
     1259    r""" 
     1260    Deserialize a matrix encoded in the string \code{s}. 
     1261 
     1262    INPUT: 
     1263        r -- number of rows of matrix 
     1264        c -- number of columns of matrix 
     1265        s -- a string 
     1266        size -- length of the string s 
     1267 
     1268    EXAMPLE: 
     1269        sage: A = random_matrix(GF(2),100,101) 
     1270        sage: _,(r,c,s,s2) = A.__reduce__() 
     1271        sage: from sage.matrix.matrix_mod2_dense import unpickle_matrix_mod2_dense_v1 
     1272        sage: unpickle_matrix_mod2_dense_v1(r,c,s,s2) == A 
     1273        True 
     1274        sage: loads(dumps(A)) == A 
     1275        True 
     1276    """ 
     1277    from sage.matrix.constructor import Matrix 
     1278    from sage.rings.finite_field import FiniteField as GF 
     1279 
     1280    cdef int i, j 
     1281    cdef Matrix_mod2_dense A 
     1282 
     1283    A = <Matrix_mod2_dense>Matrix(GF(2),r,c) 
     1284    if r == 0 or c == 0: 
     1285        return A 
     1286 
     1287    cdef char *buf = <char*>sage_malloc(size) 
     1288    for i from 0 <= i < size: 
     1289        buf[i] = data[i] 
     1290 
     1291    _sig_on 
     1292    cdef gdImagePtr im = gdImageCreateFromPngPtr(size, buf) 
     1293    _sig_off 
     1294     
     1295    sage_free(buf) 
     1296         
     1297    if gdImageSX(im) != c or gdImageSY(im) != r: 
     1298        raise TypeError, "Pickled data dimension doesn't match." 
     1299 
     1300 
     1301    for i from 0 <= i < r: 
     1302        for j from 0 <= j < c: 
     1303            mzd_write_bit(A._entries, i, j, 1-gdImageGetPixel(im, j, i)) 
     1304    gdImageDestroy(im) 
     1305    return A 
     1306         
     1307def from_png(filename): 
     1308    r""" 
     1309    Returns a dense matrix over GF(2) from a 1-bit PNG image read from 
     1310    \code{filename}. No attempt is made to verify that the filname string 
     1311    actually points to a PNG image. 
     1312 
     1313    INPUT: 
     1314        filename -- a string 
     1315 
     1316    EXAMPLE: 
     1317        sage: from sage.matrix.matrix_mod2_dense import from_png, to_png 
     1318        sage: A = random_matrix(GF(2),10,10) 
     1319        sage: fn = tmp_filename() 
     1320        sage: to_png(A, fn) 
     1321        sage: B = from_png(fn) 
     1322        sage: A == B 
     1323        True 
     1324    """ 
     1325    from sage.matrix.constructor import Matrix 
     1326    from sage.rings.finite_field import FiniteField as GF 
     1327 
     1328    cdef int i,j,r,c 
     1329    cdef Matrix_mod2_dense A 
     1330 
     1331    fn = open(filename,"r") # check filename 
     1332    fn.close()  
     1333 
     1334    cdef FILE *f = fopen(filename, "rb") 
     1335    _sig_on 
     1336    cdef gdImagePtr im = gdImageCreateFromPng(f) 
     1337    _sig_off 
     1338 
     1339    c, r = gdImageSX(im), gdImageSY(im) 
     1340 
     1341    A = <Matrix_mod2_dense>Matrix(GF(2),r,c) 
     1342 
     1343    for i from 0 <= i < r: 
     1344        for j from 0 <= j < c: 
     1345            mzd_write_bit(A._entries, i, j, 1-gdImageGetPixel(im, j, i)) 
     1346    fclose(f) 
     1347    gdImageDestroy(im) 
     1348    return A 
     1349 
     1350def to_png(Matrix_mod2_dense A, filename): 
     1351    r""" 
     1352    Saves the matrix \code{A} to filename as a 1-bit PNG image. 
     1353     
     1354    INPUT: 
     1355        A -- a matrix over GF(2) 
     1356        filename -- a string for a file in a writeable position 
     1357 
     1358    EXAMPLE: 
     1359        sage: from sage.matrix.matrix_mod2_dense import from_png, to_png 
     1360        sage: A = random_matrix(GF(2),10,10) 
     1361        sage: fn = tmp_filename() 
     1362        sage: to_png(A, fn) 
     1363        sage: B = from_png(fn) 
     1364        sage: A == B 
     1365        True 
     1366    """ 
     1367    cdef int i,j, r,c 
     1368    r, c = A.nrows(), A.ncols() 
     1369    if r == 0 or c == 0: 
     1370        raise TypeError, "Cannot write image with dimensions %d x %d"%(c,r) 
     1371    fn = open(filename,"w") # check filename 
     1372    fn.close()  
     1373    cdef gdImagePtr im = gdImageCreate(c, r) 
     1374    cdef FILE * out = fopen(filename, "wb") 
     1375    cdef int black = gdImageColorAllocate(im, 0, 0, 0) 
     1376    cdef int white = gdImageColorAllocate(im, 255, 255, 255) 
     1377    gdImageFilledRectangle(im, 0, 0, c-1, r-1, white) 
     1378    for i from 0 <= i < r: 
     1379        for j from 0 <= j < c: 
     1380            if mzd_read_bit(A._entries, i, j): 
     1381                gdImageSetPixel(im, j, i, black ) 
     1382 
     1383    gdImagePng(im, out) 
     1384    gdImageDestroy(im) 
     1385    fclose(out) 
  • a/setup.py

    old new  
    332332 
    333333matrix_mod2_dense = Extension('sage.matrix.matrix_mod2_dense', 
    334334                              ['sage/matrix/matrix_mod2_dense.pyx'], 
    335                               libraries = ['gmp','m4ri']) 
     335                              libraries = ['gmp','m4ri', 'png', 'gd']) 
    336336 
    337337matrix_modn_sparse = Extension('sage.matrix.matrix_modn_sparse', 
    338338                               ['sage/matrix/matrix_modn_sparse.pyx'])