diff --git a/doc/katarakt.txt b/doc/katarakt.txt
index 90fd63fe9160f074eb20c67fcfa47830edef9abe..c3d1f1dc3d881d08f2f01edb731ce169244eef24 100644
--- a/doc/katarakt.txt
+++ b/doc/katarakt.txt
@@ -150,8 +150,8 @@ VARIABLES
 'string' *background_color_fullscreen* ::
 	0xFF000000: Fullscreen background color in ARGB Format.
 'string' *unrendered_page_color* ::
-	0x80808080: Color that gets drawn instead of a page that hasn't been
-	rendered yet.
+	0x40FFFFFF: Color that gets drawn instead of a page that hasn't been
+	rendered yet. If colors are inverted, this gets inverted as well.
 'int' *click_link_button* ::
 	1: The mouse button used for clicking links. Buttons 1-5 are supported.
 'int' *drag_view_button* ::
@@ -212,6 +212,12 @@ GotoLine {
 'int' *prefetch_count* ::
 	4: Number of pages exceeding the currently visible ones to render, back-
 	and forwards respectively.
+'float' *inverted_color_contrast* ::
+	0.5: the contrast when using inverted colors to avoid too much
+	brightness.
+'float' *inverted_color_brightening* ::
+	0.15: amount of brightening when using inverted colors to shift black to
+	gray.
 'int' *mouse_wheel_factor* ::
 	120: QT delta for turning the mouse wheel 1 click. Shouldn't need to be
 	touched.
diff --git a/share/katarakt.ini b/share/katarakt.ini
index 2c33eeb01a551ce6f8a71ea24b721e255207bd68..087e1fe55c73b40f1834048f1cdfecf123c97072 100644
--- a/share/katarakt.ini
+++ b/share/katarakt.ini
@@ -22,6 +22,8 @@ stylesheet=
 page_overlay_text=Page %1/%2
 icon_theme=
 prefetch_count=4
+inverted_color_contrast=0.5
+inverted_color_brightening=0.15
 mouse_wheel_factor=120
 thumbnail_filter=true
 thumbnail_size=32
diff --git a/src/config.cpp b/src/config.cpp
index 98d01b9ba8bd1c2e36877f701287fcc43a9ab5f9..eb348b8bd1eca6c538c5e8608ae3f8503e834397 100644
--- a/src/config.cpp
+++ b/src/config.cpp
@@ -45,6 +45,8 @@ void CFG::init_defaults() {
 	vd.push_back("Settings/icon_theme"); defaults[vd.back()] = "";
 	// internal
 	vd.push_back("Settings/prefetch_count"); defaults[vd.back()] = 4;
+	vd.push_back("Settings/inverted_color_contrast"); defaults[vd.back()] = 0.5;
+	vd.push_back("Settings/inverted_color_brightening"); defaults[vd.back()] = 0.15;
 	vd.push_back("Settings/mouse_wheel_factor"); defaults[vd.back()] = 120; // (qt-)delta for turning the mouse wheel 1 click
 	vd.push_back("Settings/thumbnail_filter"); defaults[vd.back()] = true; // filter when creating thumbnail image
 	vd.push_back("Settings/thumbnail_size"); defaults[vd.back()] = 32;
diff --git a/src/kpage.cpp b/src/kpage.cpp
index e1e39dfddb2b505eb63d37f1276e6e61e7afddcc..e3667a931372397e1ef65cfa01308b6cdb2bb364 100644
--- a/src/kpage.cpp
+++ b/src/kpage.cpp
@@ -44,11 +44,23 @@ const QImage *KPage::get_image(int index) const {
 }
 
 int KPage::get_width(int index) const {
-	return status[index];
+	// status might contain the information for img_other, but no inverted version is available yet
+	if (img[index].isNull()) {
+		return 0;
+	} else {
+		return status[index];
+	}
 }
 
 char KPage::get_rotation(int index) const {
-	return rotation[index];
+	// return rotation of next available image, try the right index first
+	for (int i = 3; i > 0; i--) {
+		if (!img[(index + i) % 3].isNull()) {
+			return rotation[(index + i) % 3];
+		}
+	}
+	// no image available? use thumbnail (always 0)
+	return 0;
 }
 
 const QList<SelectionLine *> *KPage::get_text() const {
@@ -59,4 +71,11 @@ const QList<SelectionLine *> *KPage::get_text() const {
 //	return label;
 //}
 
+void KPage::toggle_invert_colors() {
+	for (int i = 0; i < 3; i++) {
+		img[i].swap(img_other[i]);
+	}
+	thumbnail.swap(thumbnail_other);
+	inverted_colors = !inverted_colors;
+}
 
diff --git a/src/kpage.h b/src/kpage.h
index 63e07b45dd3c8e47036b961f485241360a46ff38..8bce4ba1bf2ba3578ce8fc2007c547d437b7eeba 100644
--- a/src/kpage.h
+++ b/src/kpage.h
@@ -22,10 +22,18 @@ public:
 //	QString get_label() const;
 
 private:
+	void toggle_invert_colors();
+
 	float width;
 	float height;
 	QImage img[3];
 	QImage thumbnail;
+	// for inverted colors with reduced contrast
+	// img_other contain the currently not needed color versions
+	// img store the current versions to be displayed
+	QImage img_other[3];
+	QImage thumbnail_other;
+
 //	QString label;
 	QList<Poppler::Link *> *links;
 	QMutex mutex;
diff --git a/src/resourcemanager.cpp b/src/resourcemanager.cpp
index bf4009a89463e9daa10b20dd7c9d7c4ce2d13b35..44fcf18d71746eae3750160acbee8f4303eeac29 100644
--- a/src/resourcemanager.cpp
+++ b/src/resourcemanager.cpp
@@ -9,7 +9,6 @@
 #endif
 #include "resourcemanager.h"
 #include "canvas.h"
-#include "config.h"
 #include "util.h"
 #include "kpage.h"
 #include "worker.h"
@@ -32,11 +31,6 @@ ResourceManager::ResourceManager(const QString &file, Viewer *v) :
 #endif
 		inverted_colors(false),
 		cur_jump_pos(jumplist.end()) {
-	// load config options
-	CFG *config = CFG::get_instance();
-	smooth_downscaling = config->get_value("Settings/thumbnail_filter").toBool();
-	thumbnail_size = config->get_value("Settings/thumbnail_size").toInt();
-
 	initialize(file, QByteArray());
 }
 
@@ -181,20 +175,20 @@ const KPage *ResourceManager::get_page(int page, int width, int index) {
 		return NULL;
 	}
 
-	// page not available or wrong size/rotation
+	// page not available or wrong size/rotation/color
 	k_page[page].mutex.lock();
+	bool must_invert_colors = k_page[page].inverted_colors != inverted_colors;
+	if (must_invert_colors) {
+		k_page[page].toggle_invert_colors();
+	}
+
 	if (k_page[page].img[index].isNull() ||
 			k_page[page].status[index] != width ||
-			k_page[page].rotation[index] != rotation) {
+			k_page[page].rotation[index] != rotation ||
+			must_invert_colors) {
 		enqueue(page, width, index);
 	}
-	if (inverted_colors != k_page[page].inverted_colors) {
-		k_page[page].inverted_colors = inverted_colors;
-		for (int i = 0; i < 3; i++) {
-			k_page[page].img[i].invertPixels();
-		}
-		k_page[page].thumbnail.invertPixels();
-	}
+
 	return &k_page[page];
 }
 
@@ -240,33 +234,9 @@ void ResourceManager::collect_garbage(int keep_min, int keep_max) {
 		cerr << "    removing page " << page << endl;
 #endif
 		k_page[page].mutex.lock();
-		// create thumbnail
-		if (k_page[page].thumbnail.isNull()) {
-			Qt::TransformationMode mode = Qt::FastTransformation;
-			if (smooth_downscaling) {
-				mode = Qt::SmoothTransformation;
-			}
-			// find the index of the rendered image
-			for (int i = 0; i < 3; i++) {
-				if (!k_page[page].img[i].isNull()) {
-//					k_page[page].inverted_colors = inverted_colors;
-					// scale
-					k_page[page].thumbnail = k_page[page].img[i].scaled(
-							QSize(thumbnail_size, thumbnail_size),
-							Qt::IgnoreAspectRatio, mode);
-					// rotate
-					if (k_page[page].rotation[i] != 0) {
-						QTransform trans;
-						trans.rotate(-k_page[page].rotation[i] * 90);
-						k_page[page].thumbnail = k_page[page].thumbnail.transformed(
-								trans);
-					}
-					break;
-				}
-			}
-		}
 		for (int i = 0; i < 3; i++) {
 			k_page[page].img[i] = QImage();
+			k_page[page].img_other[i] = QImage();
 			k_page[page].status[i] = 0;
 			k_page[page].rotation[i] = 0;
 		}
diff --git a/src/resourcemanager.h b/src/resourcemanager.h
index 0379f28ee51cbb41a37faec70daf053b2ab25347..985ad7c505cdbd01524b524ffea28227712551e8 100644
--- a/src/resourcemanager.h
+++ b/src/resourcemanager.h
@@ -107,9 +107,6 @@ private:
 	QSocketNotifier *i_notifier;
 #endif
 
-	// config options
-	bool smooth_downscaling;
-	int thumbnail_size;
 	bool inverted_colors;
 
 	std::list<int> jumplist;
diff --git a/src/util.cpp b/src/util.cpp
index f8e3d10227e00dd49440a26e27cff6728a29a6b2..d1dd49f3a9af1a627ec735e45cd19ab126aef011 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -1,9 +1,15 @@
 #include <QAction>
 #include <QObject>
+#include <QImage>
+//#include <QTime>
+//#include <iostream>
 #include "util.h"
 #include "config.h"
 
 
+using namespace std;
+
+
 const QRectF rotate_rect(const QRectF &rect, float w, float h, int rotation) {
 	if (rotation == 0) {
 		return rect;
@@ -53,3 +59,28 @@ void add_action(QWidget *base, const char *action, const char *slot, QWidget *re
 	}
 }
 
+void invert_image(QImage *img) {
+	static QRgb invert_mask = qRgba(255, 255, 255, 0);
+	static float inverted_contrast =
+			CFG::get_instance()->get_value("Settings/inverted_color_contrast").toFloat();
+	static int offset = 255 *
+			CFG::get_instance()->get_value("Settings/inverted_color_brightening").toFloat();
+//	QTime time;
+//	time.start();
+
+//	img->invertPixels();
+
+	QRgb *pixels = reinterpret_cast<QRgb *>(img->bits());
+	QRgb *pixels_end = pixels + img->width() * img->height();
+
+	while (pixels < pixels_end) {
+		*pixels ^= invert_mask;
+		*pixels = qRgb(
+				(qRed(*pixels)) * inverted_contrast + offset,
+				(qGreen(*pixels)) * inverted_contrast + offset,
+				(qBlue(*pixels)) * inverted_contrast + offset);
+		++pixels;
+	}
+//	cout << time.elapsed() << "ms elapsed" << endl;
+}
+
diff --git a/src/util.h b/src/util.h
index 4eebfcc4c9e37902997fe1f4fe95e225ae09e45b..b762549a0eadf73a1111793df01313221995d588 100644
--- a/src/util.h
+++ b/src/util.h
@@ -4,6 +4,10 @@
 #include <QRect>
 #include <QRectF>
 
+
+class QImage;
+
+
 #define POPPLER_VERSION ((POPPLER_VERSION_MAJOR << 16) | (POPPLER_VERSION_MINOR << 8) | (POPPLER_VERSION_MICRO))
 
 #define POPPLER_VERSION_CHECK(major,minor,micro) ((major << 16) | (minor << 8) | (micro))
@@ -21,5 +25,7 @@ QRect transform_rect_expand(const QRectF &rect, float scale, int off_x, int off_
 
 void add_action(QWidget *base, const char *action, const char *slot, QWidget *receiver);
 
+void invert_image(QImage *img);
+
 #endif
 
diff --git a/src/worker.cpp b/src/worker.cpp
index 897ea2f8100ea021bc2d9aa697e4d8a0084f3335..6abb7c2f9e0003dba8ae0726004c176e809ab99e 100644
--- a/src/worker.cpp
+++ b/src/worker.cpp
@@ -3,6 +3,8 @@
 #include "kpage.h"
 #include "canvas.h"
 #include "selection.h"
+#include "util.h"
+#include "config.h"
 #include <list>
 #include <iostream>
 #include <poppler/qt4/poppler-qt4.h>
@@ -13,6 +15,10 @@ using namespace std;
 Worker::Worker(ResourceManager *res) :
 		die(false),
 		res(res) {
+	// load config options
+	CFG *config = CFG::get_instance();
+	smooth_downscaling = config->get_value("Settings/thumbnail_filter").toBool();
+	thumbnail_size = config->get_value("Settings/thumbnail_size").toInt();
 }
 
 void Worker::run() {
@@ -57,58 +63,90 @@ void Worker::run() {
 		res->requestMutex.unlock();
 
 		// check for duplicate requests
-		res->k_page[page].mutex.lock();
-		if (res->k_page[page].status[index] == width &&
-				res->k_page[page].rotation[index] == res->rotation) {
-			res->k_page[page].mutex.unlock();
-			continue;
+		KPage &kp = res->k_page[page];
+
+		kp.mutex.lock();
+		bool render_new = true;
+		if (kp.status[index] == width && kp.rotation[index] == res->rotation) {
+			if (kp.img[index].isNull()) { // only invert colors
+				render_new = false;
+			} else { // nothing to do
+				kp.mutex.unlock();
+				continue;
+			}
 		}
 		int rotation = res->rotation;
-		res->k_page[page].mutex.unlock();
+		kp.mutex.unlock();
 
 		// open page
 #ifdef DEBUG
 		cerr << "    rendering page " << page << " for index " << index << endl;
 #endif
-		Poppler::Page *p = res->doc->page(page);
-		if (p == NULL) {
-			cerr << "failed to load page " << page << endl;
-			continue;
-		}
+		Poppler::Page *p = NULL;
+		if (render_new) {
+			p = res->doc->page(page);
+			if (p == NULL) {
+				cerr << "failed to load page " << page << endl;
+				continue;
+			}
 
-		// render page
-		float dpi = 72.0 * width / res->get_page_width(page);
-		QImage img = p->renderToImage(dpi, dpi, -1, -1, -1, -1,
-				static_cast<Poppler::Page::Rotation>(rotation));
+			// render page
+			float dpi = 72.0 * width / res->get_page_width(page);
+			QImage img = p->renderToImage(dpi, dpi, -1, -1, -1, -1,
+					static_cast<Poppler::Page::Rotation>(rotation));
 
-		if (img.isNull()) {
-			cerr << "failed to render page " << page << endl;
-			continue;
-		}
+			if (img.isNull()) {
+				cerr << "failed to render page " << page << endl;
+				continue;
+			}
 
-		// invert to current color setting
-		if (res->inverted_colors) {
-			img.invertPixels();
+			// insert new image
+			kp.mutex.lock();
+			if (kp.inverted_colors) {
+				kp.img[index] = QImage();
+				kp.img_other[index] = img;
+			} else {
+				kp.img[index] = img;
+				kp.img_other[index] = QImage();
+			}
+			kp.status[index] = width;
+			kp.rotation[index] = rotation;
+		} else {
+			// image already exists
+			kp.mutex.lock();
 		}
 
-		// put page
-		res->k_page[page].mutex.lock();
-		if (!res->k_page[page].img[index].isNull()) {
-			res->k_page[page].img[index] = QImage(); // assign null image
+		if (kp.inverted_colors) {
+			// generate inverted image
+			kp.img[index] = kp.img_other[index];
+			invert_image(&kp.img[index]);
 		}
 
-		// adjust all available images to current color setting
-		if (res->k_page[page].inverted_colors != res->inverted_colors) {
-			res->k_page[page].inverted_colors = res->inverted_colors;
-			for (int i = 0; i < 3; i++) {
-				res->k_page[page].img[i].invertPixels();
+		// create thumbnail
+		if (kp.thumbnail.isNull()) {
+			Qt::TransformationMode mode = Qt::FastTransformation;
+			if (smooth_downscaling) {
+				mode = Qt::SmoothTransformation;
+			}
+			// scale
+			if (kp.inverted_colors) {
+				kp.thumbnail = kp.img_other[index].scaled(QSize(thumbnail_size, thumbnail_size), Qt::IgnoreAspectRatio, mode);
+			} else {
+				kp.thumbnail = kp.img[index].scaled(QSize(thumbnail_size, thumbnail_size), Qt::IgnoreAspectRatio, mode);
+			}
+			// rotate
+			if (kp.rotation[index] != 0) {
+				QTransform trans;
+				trans.rotate(-kp.rotation[index] * 90);
+				kp.thumbnail = kp.thumbnail.transformed(trans);
+			}
+			kp.thumbnail_other = kp.thumbnail;
+			invert_image(&kp.thumbnail_other);
+			if (kp.inverted_colors) {
+				kp.thumbnail.swap(kp.thumbnail_other);
 			}
-			res->k_page[page].thumbnail.invertPixels();
 		}
-		res->k_page[page].img[index] = img;
-		res->k_page[page].status[index] = width;
-		res->k_page[page].rotation[index] = rotation;
-		res->k_page[page].mutex.unlock();
+		kp.mutex.unlock();
 
 		res->garbageMutex.lock();
 		res->garbage.insert(page); // TODO add index information?
@@ -118,7 +156,7 @@ void Worker::run() {
 
 		// collect goto links
 		res->link_mutex.lock();
-		if (res->k_page[page].links == NULL) {
+		if (kp.links == NULL) {
 			res->link_mutex.unlock();
 
 			QList<Poppler::Link *> *links = new QList<Poppler::Link *>;
@@ -126,9 +164,9 @@ void Worker::run() {
 			links->swap(l);
 
 			res->link_mutex.lock();
-			res->k_page[page].links = links;
+			kp.links = links;
 		}
-		if (res->k_page[page].text == NULL) {
+		if (kp.text == NULL) {
 			res->link_mutex.unlock();
 
 			QList<Poppler::TextBox *> text = p->textList();
@@ -190,7 +228,7 @@ void Worker::run() {
 			}
 
 			res->link_mutex.lock();
-			res->k_page[page].text = lines;
+			kp.text = lines;
 		}
 		res->link_mutex.unlock();
 
@@ -198,4 +236,3 @@ void Worker::run() {
 	}
 }
 
-
diff --git a/src/worker.h b/src/worker.h
index 36d8cac6c7b13bdf46272e325190c2a13e0b46aa..ef51db05ac583126e6fdea334514f0b1a9dab1ad 100644
--- a/src/worker.h
+++ b/src/worker.h
@@ -22,6 +22,10 @@ signals:
 
 private:
 	ResourceManager *res;
+
+	// config options
+	bool smooth_downscaling;
+	int thumbnail_size;
 };
 
 #endif