$ git clone http://tcclient.ion.nu/tc_client.git
commit 44c65fe55770e7e7dcb935ce1e6a847ff4276396
Author: Alicia <...>
Date:   Wed Sep 21 22:46:10 2016 +0200

    tc_client-gtk: moved the postprocessing code into its own source file.

diff --git a/ChangeLog b/ChangeLog
index e01e13d..e124c21 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,6 @@
 0.40:
 tc_client-gtk: merged camera_remove() and camera_removebynick() into a single function, merged the deallocation of camera data into camera_free()
+tc_client-gtk: moved the postprocessing code into its own source file.
 0.39:
 Added a /closecam command to stop receiving a cam stream.
 Use uintX_t for endianness functions instead of unsigned long*x int.
diff --git a/Makefile b/Makefile
index 8e38889..8e7055b 100644
--- a/Makefile
+++ b/Makefile
@@ -16,7 +16,7 @@ IRCHACK_OBJ=utilities/irchack/irchack.o utilities/compat.o
 MODBOT_OBJ=utilities/modbot/modbot.o utilities/list.o utilities/modbot/queue.o
 CAMVIEWER_OBJ=utilities/camviewer/camviewer.o utilities/compat.o libcamera.a
 CURSEDCHAT_OBJ=utilities/cursedchat/cursedchat.o utilities/cursedchat/buffer.o utilities/compat.o utilities/list.o
-TC_CLIENT_GTK_OBJ=utilities/gtk/camviewer.o utilities/gtk/userlist.o utilities/gtk/media.o utilities/gtk/compat.o utilities/gtk/config.o utilities/gtk/gui.o utilities/stringutils.o utilities/gtk/logging.o utilities/compat.o utilities/gtk/inputhistory.o libcamera.a
+TC_CLIENT_GTK_OBJ=utilities/gtk/camviewer.o utilities/gtk/userlist.o utilities/gtk/media.o utilities/gtk/compat.o utilities/gtk/config.o utilities/gtk/gui.o utilities/stringutils.o utilities/gtk/logging.o utilities/gtk/postproc.o utilities/compat.o utilities/gtk/inputhistory.o libcamera.a
 LIBCAMERA_OBJ=utilities/libcamera/camera.o utilities/libcamera/camera_img.o
 UTILS=irchack modbot
 CONFINFO=|Will enable the IRC utility irchack|Will enable the bot utility modbot
@@ -148,7 +148,7 @@ SOURCES+=utilities/irchack/irchack.c
 SOURCES+=utilities/modbot/modbot.c utilities/modbot/queue.c utilities/modbot/queue.h utilities/modbot/commands.html
 SOURCES+=utilities/camviewer/camviewer.c
 SOURCES+=utilities/cursedchat/cursedchat.c utilities/cursedchat/buffer.c utilities/cursedchat/buffer.h
-SOURCES+=utilities/gtk/camviewer.c utilities/gtk/userlist.c utilities/gtk/media.c utilities/gtk/compat.c utilities/gtk/config.c utilities/gtk/gui.c utilities/gtk/logging.c utilities/gtk/inputhistory.c utilities/gtk/userlist.h utilities/gtk/media.h utilities/gtk/compat.h utilities/gtk/config.h utilities/gtk/gui.h utilities/gtk/logging.h utilities/gtk/inputhistory.h gtkgui.glade
+SOURCES+=utilities/gtk/camviewer.c utilities/gtk/userlist.c utilities/gtk/media.c utilities/gtk/compat.c utilities/gtk/config.c utilities/gtk/gui.c utilities/gtk/logging.c utilities/gtk/postproc.c utilities/gtk/inputhistory.c utilities/gtk/userlist.h utilities/gtk/media.h utilities/gtk/compat.h utilities/gtk/config.h utilities/gtk/gui.h utilities/gtk/logging.h utilities/gtk/postproc.h utilities/gtk/inputhistory.h gtkgui.glade
 SOURCES+=utilities/gtk/gencamplaceholder.sh utilities/gtk/camplaceholder.xcf utilities/gtk/spinnerdot.xcf
 SOURCES+=utilities/compat.c utilities/compat.h utilities/list.c utilities/list.h utilities/stringutils.c utilities/stringutils.h
 SOURCES+=utilities/libcamera/camera.c utilities/libcamera/camera.h utilities/libcamera/camera_v4l2.c utilities/libcamera/camera_v4l2.h utilities/libcamera/camera_img.c utilities/libcamera/camera_img.h utilities/libcamera/camera_escapi.cpp utilities/libcamera/camera_escapi.h
diff --git a/utilities/gtk/camviewer.c b/utilities/gtk/camviewer.c
index 58167bc..16068cd 100644
--- a/utilities/gtk/camviewer.c
+++ b/utilities/gtk/camviewer.c
@@ -217,7 +217,7 @@ gboolean handledata(GIOChannel* iochannel, GIOCondition condition, gpointer data
     struct SwsContext* swsctx=sws_getContext(cam->frame->width, cam->frame->height, cam->frame->format, camsize_scale.width, camsize_scale.height, AV_PIX_FMT_RGB24, SWS_BICUBIC, 0, 0, 0);
     sws_scale(swsctx, (const uint8_t*const*)cam->frame->data, cam->frame->linesize, 0, cam->frame->height, cam->dstframe->data, cam->dstframe->linesize);
     sws_freeContext(swsctx);
-    camera_postproc(cam, cam->dstframe->data[0], camsize_scale.width, camsize_scale.height);
+    postprocess(&cam->postproc, cam->dstframe->data[0], camsize_scale.width, camsize_scale.height);
 
     GdkPixbuf* oldpixbuf=gtk_image_get_pixbuf(GTK_IMAGE(cam->cam));
     GdkPixbuf* gdkframe=gdk_pixbuf_new_from_data(cam->dstframe->data[0], GDK_COLORSPACE_RGB, 0, 8, camsize_scale.width, camsize_scale.height, cam->dstframe->linesize[0], freebuffer, 0);
diff --git a/utilities/gtk/media.c b/utilities/gtk/media.c
index 6ba2304..d0b409f 100644
--- a/utilities/gtk/media.c
+++ b/utilities/gtk/media.c
@@ -98,8 +98,7 @@ void camera_free(struct camera* cam)
   free(cam->id);
   free(cam->nick);
 
-  if(cam->postproc.greenscreen){img_free(cam->postproc.greenscreen);}
-  free((void*)cam->postproc.greenscreen_filename);
+  postproc_free(&cam->postproc);
 }
 
 void camera_remove(const char* id, char isnick)
@@ -164,11 +163,7 @@ struct camera* camera_new(const char* nick, const char* id)
   gtk_box_pack_start(GTK_BOX(cam->box), cam->label, 0, 0, 0);
   g_signal_connect(eventbox, "button-release-event", G_CALLBACK(gui_show_cam_menu), cam->id);
   // Initialize postprocessing values
-  cam->postproc.min_brightness=0;
-  cam->postproc.max_brightness=255;
-  cam->postproc.autoadjust=0;
-  cam->postproc.flip_horizontal=0;
-  cam->postproc.flip_vertical=0;
+  postproc_init(&cam->postproc);
   return cam;
 }
 
@@ -213,7 +208,7 @@ gboolean cam_encode(GIOChannel* iochannel, GIOCondition condition, gpointer data
     av_image_alloc(cam->frame->data, cam->frame->linesize, camsize_out.width, camsize_out.height, cam->frame->format, 1);
   }
   g_io_channel_read_chars(iochannel, (void*)cam->frame->data[0], camsize_out.width*camsize_out.height*3, 0, 0);
-  camera_postproc(cam, cam->frame->data[0], cam->frame->width, cam->frame->height);
+  postprocess(&cam->postproc, cam->frame->data[0], cam->frame->width, cam->frame->height);
   // Update our local display
   GdkPixbuf* oldpixbuf=gtk_image_get_pixbuf(GTK_IMAGE(cam->cam));
   GdkPixbuf* gdkframe=gdk_pixbuf_new_from_data(cam->frame->data[0], GDK_COLORSPACE_RGB, 0, 8, cam->frame->width, cam->frame->height, cam->frame->linesize[0], 0, 0);
@@ -387,60 +382,6 @@ const char* camselect_file(void)
   return file;
 }
 
-void camera_postproc(struct camera* cam, unsigned char* buf, unsigned int width, unsigned int height)
-{
-  if(cam->postproc.min_brightness!=0 || cam->postproc.max_brightness!=255 || cam->postproc.autoadjust)
-  {
-    unsigned char min=255;
-    unsigned char max=0;
-    unsigned int count=width*height;
-    unsigned int i;
-    for(i=0; i<count*3; ++i)
-    {
-      if(cam->postproc.autoadjust)
-      {
-        if(buf[i]<min){min=buf[i];}
-        if(buf[i]>max){max=buf[i];}
-      }
-      double v=((double)buf[i]-cam->postproc.min_brightness)*255/(cam->postproc.max_brightness-cam->postproc.min_brightness);
-      if(v<0){v=0;}
-      if(v>255){v=255;}
-      buf[i]=v;
-    }
-    if(cam->postproc.autoadjust)
-    {
-      cam->postproc.min_brightness=min;
-      cam->postproc.max_brightness=max;
-    }
-  }
-  if(cam->postproc.flip_horizontal)
-  {
-    unsigned int x;
-    unsigned int y;
-    for(y=0; y<height; ++y)
-    for(x=0; x<width/2; ++x)
-    {
-      unsigned char pixel[3];
-      memcpy(pixel, &buf[(y*width+x)*3], 3);
-      memcpy(&buf[(y*width+x)*3], &buf[(y*width+(width-x-1))*3], 3);
-      memcpy(&buf[(y*width+(width-x-1))*3], pixel, 3);
-    }
-  }
-  if(cam->postproc.flip_vertical)
-  {
-    unsigned int x;
-    unsigned int y;
-    for(y=0; y<height/2; ++y)
-    for(x=0; x<width; ++x)
-    {
-      unsigned char pixel[3];
-      memcpy(pixel, &buf[(y*width+x)*3], 3);
-      memcpy(&buf[(y*width+x)*3], &buf[((height-y-1)*width+x)*3], 3);
-      memcpy(&buf[((height-y-1)*width+x)*3], pixel, 3);
-    }
-  }
-}
-
 void updatescaling(unsigned int width, unsigned int height, char changedcams)
 {
   if(!camcount){return;}
diff --git a/utilities/gtk/media.h b/utilities/gtk/media.h
index 15ad786..58197bc 100644
--- a/utilities/gtk/media.h
+++ b/utilities/gtk/media.h
@@ -15,6 +15,7 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 #include <libavcodec/avcodec.h>
+#include "postproc.h"
 struct camera
 {
   AVFrame* frame;
@@ -28,14 +29,7 @@ struct camera
   char* nick;
   GtkWidget* box; // holds label and cam
   GtkWidget* label;
-  struct
-  {
-    double min_brightness;
-    double max_brightness;
-    char autoadjust;
-    char flip_horizontal;
-    char flip_vertical;
-  } postproc;
+  struct postproc_ctx postproc;
   unsigned int placeholder;
 };
 struct size
diff --git a/utilities/gtk/postproc.c b/utilities/gtk/postproc.c
new file mode 100644
index 0000000..c18c996
--- /dev/null
+++ b/utilities/gtk/postproc.c
@@ -0,0 +1,87 @@
+/*
+    tc_client-gtk, a graphical user interface for tc_client
+    Copyright (C) 2016  alicia@ion.nu
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Affero General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    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 Affero General Public License for more details.
+
+    You should have received a copy of the GNU Affero General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <string.h>
+#include <stdlib.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include "postproc.h"
+
+void postproc_init(struct postproc_ctx* pp)
+{
+  pp->min_brightness=0;
+  pp->max_brightness=255;
+  pp->autoadjust=0;
+  pp->flip_horizontal=0;
+  pp->flip_vertical=0;
+}
+
+void postprocess(struct postproc_ctx* pp, unsigned char* buf, unsigned int width, unsigned int height)
+{
+  if(pp->min_brightness!=0 || pp->max_brightness!=255 || pp->autoadjust)
+  {
+    unsigned char min=255;
+    unsigned char max=0;
+    unsigned int count=width*height;
+    unsigned int i;
+    for(i=0; i<count*3; ++i)
+    {
+      if(pp->autoadjust)
+      {
+        if(buf[i]<min){min=buf[i];}
+        if(buf[i]>max){max=buf[i];}
+      }
+      double v=((double)buf[i]-pp->min_brightness)*255/(pp->max_brightness-pp->min_brightness);
+      if(v<0){v=0;}
+      if(v>255){v=255;}
+      buf[i]=v;
+    }
+    if(pp->autoadjust)
+    {
+      pp->min_brightness=min;
+      pp->max_brightness=max;
+    }
+  }
+  if(pp->flip_horizontal)
+  {
+    unsigned int x;
+    unsigned int y;
+    for(y=0; y<height; ++y)
+    for(x=0; x<width/2; ++x)
+    {
+      unsigned char pixel[3];
+      memcpy(pixel, &buf[(y*width+x)*3], 3);
+      memcpy(&buf[(y*width+x)*3], &buf[(y*width+(width-x-1))*3], 3);
+      memcpy(&buf[(y*width+(width-x-1))*3], pixel, 3);
+    }
+  }
+  if(pp->flip_vertical)
+  {
+    unsigned int x;
+    unsigned int y;
+    for(y=0; y<height/2; ++y)
+    for(x=0; x<width; ++x)
+    {
+      unsigned char pixel[3];
+      memcpy(pixel, &buf[(y*width+x)*3], 3);
+      memcpy(&buf[(y*width+x)*3], &buf[((height-y-1)*width+x)*3], 3);
+      memcpy(&buf[((height-y-1)*width+x)*3], pixel, 3);
+    }
+  }
+}
+
+void postproc_free(struct postproc_ctx* pp)
+{
+}
diff --git a/utilities/gtk/postproc.h b/utilities/gtk/postproc.h
new file mode 100644
index 0000000..9dcfff0
--- /dev/null
+++ b/utilities/gtk/postproc.h
@@ -0,0 +1,28 @@
+/*
+    tc_client-gtk, a graphical user interface for tc_client
+    Copyright (C) 2016  alicia@ion.nu
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Affero General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    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 Affero General Public License for more details.
+
+    You should have received a copy of the GNU Affero General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+struct postproc_ctx
+{
+  double min_brightness;
+  double max_brightness;
+  char autoadjust;
+  char flip_horizontal;
+  char flip_vertical;
+};
+
+extern void postproc_init(struct postproc_ctx* pp);
+extern void postprocess(struct postproc_ctx* pp, unsigned char* buf, unsigned int width, unsigned int height);
+extern void postproc_free(struct postproc_ctx* pp);