summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@operamail.com>2015-04-04 22:20:19 +0200
committerMattias Andrée <maandree@operamail.com>2015-04-04 22:20:19 +0200
commit9ce5fd33f66224dfd1a96334a531ae984e8622b5 (patch)
tree455cd18d36d691307071bf8f4411e5336cb71ea3
parentlog what is happening (diff)
downloadblueshift-demomode-9ce5fd33f66224dfd1a96334a531ae984e8622b5.tar.gz
blueshift-demomode-9ce5fd33f66224dfd1a96334a531ae984e8622b5.tar.bz2
blueshift-demomode-9ce5fd33f66224dfd1a96334a531ae984e8622b5.tar.xz
draft of image filtering
Signed-off-by: Mattias Andrée <maandree@operamail.com>
-rw-r--r--COPYING2
-rw-r--r--TODO2
-rw-r--r--src/blueshift-demomode-image.c346
-rwxr-xr-xsrc/blueshift-demomode-image.py117
-rw-r--r--src/blueshift_demomode.py33
5 files changed, 483 insertions, 17 deletions
diff --git a/COPYING b/COPYING
index 119c37f..4f9fca8 100644
--- a/COPYING
+++ b/COPYING
@@ -1,5 +1,5 @@
blueshift-demomode — Blueshift-effect demonstration tools
-Copyright Ⓒ 2014 Mattias Andrée (maandree@member.fsf.org)
+Copyright Ⓒ 2014, 2015 Mattias Andrée (maandree@member.fsf.org)
This library is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..b680e22
--- /dev/null
+++ b/TODO
@@ -0,0 +1,2 @@
+add video support
+
diff --git a/src/blueshift-demomode-image.c b/src/blueshift-demomode-image.c
new file mode 100644
index 0000000..f2d55b9
--- /dev/null
+++ b/src/blueshift-demomode-image.c
@@ -0,0 +1,346 @@
+/**
+ * blueshift-demomode — Blueshift-effect demonstration tools
+ * Copyright Ⓒ 2014, 2015 Mattias Andrée (maandree@member.fsf.org)
+ *
+ * This library 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 library 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 library. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+
+
+/**
+ * Value for `tupletype` when the image is black and white
+ * The bytes are: whitenames (note that it is not blackness as with P1 and P4)
+ * (note that it is bytes and not bits as with P4)
+ */
+#define BLACKANDWHITE 0
+
+/**
+ * Value for `tupletype` when the image is grey
+ * The words are: whiteness
+ */
+#define GRAYSCALE 1
+
+/**
+ * Value for `tupletype` when the image is coloured
+ * The words are: redness, greenness, blueness
+ */
+#define RGB 2
+
+/**
+ * Value for `tupletype` when the image is black and white with an alpha channel
+ * The bytes are: blackness (note that it is not blackness as with P1 and P4), transparency
+ */
+#define BLACKANDWHITE_ALPHA 3
+
+/**
+ * Value for `tupletype` when the image is grey with an alpha channel
+ * The words are: whiteness, transparency
+ */
+#define GRAYSCALE_ALPHA 4
+
+/**
+ * Value for `tupletype` when the image is coloured with an alpha channel
+ * The words are: redness, greenness, blueness, transparency
+ */
+#define RGB_ALPHA 5
+
+
+
+/**
+ * The width of image, in pixels
+ */
+static size_t width = 0;
+static int have_width = 0;
+
+/**
+ * The height of the image, in pixels
+ */
+static size_t height = 0;
+static int have_height = 0;
+
+/**
+ * The number of channals, 1 for black and white or greyscale, 3 for colour, plus 1 for alpha
+ */
+static int depth = 0;
+static int have_depth = 0;
+
+/**
+ * The maximum value a channel can have, the white point threshold
+ */
+static uint32_t maxval = 0;
+static int have_maxval = 0;
+
+/**
+ * The channel configuration
+ */
+static int tupltype = 0;
+static int have_tupltype = 0;
+
+
+static size_t red_n, green_n, blue_n;
+static uint32_t* max = NULL;
+static uint32_t* red = NULL;
+static uint32_t* green = NULL;
+static uint32_t* blue = NULL;
+
+static char* execname;
+
+
+
+static void strip(char* buffer)
+{
+ size_t offset = 0;
+ size_t end = strlen(buffer);
+ while (buffer[offset] && ((buffer[offset] == ' ') || (buffer[offset] == '\t')))
+ offset++;
+ while (end && ((buffer[end - 1] == ' ') || (buffer[end - 1] == '\t')))
+ end--;
+ buffer[end] = '\0';
+ memmove(buffer, buffer + offset, end + 1 - offset);
+}
+
+
+static long long conv(char* buffer)
+{
+ strip(buffer);
+ return atoll(buffer);
+}
+
+
+static uint32_t* int_split(char* buffer, size_t* out_n)
+{
+ size_t n = 1;
+ char* buf = buffer;
+ uint32_t* rc = NULL;
+ uint32_t v = 0;
+
+ while (*buf)
+ if (*buf++ == ' ')
+ n++;
+
+ if (out_n)
+ *out_n = n;
+ rc = malloc(n * sizeof(uint32_t));
+ if (rc == NULL)
+ return NULL;
+
+ for (n = 0; *buf; buf++)
+ if (*buf == ' ')
+ rc[n++] = v, v = 0;
+ else
+ v = (v * 10) + (*buf & 15);
+ rc[n] = v;
+
+ return rc;
+}
+
+
+static inline void conv1(unsigned char* in, unsigned char* out, uint32_t* lut, size_t lutsize, uint32_t lutmax)
+{
+ size_t n = ((uint32_t)*in * lutsize + maxval / 2) / maxval;
+ if (n > lutsize)
+ n = lutsize;
+ *out = (unsigned char)(lut[n] * maxval / lutmax);
+}
+
+
+static inline void conv2(unsigned char* in, unsigned char* out, uint32_t* lut, size_t lutsize, uint32_t lutmax)
+{
+ size_t n = (((uint32_t)(in[0])) << 8) | ((uint32_t)(in[1]));
+ n = (n * lutsize + maxval / 2) / maxval;
+ if (n > lutsize)
+ n = lutsize;
+ n = lut[n] * maxval / lutmax;
+ out[0] = (n >> 8) & 255;
+ out[1] = (n >> 0) & 255;
+}
+
+
+#define FILTER(FOR, SIZE, RGB, WPTR) \
+ for FOR \
+ { \
+ conv##SIZE(data + ptr + RGB * SIZE * 0, data + WPTR + SIZE * 0, red, red_n, max[0]); \
+ conv##SIZE(data + ptr + RGB * SIZE * 1, data + WPTR + SIZE * 1, green, green_n, max[1]); \
+ conv##SIZE(data + ptr + RGB * SIZE * 2, data + WPTR + SIZE * 2, blue, blue_n, max[2]); \
+ }
+
+
+static int filter(size_t size, int rgb, int alpha, int dual)
+{
+ char* data = malloc(size * (rgb ? 1 : 3));
+ size_t ptr = 0;
+ ssize_t got;
+ if (data == NULL)
+ goto fail;
+
+ while (size)
+ {
+ got = read(0, data + ptr, size);
+ if (got < 0)
+ goto fail;
+ ptr += (size_t)got;
+ size -= (size_t)got;
+ }
+
+ size = ptr;
+
+ if (rgb && alpha && dual) FILTER((ptr = 0; ptr < size; ptr += 8), 2, 1, ptr)
+ else if (rgb && alpha) FILTER((ptr = 0; ptr < size; ptr += 4), 1, 1, ptr)
+ else if (rgb && dual) FILTER((ptr = 0; ptr < size; ptr += 6), 2, 1, ptr)
+ else if (rgb) FILTER((ptr = 0; ptr < size; ptr += 3), 1, 1, ptr)
+ else if (alpha && dual) FILTER((; ptr; ptr -= 4, size -= 8), 2, 0, size - 8)
+ else if (alpha) FILTER((; ptr; ptr -= 2, size -= 4), 1, 0, size - 4)
+ else if (dual) FILTER((; ptr; ptr -= 2, size -= 6), 2, 0, size - 6)
+ else FILTER((; ptr; ptr -= 1, size -= 3), 1, 0, size - 3)
+
+ return 0;
+ fail:
+ perror(execname);
+ free(data);
+ return -1;
+}
+
+
+int main(int argc, char** argv)
+{
+ int ok = 0;
+ int stage = 0;
+ char buf[1024];
+ size_t ptr = 0, size;
+ int alpha;
+
+ execname = *argv;
+
+
+ for (;;)
+ {
+ int c = getchar();
+ if (c < 0)
+ goto bad;
+ if (c == '\n')
+ {
+ buf[ptr] = '\0';
+ ptr = 0;
+ strip(buf);
+ if (!strcmp(buf, "P7"))
+ {
+ if (stage++)
+ break;
+ }
+ else if (!strcmp(buf, "ENDHDR"))
+ {
+ ok = 1;
+ break;
+ }
+ else if (strstr(buf, "WIDTH") == buf)
+ {
+ if (have_width) break;
+ have_width = 1, width = (size_t)conv(buf + 5);
+ }
+ else if (strstr(buf, "HEIGHT") == buf)
+ {
+ if (have_height) break;
+ have_height = 1, height = (size_t)conv(buf + 6);
+ }
+ else if (strstr(buf, "DEPTH") == buf)
+ {
+ if (have_depth) break;
+ have_depth = 1, depth = (int)conv(buf + 5);
+ }
+ else if (strstr(buf, "MAXVAL") == buf)
+ {
+ if (have_maxval) break;
+ have_maxval = 1, maxval = (uint32_t)conv(buf + 6);
+ }
+ else if (strstr(buf, "TUPLTYPE") == buf)
+ {
+ if (have_tupltype) break;
+ strip(buf + 8);
+ have_tupltype = 1;
+ if (!strcmp(buf + 8, "BLACKANDWHITE")) tupltype = BLACKANDWHITE;
+ else if (!strcmp(buf + 8, "GRAYSCALE")) tupltype = GRAYSCALE;
+ else if (!strcmp(buf + 8, "RGB")) tupltype = RGB;
+ else if (!strcmp(buf + 8, "BLACKANDWHITE_ALPHA")) tupltype = BLACKANDWHITE_ALPHA;
+ else if (!strcmp(buf + 8, "GRAYSCALE_ALPHA")) tupltype = GRAYSCALE_ALPHA;
+ else if (!strcmp(buf + 8, "RGB_ALPHA")) tupltype = RGB_ALPHA;
+ else
+ goto bad;
+ }
+ }
+ else
+ if (ptr + 1 == sizeof(buf) / sizeof(*buf))
+ goto bad;
+ else
+ buf[ptr++] = (char)c;
+ }
+
+ if (!ok || !width || !height || !depth || !maxval || !tupltype)
+ ok = 0;
+ else if ((width < 1) || (height < 0)) ok = 0;
+ else if (tupltype == BLACKANDWHITE) ok = (depth == 1) && (1 <= maxval) && (maxval <= 1);
+ else if (tupltype == GRAYSCALE) ok = (depth == 1) && (1 <= maxval) && (maxval <= 65535);
+ else if (tupltype == RGB) ok = (depth == 3) && (1 <= maxval) && (maxval <= 65535);
+ else if (tupltype == BLACKANDWHITE_ALPHA) ok = (depth == 2) && (1 <= maxval) && (maxval <= 1);
+ else if (tupltype == GRAYSCALE_ALPHA) ok = (depth == 2) && (1 <= maxval) && (maxval <= 65535);
+ else if (tupltype == RGB_ALPHA) ok = (depth == 4) && (1 <= maxval) && (maxval <= 65535);
+ if (!ok)
+ goto bad;
+
+ if ((max = int_split(argv[1], NULL)) == NULL) goto fail;
+ if ((red = int_split(argv[2], &red_n)) == NULL) goto fail;
+ if ((green = int_split(argv[3], &green_n)) == NULL) goto fail;
+ if ((blue = int_split(argv[4], &blue_n)) == NULL) goto fail;
+ alpha = tupltype >= BLACKANDWHITE_ALPHA;
+
+
+ printf("P7\n");
+ printf("WIDTH %zu\n", width);
+ printf("HEIGHT %zu\n", height);
+ printf("DEPTH %i\n", alpha ? 4 : 3);
+ printf("MAXVAL %zu\n", (size_t)maxval);
+ printf("TUPLTYPE %s\n", alpha ? "RGB_ALPHA" : "RGB");
+ printf("ENDHDR\n");
+
+
+ red_n--;
+ green_n--;
+ blue_n--;
+ size = width * height * depth * (maxval > 255 ? 2 : 1);
+ if (filter(size, tupltype == (alpha ? RGB_ALPHA : RGB), alpha, maxval > 255))
+ goto fail;
+
+
+ free(max);
+ free(red);
+ free(green);
+ free(blue);
+ return 0;
+ bad:
+ fprintf(stderr, "%s: %s\n", execname, "Failed to load image");
+ return 1;
+ fail:
+ perror(execname);
+ free(max);
+ free(red);
+ free(green);
+ free(blue);
+ return 1;
+}
+
diff --git a/src/blueshift-demomode-image.py b/src/blueshift-demomode-image.py
new file mode 100755
index 0000000..cbc7fe5
--- /dev/null
+++ b/src/blueshift-demomode-image.py
@@ -0,0 +1,117 @@
+#!/usr/bin/env python3
+copyright='''
+blueshift-demomode — Blueshift-effect demonstration tools
+Copyright Ⓒ 2014, 2015 Mattias Andrée (maandree@member.fsf.org)
+
+This library 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 library 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 library. If not, see <http://www.gnu.org/licenses/>.
+'''
+
+
+import os, sys
+
+from argparser import *
+
+
+PROGRAM_NAME = 'blueshift-demomode'
+PROGRAM_VERSION = '1'
+IMAGE_COMMAND = 'bin/blueshift-demomode-image'
+
+
+parser = ArgParser('Blueshift-effect demonstration tools',
+ sys.argv[0] + ' (options | [--] images-file)',
+ None, None, True, ArgParser.standard_abbreviations())
+
+parser.add_argumentless(['-h', '-?', '--help'], 0, 'Print this help information')
+parser.add_argumentless(['-C', '--copying', '--copyright'], 0, 'Print copyright information')
+parser.add_argumentless(['-W', '--warranty'], 0, 'Print non-warranty information')
+parser.add_argumentless(['-v', '--version'], 0, 'Print program name and version')
+
+parser.parse()
+parser.support_alternatives()
+
+if parser.opts['--help'] is not None:
+ parser.help()
+ sys.exit(0)
+elif parser.opts['--copyright'] is not None:
+ print(copyright[1 : -1])
+ sys.exit(0)
+elif parser.opts['--warranty'] is not None:
+ print(copyright.split('\n\n')[2])
+ sys.exit(0)
+elif parser.opts['--version'] is not None:
+ print('%s %s' % (PROGRAM_NAME, PROGRAM_VERSION))
+ sys.exit(0)
+
+
+if not len(parser.files) == 1:
+ print('%s: you must select exactly one image file' % sys.argv[0], file = sys.stderr);
+
+
+monitor = None
+data = sys.stdin.buffer.read().decode('utf-8', 'strict').split('\n')
+
+if monitor is not None:
+ buf = []
+ stage = 0
+ for d in data:
+ if stage == 0:
+ if d.startswith('monitors: '):
+ d = data[len('monitors: '):].split(' ')
+ if monitor in d:
+ stage = 1
+ elif stage == 1:
+ if d.startswith('monitors: '):
+ break
+ buf.append(d)
+ data = buf
+
+data_max = [d[len('max: ' ):] for d in data if d.startswith('max: ' )]
+data_red = [d[len('red: ' ):] for d in data if d.startswith('red: ' )]
+data_green = [d[len('green: '):] for d in data if d.startswith('green: ')]
+data_blue = [d[len('blue: ' ):] for d in data if d.startswith('blue: ' )]
+
+if any(map(lambda x : len(x) == 0, [data_max, data_red, data_green, data_blue])):
+ print('%s: could not find any gamma ramp data' % sys.argv[0], file = sys.stderr);
+ sys.exit(1)
+
+data_max = data_max[0]
+data_red = data_red[0]
+data_green = data_green[0]
+data_blue = data_blue[0]
+
+
+command = [IMAGE_COMMAND, data_max, data_red, data_green, data_blue]
+
+
+os.close(0)
+(read_end, write_end) = os.pipe()
+pid = os.fork()
+
+if pid == 0:
+ os.close(read_end)
+ if not write_end == 1:
+ os.dup2(write_end, 1)
+ os.close(write_end)
+ fd = os.open(parser.files[0], os.O_RDONLY)
+ if not fd == 0:
+ os.dup2(fd, 0)
+ os.close(fd)
+ os.execvp('convert', ['convert', '-', 'pam:-'])
+else:
+ os.close(write_end)
+ if not read_end == 0:
+ os.dup2(read_end, 0)
+ os.close(read_end)
+ os.execvp(command[0], command)
+
diff --git a/src/blueshift_demomode.py b/src/blueshift_demomode.py
index 3817e34..75dc507 100644
--- a/src/blueshift_demomode.py
+++ b/src/blueshift_demomode.py
@@ -1,20 +1,21 @@
# -*- python -*-
-
-# blueshift-demomode — Blueshift-effect demonstration tools
-# Copyright Ⓒ 2014 Mattias Andrée (maandree@member.fsf.org)
-#
-# This library 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 library 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 library. If not, see <http://www.gnu.org/licenses/>.
+'''
+blueshift-demomode — Blueshift-effect demonstration tools
+Copyright Ⓒ 2014, 2015 Mattias Andrée (maandree@member.fsf.org)
+
+This library 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 library 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 library. If not, see <http://www.gnu.org/licenses/>.
+'''
import time