Permalink
Browse files

Parallelized remapping and Voronoi iteration

  • Loading branch information...
kornelski committed Jan 22, 2012
1 parent c23687f commit 3c2d720f08fcaae61e49c6cfba2da91852067433
Showing with 41 additions and 16 deletions.
  1. +5 −2 Makefile
  2. +16 −6 pngquant.c
  3. +19 −7 viter.c
  4. +1 −1 viter.h
View
@@ -13,15 +13,18 @@ CUSTOMZLIB ?= ../zlib
CFLAGSOPT ?= -O3 -fearly-inlining -fstrict-aliasing -ffast-math -funroll-loops -fomit-frame-pointer -fexpensive-optimizations -ffinite-math-only -funsafe-loop-optimizations -ftree-vectorize
CFLAGS ?= -DNDEBUG -Wall -I. -I$(CUSTOMLIBPNG) -I$(CUSTOMZLIB) -I/usr/local/include/ -I/usr/include/ -I/usr/X11/include/ $(CFLAGSOPT)
CFLAGS += -std=c99
CFLAGS += -std=c99 $(CFLAGSADD)
LDFLAGS ?= -L$(CUSTOMLIBPNG) -L$(CUSTOMZLIB) -L/usr/local/lib/ -L/usr/lib/ -L/usr/X11/lib/
LDFLAGS += -lz -lpng -lm
LDFLAGS += -lz -lpng -lm $(LDFLAGSADD)
OBJS = pngquant.o rwpng.o pam.o mediancut.o blur.o mempool.o viter.o nearest.o
all: $(BIN)
openmp::
CFLAGSADD=-fopenmp LDFLAGSADD=-lgomp $(MAKE) -j 8 $(MAKEFLAGS)
$(BIN): $(OBJS)
$(CC) $(OBJS) $(LDFLAGS) -o $@
View
@@ -43,6 +43,13 @@
# include <io.h> /* setmode() */
#endif
#ifdef _OPENMP
#include <omp.h>
#else
#define omp_get_max_threads() 1
#define omp_get_thread_num() 0
#endif
#include "rwpng.h" /* typedefs, common macros, public prototypes */
#include "pam.h"
#include "mediancut.h"
@@ -345,9 +352,12 @@ float remap_to_palette(read_info *input_image, write_info *output_image, colorma
struct nearest_map *const n = nearest_init(map);
const int transparent_ind = nearest_search(n, (f_pixel){0,0,0,0}, min_opaque_val, NULL);
viter_state average_color[map->colors];
viter_init(map, 1, average_color);
const int max_threads = omp_get_max_threads();
viter_state average_color[map->colors * max_threads];
viter_init(map, max_threads, average_color);
#pragma omp parallel for if (rows*cols > 3000) \
default(none) shared(average_color) reduction(+:remapping_error) reduction(+:remapped_pixels)
for (int row = 0; row < rows; ++row) {
for(int col = 0; col < cols; ++col) {
@@ -366,13 +376,13 @@ float remap_to_palette(read_info *input_image, write_info *output_image, colorma
row_pointers[row][col] = match;
viter_update_color(px, 1.0, map, match, 0, average_color);
}
viter_update_color(px, 1.0, map, match, omp_get_thread_num(), average_color);
}
}
nearest_free(n);
viter_finalize(map, max_threads, average_color);
viter_finalize(map, 1, average_color);
nearest_free(n);
return remapping_error / MAX(1,remapped_pixels);
}
View
26 viter.c
@@ -4,6 +4,14 @@
#include "nearest.h"
#include <stdlib.h>
#include <string.h>
#ifdef _OPENMP
#include <omp.h>
#else
#define omp_get_max_threads() 1
#define omp_get_thread_num() 0
#endif
/*
* Voronoi iteration: new palette color is computed from weighted average of colors that map to that palette entry.
*/
@@ -50,26 +58,30 @@ void viter_finalize(colormap *map, const int max_threads, const viter_state aver
}
}
double viter_do_iteration(hist *hist, colormap *map, const float min_opaque_val, viter_callback callback)
double viter_do_iteration(hist *hist, colormap *const map, const float min_opaque_val, viter_callback callback)
{
viter_state average_color[map->colors];
viter_init(map, 1, average_color);
const int max_threads = omp_get_max_threads();
viter_state average_color[map->colors * max_threads];
viter_init(map, max_threads, average_color);
struct nearest_map *const n = nearest_init(map);
hist_item *achv = hist->achv;
hist_item *const achv = hist->achv;
const int hist_size = hist->size;
double total_diff=0;
for(int j=0; j < hist->size; j++) {
#pragma omp parallel for if (hist_size > 3000) \
default(none) shared(average_color,callback) reduction(+:total_diff)
for(int j=0; j < hist_size; j++) {
float diff;
int match = nearest_search(n, achv[j].acolor, min_opaque_val, &diff);
total_diff += diff * achv[j].perceptual_weight;
viter_update_color(achv[j].acolor, achv[j].perceptual_weight, map, match, 0, average_color);
viter_update_color(achv[j].acolor, achv[j].perceptual_weight, map, match, omp_get_thread_num(), average_color);
if (callback) callback(&achv[j], diff);
}
nearest_free(n);
viter_finalize(map, 1, average_color);
viter_finalize(map, max_threads, average_color);
return total_diff / hist->total_perceptual_weight;
}
View
@@ -8,4 +8,4 @@ typedef void (*viter_callback)(hist_item *item, float diff);
void viter_init(const colormap *map, const int max_threads, viter_state state[]);
void viter_update_color(const f_pixel acolor, const float value, const colormap *map, const int match, const int thread, viter_state state[]);
void viter_finalize(colormap *map, const int max_threads, const viter_state state[]);
double viter_do_iteration(hist *hist, colormap *map, const float min_opaque_val, viter_callback callback);
double viter_do_iteration(hist *hist, colormap *const map, const float min_opaque_val, viter_callback callback);

0 comments on commit 3c2d720

Please sign in to comment.