aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.in2
-rw-r--r--NEWS11
-rw-r--r--po/sv.po18
-rw-r--r--src/kern-linux.c54
-rw-r--r--src/kern.h31
-rw-r--r--src/png.c106
-rw-r--r--src/png.h46
-rw-r--r--src/pnm.c118
-rw-r--r--src/pnm.h17
-rw-r--r--src/scrotty.c194
10 files changed, 344 insertions, 253 deletions
diff --git a/Makefile.in b/Makefile.in
index 4f812f4..af7ea0c 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -56,7 +56,7 @@ _VERSION = 2.0
_C_STD = c99
_PEDANTIC = yes
_BIN = scrotty
-_OBJ_scrotty = scrotty kern-linux info pattern png
+_OBJ_scrotty = scrotty kern-linux info pattern pnm png
_HEADER_DIRLEVELS = 1
_CPPFLAGS = -D'PACKAGE="$(PKGNAME)"' -D'PROGRAM_VERSION="$(_VERSION)"'
_CPPFLAGS += $(shell pkg-config --cflags libpng)
diff --git a/NEWS b/NEWS
index 8016618..1bd2dad 100644
--- a/NEWS
+++ b/NEWS
@@ -36,10 +36,21 @@ scrotty NEWS -*- outline -*-
The invocation syntax is less strict, and short options
have been added.
+ Performance is significantly improved (for PNG images)
+ because images are stored directly as PNG and not converted.
+
** Translations
The program and the man page has been translated to Swedish.
+** Bug fixes
+
+ The images is not saved as PNM if PNG is requested but the
+ filenames does not end with .png, which could happend when
+ the program selected filename automatically and needed to
+ add a number at the end so that existing files were not
+ overriden.
+
* Noteworthy changes in release 1.0.2 (2015-(10)Dec-01 UTC) [stable]
diff --git a/po/sv.po b/po/sv.po
index 63e9244..e92e8ec 100644
--- a/po/sv.po
+++ b/po/sv.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: scrotty 1.1\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-12-11 12:27+0100\n"
+"POT-Creation-Date: 2015-12-11 13:21+0100\n"
"PO-Revision-Date: 2015-12-07 18:50+0100\n"
"Last-Translator: Mattias Andrée <maandree@member.fsf.org>\n"
"Language-Team: none\n"
@@ -17,39 +17,39 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-#: src/scrotty.c:387
+#: src/scrotty.c:225
#, c-format
msgid "Saved framebuffer %i to %s.\n"
msgstr "Bildrutebuffert %i sparad till %s.\n"
-#: src/scrotty.c:519 src/scrotty.c:523 src/scrotty.c:529
+#: src/scrotty.c:357 src/scrotty.c:361 src/scrotty.c:367
#, c-format
msgid "%s: %s. Type '%s --help' for help.\n"
msgstr "%s: %s. Kör '%s --help' för hjälp.\n"
-#: src/scrotty.c:519
+#: src/scrotty.c:357
msgid "--exec is used twice."
msgstr "--exec förkommer mer än en gång."
-#: src/scrotty.c:523
+#: src/scrotty.c:361
msgid "Invalid input."
msgstr "Ogiltig indata."
-#: src/scrotty.c:529
+#: src/scrotty.c:367
msgid "FILENAME-PATTERN is used twice."
msgstr "FILNAMNSMÖNSTER förekommer mer än en gång"
-#: src/scrotty.c:542
+#: src/scrotty.c:380
#, c-format
msgid "%s: It looks like you are inside a display server. If this is correct, what you see is probably not what you get.\n"
msgstr "%s: Det ser ut som att du är innan för en grafikserver. Om detta är korrect, vad de ser är troligtvis inte vad du får.\n"
-#: src/scrotty.c:552
+#: src/scrotty.c:390
#, c-format
msgid "%s: %s: %s\n"
msgstr "%s: %s: %s\n"
-#: src/kern-linux.c:41
+#: src/kern-linux.c:42
#, c-format
msgid "%s: Unable to find a framebuffer. If you have a file named %s/MAKEDEV, run it with '-d /dev/fb' as root, or try running '%s'.\n"
msgstr "%s: Kunde inte hitta någon bildrutebuffert. Om filen %s/MAKEDEV finns ditt system, kör den med '-d /dev/fb' som root, eller testa att köra '%s'.\n"
diff --git a/src/kern-linux.c b/src/kern-linux.c
index fdae636..00930f1 100644
--- a/src/kern-linux.c
+++ b/src/kern-linux.c
@@ -19,6 +19,7 @@
#include "common.h"
#include "kern.h"
#include "pnm.h"
+#include "png.h"
@@ -128,8 +129,8 @@ measure (int fbno, char *restrict fbpath, long *restrict width, long *restrict h
* @return Zero on success, -1 on error.
*/
int
-convert_fb (FILE *restrict file, const char *restrict buf,
- size_t n, size_t *restrict adjustment)
+convert_fb_to_pnm (FILE *restrict file, const char *restrict buf,
+ size_t n, size_t *restrict adjustment)
{
const uint32_t *restrict pixel;
int r, g, b;
@@ -144,7 +145,7 @@ convert_fb (FILE *restrict file, const char *restrict buf,
g = (*pixel >> 8) & 255;
b = (*pixel >> 0) & 255;
- if (SAVE_PIXEL (file, r, g, b) < 0)
+ if (SAVE_PNM_PIXEL (file, r, g, b) < 0)
goto fail;
}
@@ -154,3 +155,50 @@ convert_fb (FILE *restrict file, const char *restrict buf,
return -1;
}
+
+/**
+ * Convert read data from a framebuffer to PNG pixel data.
+ *
+ * @param file The output image file.
+ * @param buf Buffer with read data.
+ * @param n The number of read characters.
+ * @param width3 The width of the image multipled by 3.
+ * @param adjustment Set to zero if all bytes were converted
+ * (a whole number of pixels where available,)
+ * otherwise, set to the number of bytes a
+ * pixel is encoded.
+ * @param state Use this to keep track of where in the you
+ * stopped. It will be 0 on the first call.
+ * @return Zero on success, -1 on error.
+ */
+int convert_fb_to_png (png_struct *pngbuf, png_byte *restrict pixbuf, const char *restrict buf,
+ size_t n, long width3, size_t *restrict adjustment, long *restrict state)
+{
+ const uint32_t *restrict pixel;
+ int r, g, b;
+ size_t off;
+ long x3 = *state;
+
+ for (off = 0; off < n; off += 4)
+ {
+ /* A pixel in the framebuffer is formatted as `%{blue}%{green}%{red}%{x}`
+ in big-endian binary, or `%{x}%{red}%{green}%{blue}` in little-endian binary. */
+ pixel = (const uint32_t *)(buf + off);
+ r = (*pixel >> 16) & 255;
+ g = (*pixel >> 8) & 255;
+ b = (*pixel >> 0) & 255;
+
+ SAVE_PNG_PIXEL (pixbuf, x3, r, g, b);
+ x3 += 3;
+ if (x3 == width3)
+ {
+ SAVE_PNG_ROW (pngbuf, pixbuf);
+ x3 = 0;
+ }
+ }
+
+ *adjustment = (off != n ? 4 : 0);
+ *state = x3;
+ return 0;
+}
+
diff --git a/src/kern.h b/src/kern.h
index 45f692a..8c2adf0 100644
--- a/src/kern.h
+++ b/src/kern.h
@@ -16,6 +16,15 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#ifdef __GNUC__
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wpadded"
+#endif
+#include <png.h>
+#ifdef __GNUC__
+# pragma GCC diagnostic pop
+#endif
+
/**
@@ -65,6 +74,24 @@ int measure (int fbno, char *restrict fbpath, long *restrict width, long *restri
* pixel is encoded.
* @return Zero on success, -1 on error.
*/
-int convert_fb (FILE *restrict file, const char *restrict buf,
- size_t n, size_t *restrict adjustment);
+int convert_fb_to_pnm (FILE *restrict file, const char *restrict buf,
+ size_t n, size_t *restrict adjustment);
+
+/**
+ * Convert read data from a framebuffer to PNG pixel data.
+ *
+ * @param file The output image file.
+ * @param buf Buffer with read data.
+ * @param n The number of read characters.
+ * @param width3 The width of the image multipled by 3.
+ * @param adjustment Set to zero if all bytes were converted
+ * (a whole number of pixels where available,)
+ * otherwise, set to the number of bytes a
+ * pixel is encoded.
+ * @param state Use this to keep track of where in the you
+ * stopped. It will be 0 on the first call.
+ * @return Zero on success, -1 on error.
+ */
+int convert_fb_to_png (png_struct *pngbuf, png_byte *restrict pixbuf, const char *restrict buf,
+ size_t n, long width3, size_t *restrict adjustment, long *restrict state);
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;
}
diff --git a/src/png.h b/src/png.h
index 02a6223..b621234 100644
--- a/src/png.h
+++ b/src/png.h
@@ -16,14 +16,50 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#ifdef __GNUC__
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wpadded"
+#endif
+#include <png.h>
+#ifdef __GNUC__
+# pragma GCC diagnostic pop
+#endif
+
+
+
+/**
+ * Store a pixel to a PNG row buffer.
+ *
+ * @param PIXBUF:png_byte * The pixel buffer for the row.
+ * @param X3:long The column of the pixel multipled by 3.
+ * @param R:int The [0, 255]-value on the red subpixel.
+ * @param G:int The [0, 255]-value on the green subpixel.
+ * @param B:int The [0, 255]-value on the blue subpixel.
+ */
+#define SAVE_PNG_PIXEL(PIXBUF, X3, R, G, B) \
+ ((PIXBUF)[(X3) + 0] = (png_byte)(R), \
+ (PIXBUF)[(X3) + 1] = (png_byte)(G), \
+ (PIXBUF)[(X3) + 2] = (png_byte)(B))
+
+/**
+ * Store a row to a PNG image.
+ *
+ * @param PNGBUF:png_struct * The PNG image structure.
+ * @param PIXBUF:png_byte * The pixel buffer for the row.
+ */
+#define SAVE_PNG_ROW(PNGBUF, PIXBUF) \
+ png_write_row (PNGBUF, PIXBUF)
/**
- * Convert an image from PNM to PNG.
+ * 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);
+int
+save_png (int fbfd, long width, long height, int imgfd);
diff --git a/src/pnm.c b/src/pnm.c
new file mode 100644
index 0000000..da9dd3a
--- /dev/null
+++ b/src/pnm.c
@@ -0,0 +1,118 @@
+/**
+ * scrotty — Screenshot program for Linux's TTY
+ *
+ * Copyright © 2014, 2015 Mattias Andrée (maandree@member.fsf.org)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include "common.h"
+#include "pnm.h"
+#include "kern.h"
+
+
+
+#define LIST_0_9(P) P"0\n", P"1\n", P"2\n", P"3\n", P"4\n", P"5\n", P"6\n", P"7\n", P"8\n", P"9\n"
+/**
+ * [0, 255]-integer-to-text convertion lookup table for faster conversion from
+ * raw framebuffer data to the PNM format. The values have a whitespace at the
+ * end for even faster conversion.
+ * Lines should not be longer than 70 (although most programs will probably
+ * work even if there are longer lines), therefore the selected whitespace
+ * is LF (new line).
+ *
+ * ASCII has wider support than binary, and is create for version control,
+ * especifially with one datum per line.
+ */
+const char* inttable[] =
+ {
+ LIST_0_9(""), LIST_0_9("1"), LIST_0_9("2"), LIST_0_9("3"), LIST_0_9("4"),
+ LIST_0_9("5"), LIST_0_9("6"), LIST_0_9("7"), LIST_0_9("8"), LIST_0_9("9"),
+
+ LIST_0_9("10"), LIST_0_9("11"), LIST_0_9("12"), LIST_0_9("13"), LIST_0_9("14"),
+ LIST_0_9("15"), LIST_0_9("16"), LIST_0_9("17"), LIST_0_9("18"), LIST_0_9("19"),
+
+ LIST_0_9("20"), LIST_0_9("21"), LIST_0_9("22"), LIST_0_9("23"), LIST_0_9("24"),
+ "250\n", "251\n", "252\n", "253\n", "254\n", "255\n"
+ };
+
+
+
+/**
+ * Create an PNM file.
+ *
+ * @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
+save_pnm (int fbfd, long width, long height, int imgfd)
+{
+ char buf[8 << 10];
+ FILE *file = NULL;
+ ssize_t got, off;
+ size_t adjustment;
+ int saved_errno;
+
+ /* Create a FILE *, for writing, for the image file. */
+ file = fdopen (imgfd, "w");
+ if (file == NULL)
+ goto fail;
+
+ /* The PNM image should begin with `P3\n%{width} %{height}\n%{colour max=255}\n`.
+ ('\n' and ' ' can be exchanged at will.) */
+ if (fprintf (file, "P3\n%li %li\n255\n", width, height) < 0)
+ goto fail;
+
+ /* Convert raw framebuffer data into a PNM image. */
+ for (off = 0;;)
+ {
+ /* 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_pnm (file, buf, (size_t)got, &adjustment) < 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)
+ {
+ off -= (ssize_t)adjustment;
+ memcpy (buf, buf + off, (size_t)(got - off) * sizeof (char));
+ off = got - off;
+ }
+ else
+ off = 0;
+ }
+
+ /* Close file and return successfully. */
+ fflush (file);
+ fclose (file);
+ return 0;
+
+ fail:
+ saved_errno = errno;
+ if (file != NULL)
+ fclose (file);
+ errno = saved_errno;
+ return -1;
+}
+
diff --git a/src/pnm.h b/src/pnm.h
index 172e3cb..9721d4c 100644
--- a/src/pnm.h
+++ b/src/pnm.h
@@ -16,11 +16,10 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <stdio.h>
/**
- * Store a pixel to an PNM image.
+ * Store a pixel to a PNM image.
*
* A pixel in the PNM image is formatted as `%{red} %{green} %{blue} ` in text.
*
@@ -30,7 +29,7 @@
* @param B:int The [0, 255]-value on the blue subpixel.
* @return Positive on success (not zero!), -1 on error.
*/
-#define SAVE_PIXEL(F, R, G, B) \
+#define SAVE_PNM_PIXEL(F, R, G, B) \
fprintf (F, "%s%s%s", inttable[R], inttable[G], inttable[B])
@@ -47,3 +46,15 @@
*/
extern const char* inttable[];
+
+/**
+ * Create an PNM file.
+ *
+ * @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 save_pnm (int fbfd, long width, long height, int imgfd);
+
diff --git a/src/scrotty.c b/src/scrotty.c
index c076fa4..4bc6982 100644
--- a/src/scrotty.c
+++ b/src/scrotty.c
@@ -42,31 +42,6 @@
#define LIST_DISPLAY_VARS X(DISPLAY) X(MDS_DISPLAY) X(MIR_DISPLAY) X(WAYLAND_DISPLAY) X(PREFERRED_DISPLAY)
-#define LIST_0_9(P) P"0\n", P"1\n", P"2\n", P"3\n", P"4\n", P"5\n", P"6\n", P"7\n", P"8\n", P"9\n"
-/**
- * [0, 255]-integer-to-text convertion lookup table for faster conversion from
- * raw framebuffer data to the PNM format. The values have a whitespace at the
- * end for even faster conversion.
- * Lines should not be longer than 70 (although most programs will probably
- * work even if there are longer lines), therefore the selected whitespace
- * is LF (new line).
- *
- * ASCII has wider support than binary, and is create for version control,
- * especifially with one datum per line.
- */
-const char* inttable[] =
- {
- LIST_0_9(""), LIST_0_9("1"), LIST_0_9("2"), LIST_0_9("3"), LIST_0_9("4"),
- LIST_0_9("5"), LIST_0_9("6"), LIST_0_9("7"), LIST_0_9("8"), LIST_0_9("9"),
-
- LIST_0_9("10"), LIST_0_9("11"), LIST_0_9("12"), LIST_0_9("13"), LIST_0_9("14"),
- LIST_0_9("15"), LIST_0_9("16"), LIST_0_9("17"), LIST_0_9("18"), LIST_0_9("19"),
-
- LIST_0_9("20"), LIST_0_9("21"), LIST_0_9("22"), LIST_0_9("23"), LIST_0_9("24"),
- "250\n", "251\n", "252\n", "253\n", "254\n", "255\n"
- };
-
-
/**
* `argv[0]` from `main`.
@@ -89,85 +64,6 @@ static int try_alt_fbpath = 0;
/**
- * Create an PNM-file that is sent to a conversion process,
- * or directly to a file.
- *
- * @param fbname The framebuffer device.
- * @param width The width of the image.
- * @param height The height of the image.
- * @param fd The file descriptor connected to conversion process's stdin.
- * @return Zero on success, -1 on error.
- */
-static int
-save_pnm (const char *fbpath, long width, long height, int fd)
-{
- char buf[8 << 10];
- FILE *file = NULL;
- int fbfd = 1;
- ssize_t got, off;
- int saved_errno;
- size_t adjustment;
-
- /* Open the framebuffer device for reading. */
- fbfd = open (fbpath, O_RDONLY);
- if (fbfd == -1)
- goto fail;
-
- /* Create a FILE *, for writing, for the image file. */
- file = fdopen (fd, "w");
- if (file == NULL)
- goto fail;
-
- /* The PNM image should begin with `P3\n%{width} %{height}\n%{colour max=255}\n`.
- ('\n' and ' ' can be exchanged at will.) */
- if (fprintf (file, "P3\n%li %li\n255\n", width, height) < 0)
- goto fail;
-
- /* Convert raw framebuffer data into an PNM image. */
- for (off = 0;;)
- {
- /* 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 (file, buf, (size_t)got, &adjustment) < 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)
- {
- off -= (ssize_t)adjustment;
- memcpy (buf, buf + off, (size_t)(got - off) * sizeof (char));
- off = got - off;
- }
- else
- off = 0;
- }
-
- /* Close files and return successfully. */
- fflush (file);
- fclose (file);
- close (fbfd);
- return 0;
-
- fail:
- saved_errno = errno;
- if (file != NULL)
- fclose (file);
- if (fbfd >= 0)
- close (fbfd);
- errno = saved_errno;
- return -1;
-}
-
-
-/**
* Create an image of a framebuffer.
*
* @param fbname The framebuffer device.
@@ -180,92 +76,34 @@ save_pnm (const char *fbpath, long width, long height, int fd)
static int
save (const char *fbpath, const char *imgpath, long width, long height, int raw)
{
- int pipe_rw[2] = { -1, -1 };
- pid_t pid;
- int status;
- int fd = -1;
+ int imgfd = -1, fbfd;
int saved_errno;
- if (raw)
- goto no_convert;
-
-
- /* Create a pipe that for sending data into the conversion process program. */
- if (pipe (pipe_rw) < 0)
- goto fail;
-
- /* Fork the process, the child will become the conversion process. */
- pid = fork ();
- if (pid == -1)
- goto fail;
-
-
- /* Child process: */
- if (pid == 0)
- {
- /* Close the write-end of the pipe. */
- close (pipe_rw[1]);
-
- /* Open file descriptor for the output image. */
- fd = open (imgpath, O_WRONLY | O_CREAT | O_TRUNC,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
- if (fd == -1)
- goto child_fail;
-
- /* Convert the PNM-image we create to a compressed image, namely in PNG. */
- if (convert (pipe_rw[0], fd) < 0)
- goto child_fail;
-
- _exit(0);
- child_fail:
- perror(execname);
- _exit(1);
- }
-
-
- /* Parent process: */
-
- /* Close the read-end of the pipe. */
- close (pipe_rw[0]), pipe_rw[0] = -1;
-
- /* Create a PNM-image of the framebuffer. */
- if (save_pnm (fbpath, width, height, pipe_rw[1]) < 0)
- goto fail;
-
- /* Close the write-end of the pipe. */
- close (pipe_rw[1]), pipe_rw[1] = -1;
-
- /* Wait for conversion process to exit. */
- if (waitpid (pid, &status, 0) < 0)
- goto fail;
-
- /* Return successfully if and only if conversion did. */
- return status == 0 ? 0 : -1;
-
-
- /* Conversion shall not take place: */
-
- no_convert:
/* Open output file. */
- if (fd = open (imgpath, O_WRONLY | O_CREAT | O_TRUNC,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH), fd == -1)
+ imgfd = open (imgpath, O_WRONLY | O_CREAT | O_TRUNC,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ if (imgfd == -1)
FILE_FAILURE (imgpath);
+ /* Open the framebuffer device for reading. */
+ fbfd = open (fbpath, O_RDONLY);
+ if (fbfd == -1)
+ FILE_FAILURE (fbpath);
+
/* Save image. */
- if (save_pnm (fbpath, width, height, fd) < 0)
+ if ((raw ? save_pnm : save_png) (fbfd, width, height, imgfd) < 0)
goto fail;
- close (fd);
+ close (fbfd);
+ close (imgfd);
return 0;
fail:
saved_errno = errno;
- if (pipe_rw[0] >= 0)
- close (pipe_rw[0]);
- if (pipe_rw[1] >= 0)
- close (pipe_rw[1]);
- if (fd >= 0)
- close (fd);
+ if (fbfd >= 0)
+ close (fbfd);
+ if (imgfd >= 0)
+ close (imgfd);
errno = saved_errno;
return -1;
}