Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,4 @@ test_alignment
/.cache/
/scratch.c
/configure~
/tests/test_pluq
67 changes: 35 additions & 32 deletions m4ri/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,44 +70,47 @@ void mzd_fprint_row(FILE *stream, mzd_t const *M, const rci_t i) {
#define PNGSIGSIZE 8

mzd_t *mzd_from_png(const char *fn, int verbose) {
int retval = 0;
mzd_t *A = NULL;
png_byte pngsig[PNGSIGSIZE];

FILE *fh = fopen(fn, "rb");

if (!fh) {
if (verbose) printf("Could not open file '%s' for reading\n", fn);
return NULL;
};

mzd_t *A = mzd_from_png_fh(fh, verbose);

fclose(fh);
return A;
}

mzd_t *mzd_from_png_fh(FILE *fh, int verbose) {
mzd_t *A = NULL;
png_byte pngsig[PNGSIGSIZE];

if (fread((char *)pngsig, PNGSIGSIZE, 1, fh) != 1) {
if (verbose) printf("Could not read file '%s'\n", fn);
retval = 1;
goto from_png_close_fh;
if (verbose) printf("Could not read PNG file\n");
return NULL;
}

if (png_sig_cmp(pngsig, 0, PNGSIGSIZE) != 0) {
if (verbose) printf("'%s' is not a PNG file.\n", fn);
retval = 2;
goto from_png_close_fh;
if (verbose) printf("Input is not a PNG file.\n");
return NULL;
}

png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

if (!png_ptr) {
if (verbose) printf("failed to initialise PNG read struct.\n");
retval = 3;
goto from_png_close_fh;
return NULL;
}
png_set_user_limits(png_ptr, 0x7fffffffL, 0x7fffffffL);

png_infop info_ptr = png_create_info_struct(png_ptr);

if (!info_ptr) {
if (verbose) printf("failed to initialise PNG info struct\n");
retval = 3;
goto from_png_destroy_read_struct;
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)0);
return NULL;
}

png_init_io(png_ptr, fh);
Expand All @@ -124,7 +127,8 @@ mzd_t *mzd_from_png(const char *fn, int verbose) {

if (interlace_type != PNG_INTERLACE_NONE) {
if (verbose) printf("interlaced images not supported\n");
goto from_png_destroy_read_struct;
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)0);
return NULL;
};

if (verbose)
Expand All @@ -135,7 +139,8 @@ mzd_t *mzd_from_png(const char *fn, int verbose) {

if (color_type != 0 && color_type != 3) {
if (verbose) printf("only graycscale and palette colors are supported.\n");
goto from_png_destroy_read_struct;
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)0);
return NULL;
}

A = mzd_init(m, n);
Expand Down Expand Up @@ -175,18 +180,9 @@ mzd_t *mzd_from_png(const char *fn, int verbose) {
m4ri_mm_free(row);
png_read_end(png_ptr, NULL);

from_png_destroy_read_struct:
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)0);

from_png_close_fh:
fclose(fh);

if (retval != 0 && A) {
mzd_free(A);
return NULL;
} else {
return A;
}
return A;
}

int mzd_to_png(const mzd_t *A, const char *fn, int compression_level, const char *comment,
Expand All @@ -198,11 +194,20 @@ int mzd_to_png(const mzd_t *A, const char *fn, int compression_level, const char
return 1;
}

int r = mzd_to_png_fh(A, fh, compression_level, comment, verbose);

fclose(fh);

return r;
}

int mzd_to_png_fh(const mzd_t *A, FILE *fh, int compression_level, const char *comment,
int verbose) {

png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

if (!png_ptr) {
if (verbose) printf("failed to initialise PNG write struct.\n");
fclose(fh);
return 3;
}
png_set_user_limits(png_ptr, 0x7fffffffL, 0x7fffffffL);
Expand All @@ -212,14 +217,12 @@ int mzd_to_png(const mzd_t *A, const char *fn, int compression_level, const char
if (!info_ptr) {
if (verbose) printf("failed to initialise PNG info struct\n");
png_destroy_write_struct(&png_ptr, &info_ptr);
fclose(fh);
return 3;
}

if (setjmp(png_jmpbuf(png_ptr))) {
if (verbose) printf("error writing PNG file\n");
png_destroy_write_struct(&png_ptr, &info_ptr);
fclose(fh);
return 1;
}

Expand Down Expand Up @@ -288,7 +291,6 @@ int mzd_to_png(const mzd_t *A, const char *fn, int compression_level, const char

png_write_end(png_ptr, info_ptr);
png_destroy_write_struct(&png_ptr, &info_ptr);
fclose(fh);
return 0;
}

Expand All @@ -300,7 +302,7 @@ mzd_t *mzd_from_jcf(const char *fn, int verbose) {
FILE *fh = fopen(fn, "r");

rci_t m, n;
int p = 0;
int p = 0;
int64_t nonzero = 0;

if (!fh) {
Expand All @@ -321,7 +323,8 @@ mzd_t *mzd_from_jcf(const char *fn, int verbose) {
}

if (verbose)
printf("reading %d x %d matrix with at most %" PRId64 " non-zero entries (density at most: %6.5f)\n",
printf("reading %d x %d matrix with at most %" PRId64
" non-zero entries (density at most: %6.5f)\n",
m, n, nonzero, ((double)nonzero) / ((double)m * n));

A = mzd_init(m, n);
Expand Down
31 changes: 29 additions & 2 deletions m4ri/io.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ void mzd_info(const mzd_t *A, int do_rank);
#if __M4RI_HAVE_LIBPNG

/**
* \brief Read matrix from 1-bit PNG image.
* \brief Read matrix from a 1-bit PNG image.
*
* This function returns a matrix on success and NULL otherwise. 1-bit
* Grayscale and 1-bit Palette images are supported.
Expand All @@ -103,7 +103,19 @@ void mzd_info(const mzd_t *A, int do_rank);
mzd_t *mzd_from_png(const char *fn, int verbose);

/**
* \brief Write matrix to 1-bit PNG image.
* \brief Read matrix from a 1-bit PNG image.
*
* This function returns a matrix on success and NULL otherwise. 1-bit
* Grayscale and 1-bit Palette images are supported.
*
* \param fh a file handle
* \param verbose Print error message to stdout if != 0
*/

mzd_t *mzd_from_png_fh(FILE *fh, int verbose);

/**
* \brief Write matrix to a 1-bit PNG image.
*
* This function returns zero on success and some value != 0
* otherwise. The parameter compression_level takes a zlib compression
Expand All @@ -129,6 +141,21 @@ mzd_t *mzd_from_png(const char *fn, int verbose);
int mzd_to_png(const mzd_t *A, const char *fn, int compression_level, const char *comment,
int verbose);

/**
* \brief Write matrix to a 1-bit PNG image.
*
* See mzd_to_png for details.
*
* \param A Matrix
* \param fh a file handle (must have write permission)
* \param compression_level Zlib compression level (see above)
* \param comment Optional comment (may be NULL)
* \param verbose Print error message to stdout if != 0
*/

int mzd_to_png_fh(const mzd_t *A, FILE *fh, int compression_level, const char *comment,
int verbose);

#endif //__M4RI_HAVE_LIBPNG

/**
Expand Down
8 changes: 8 additions & 0 deletions tests/test_misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,15 @@ int test_png(rci_t m, rci_t n) {

ret += mzd_cmp(A, B);

FILE *fh = tmpfile();
mzd_to_png_fh(A, fh, 9, NULL, 0);
rewind(fh);
mzd_t *C = mzd_from_png_fh(fh, 0);

ret += mzd_cmp(A, C);

remove(fn);
mzd_free(C);
mzd_free(B);
mzd_free(A);

Expand Down