aboutsummaryrefslogtreecommitdiffstats
path: root/src/png.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/png.c')
-rw-r--r--src/png.c106
1 files changed, 54 insertions, 52 deletions
diff --git a/src/png.c b/src/png.c
index 0944f18..b0da466 100644
--- a/src/png.c
+++ b/src/png.c
@@ -18,11 +18,7 @@
*/
#include "common.h"
#include "png.h"
-
-#ifdef __GNUC__
-# pragma GCC diagnostic ignored "-Wpadded"
-#endif
-#include <png.h>
+#include "kern.h"
/*
@@ -30,50 +26,37 @@
*
* Users want their files in PNG (most often), not PNM.
* Calling an external program for conversion poses
- * potential security risks, and is slower.
+ * potential security risks, and is significantly slower.
*/
/**
- * Convert an image from PNM to PNG.
- *
- * This is a very limited conversion implementation.
- * It is not generally reusable. It makes assumptions
- * that are true only necessarily for this program.
+ * Create an PNG file.
*
- * @param fdin The file descriptor for the image to convert (PNM).
- * @param fdout The file descriptor for the output image (PNG).
- * @return Zero on success, -1 on error.
+ * @param fbfd The file descriptor connected to framebuffer device.
+ * @param width The width of the image.
+ * @param height The height of the image.
+ * @param imgfd The file descriptor connected to conversion process's stdin.
+ * @return Zero on success, -1 on error.
*/
int
-convert (int fdin, int fdout)
+save_png (int fbfd, long width, long height, int imgfd)
{
-#define SCAN(...) do { if (fscanf(in, __VA_ARGS__) != 1) goto fail; } while (0)
-
- FILE *in = NULL;
- FILE *out = NULL;
- long height, width, width3;
- long y, x, r, g, b;
- png_byte *pixbuf = 0;
+ char buf[8 << 10];
+ FILE *file = NULL;
+ ssize_t got, off;
+ size_t adjustment;
+ png_byte *restrict pixbuf = NULL;
png_struct *pngbuf = NULL;
png_info *pnginfo = NULL;
- int saved_errno = 0, rc, c;
+ long width3, state = 0;
+ int rc, saved_errno;
- /* Get a FILE * for the input, we want to use fscanf, there is no dscanf. */
- in = fdopen (fdin, "r");
- if (in == NULL)
- goto fail;
/* Get a FILE * for the output, libpng wants a FILE *, not a file descriptor. */
- out = fdopen (fdout, "w");
- if (out == NULL)
+ file = fdopen (imgfd, "w");
+ if (file == NULL)
goto fail;
- /* Read head. */
- do c = fgetc(in); while ((c != '\n') && (c != EOF));
- SCAN ("%li ", &width);
- SCAN ("%li\n", &height);
- do c = fgetc(in); while ((c != '\n') && (c != EOF));
-
/* Allocte structures for the PNG. */
width3 = width * 3;
pixbuf = malloc ((size_t)width3 * sizeof (png_byte));
@@ -89,28 +72,45 @@ convert (int fdin, int fdout)
/* Initialise PNG write, and write head. */
if (setjmp (png_jmpbuf(pngbuf))) /* Failing libpng calls jump here. */
goto fail;
- png_init_io (pngbuf, out);
+ png_init_io (pngbuf, file);
png_set_IHDR (pngbuf, pnginfo, (png_uint_32)width, (png_uint_32)height,
8 /* bit depth */, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
png_write_info (pngbuf, pnginfo);
- /* Read and convert body. */
- for (y = 0; y < height; y++)
+ /* TODO (maybe) The image shall be packed. That is, if 24 bits per pixel is
+ * unnecessary, less shall be used. 6 bits is often sufficient. */
+
+ /* Convert raw framebuffer data into a PNG image (body). */
+ for (off = 0;;)
{
- for (x = 0; x < width3; x += 3)
+ /* Read data from the framebuffer, we may have up to 3 bytes buffered. */
+ got = read (fbfd, buf + off, sizeof (buf) - (size_t)off * sizeof (char));
+ if (got < 0)
+ goto fail;
+ if (got == 0)
+ break;
+ got += off;
+
+ /* Convert read pixels. */
+ if (convert_fb_to_png (pngbuf, pixbuf, buf, (size_t)got,
+ width3, &adjustment, &state) < 0)
+ goto fail;
+
+ /* If we read a whole number of pixels, reset the buffer, otherwise,
+ move the unconverted bytes to the beginning of the buffer. */
+ if (adjustment)
{
- SCAN ("%li\n", &r);
- SCAN ("%li\n", &g);
- SCAN ("%li\n", &b);
- pixbuf[x + 0] = (png_byte)r;
- pixbuf[x + 1] = (png_byte)g;
- pixbuf[x + 2] = (png_byte)b;
+ off -= (ssize_t)adjustment;
+ memcpy (buf, buf + off, (size_t)(got - off) * sizeof (char));
+ off = got - off;
}
- png_write_row (pngbuf, pixbuf);
+ else
+ off = 0;
}
- png_write_end (pngbuf, pnginfo);
+ /* Done! */
+ png_write_end (pngbuf, pnginfo);
rc = 0;
goto cleanup;
fail:
@@ -120,11 +120,13 @@ convert (int fdin, int fdout)
cleanup:
png_destroy_write_struct (&pngbuf, (pnginfo ? &pnginfo : NULL));
- if (in != NULL)
- fclose (in);
- if (out != NULL)
- fclose (out);
+ if (file != NULL)
+ {
+ fflush (file);
+ fclose (file);
+ }
free (pixbuf);
- return errno = saved_errno, rc;
+ errno = saved_errno;
+ return rc;
}