png speed improvement draft
authorMatthias Kramm <kramm@quiss.org>
Wed, 31 Mar 2010 03:29:38 +0000 (20:29 -0700)
committerMatthias Kramm <kramm@quiss.org>
Wed, 31 Mar 2010 03:29:38 +0000 (20:29 -0700)
config.h.in
configure
configure.in
lib/mem.c
lib/mem.h
lib/png.c

index 72c6e56..7f99da5 100644 (file)
@@ -82,6 +82,9 @@
 /* Define if you have the srand48 function.  */
 #undef HAVE_SRAND48
 
+/* Define if you have the calloc function.  */
+#undef HAVE_CALLOC
+
 /* Define if you have the stat function.  */
 #undef HAVE_STAT
 
 #endif
 #endif
 
+// supply a substitute calloc function if necessary
+#ifndef HAVE_CALLOC
+#define calloc rfx_calloc_replacement
+#endif
+
 #endif
index c8bd491..6a86e25 100755 (executable)
--- a/configure
+++ b/configure
@@ -5423,7 +5423,7 @@ _ACEOF
 
 fi
  #needed for jpeglib
- for ac_func in popen wcschr wcsdup mkstemp stat mmap lrand48 rand srand48 srand bcopy bzero time getrusage mallinfo open64
+ for ac_func in popen wcschr wcsdup mkstemp stat mmap lrand48 rand srand48 srand bcopy bzero time getrusage mallinfo open64 calloc
 do :
   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
 ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
index 1a5efbe..515718a 100644 (file)
@@ -272,7 +272,7 @@ dnl Checks for typedefs, structures, and compiler characteristics.
  AC_TYPE_SIZE_T
  AC_STRUCT_TM
  AC_CHECK_TYPE(boolean,int) #needed for jpeglib
- AC_CHECK_FUNCS(popen wcschr wcsdup mkstemp stat mmap lrand48 rand srand48 srand bcopy bzero time getrusage mallinfo open64)
+ AC_CHECK_FUNCS(popen wcschr wcsdup mkstemp stat mmap lrand48 rand srand48 srand bcopy bzero time getrusage mallinfo open64 calloc)
 
 AC_CHECK_SIZEOF([signed char])
 AC_CHECK_SIZEOF([signed short])
@@ -578,6 +578,10 @@ AH_BOTTOM([
 #endif
 #endif
 
+// supply a substitute calloc function if necessary
+#ifndef HAVE_CALLOC
+#define calloc rfx_calloc_replacement
+#endif
 
 #endif // __config_h__
 ])
index 8e619dc..6dd58f5 100644 (file)
--- a/lib/mem.c
+++ b/lib/mem.c
@@ -66,7 +66,7 @@ void* rfx_calloc(int size)
     return 0;
   }
 #ifdef HAVE_CALLOC
-  ptr = calloc(size);
+  ptr = calloc(1, size);
 #else
   ptr = malloc(size);
 #endif
@@ -80,6 +80,12 @@ void* rfx_calloc(int size)
 #endif
   return ptr;
 }
+#ifndef HAVE_CALLOC
+void* rfx_calloc_replacement(int nmemb, int size)
+{
+    rfx_calloc(nmemb*size);
+}
+#endif
 
 #ifdef MEMORY_INFO
 long rfx_memory_used()
index 5214c76..a963500 100644 (file)
--- a/lib/mem.h
+++ b/lib/mem.h
@@ -5,11 +5,16 @@
 extern "C" {
 #endif
 
+#include "../config.h"
+
 #define ALLOC_ARRAY(type, num) (((type)*)rfxalloc(sizeof(type)*(num)))
 void* rfx_alloc(int size);
 void* rfx_calloc(int size);
 void* rfx_realloc(void*data, int size);
 void rfx_free(void*data);
+#ifndef HAVE_CALLOC
+void* rfx_calloc_replacement(int nmemb, int size)
+#endif
 #ifdef MEMORY_INFO
 long rfx_memory_used();
 char* rfx_memory_used_str();
index 9ab0325..f6edc12 100644 (file)
--- a/lib/png.c
+++ b/lib/png.c
@@ -1376,7 +1376,7 @@ static int png_apply_specific_filter_32(int filtermode, unsigned char*dest, unsi
     }
     return filtermode;
 }
-    
+
 static int*num_bits_table = 0;
 
 static void make_num_bits_table()
@@ -1395,13 +1395,93 @@ static void make_num_bits_table()
     }
 }
 
+static int png_find_best_filter_8(unsigned char*src, int width, int y)
+{
+    /*
+
+       FFFF I X   X    M   M EEEE
+       F    I  X X     MM MM E
+       FFF  I   X      M M M EEE
+       F    I  X X     M   M E
+       F    I X   X    M   M EEEE
+
+    */
+    return 0;
+}
+
+static int png_find_best_filter_32(unsigned char*src, int width, int y)
+{
+    make_num_bits_table();
+    
+    int num_filters = y>0?5:2; //don't apply y-direction filter in first line
+
+    int srcwidth = y?width*4:0;
+    int x;
+    unsigned char*pairs[5];
+    pairs[0] = calloc(1, 8192);
+    pairs[1] = calloc(1, 8192);
+    pairs[2] = calloc(1, 8192);
+    pairs[3] = calloc(1, 8192);
+    pairs[4] = calloc(1, 8192);
+    
+    unsigned char old[5];
+
+    old[0] = src[3];
+    old[1] = src[3];
+    old[2] = src[3] - src[3-srcwidth];
+    old[3] = src[3] - src[3-srcwidth];
+    old[4] = src[3] - PaethPredictor(0, src[3-srcwidth], 0);
+
+    int different_pairs[5] = {0,0,0,0,0};
+
+    int w = width*4;
+    for(x=4;x<w;x++) {
+       unsigned char dest[5];
+       dest[0] = src[x];
+       dest[1] = src[x] - src[x-4];
+       dest[2] = src[x] - src[x-srcwidth];
+       dest[3] = src[x] - (src[x-4] + src[x-srcwidth])/2;
+       dest[4] = src[x] - PaethPredictor(src[x-4], src[x-srcwidth], src[x-4-srcwidth]);
+
+       int i;
+       for(i=0;i<5;i++) {
+           int v = dest[i]<<8|old[i];
+           int p = v>>3;
+           int b = 1<<(v&7);
+           if(!pairs[i][p]&b) {
+               pairs[i][p]|=b;
+               different_pairs[i]++;
+           }
+       }
+       memcpy(old, dest, sizeof(old));
+    }
+    int f;
+    int best_nr = 0;
+    int best_energy = INT_MAX;
+    for(f=0;f<num_filters;f++) {
+       int energy = different_pairs[f];
+       if(energy<best_energy) {
+           best_nr = f;
+           best_energy = energy;
+       }
+    }
+    free(pairs[0]);
+    free(pairs[1]);
+    free(pairs[2]);
+    free(pairs[3]);
+    free(pairs[4]);
+    return best_nr;
+}
+    
+    
 static int png_apply_filter(unsigned char*dest, unsigned char*src, int width, int y, int bpp)
 {
     make_num_bits_table();
 
     int num_filters = y>0?5:2; //don't apply y-direction filter in first line
-    int f;
     int best_nr = 0;
+#if 0
+    int f;
     int best_energy = INT_MAX;
     int w = width*(bpp/8);
     unsigned char* pairs = malloc(8192);
@@ -1432,11 +1512,17 @@ static int png_apply_filter(unsigned char*dest, unsigned char*src, int width, in
            best_energy = energy;
        }
     }
+    free(pairs);
+#else
+    if(bpp==8)
+       best_nr = png_find_best_filter_8(src, width, y);
+    else
+       best_nr = png_find_best_filter_32(src, width, y);
+#endif
     if(bpp==8)
        png_apply_specific_filter_8(best_nr, dest, src, width);
     else
        png_apply_specific_filter_32(best_nr, dest, src, width);
-    free(pairs);
     return best_nr;
 }
 
@@ -1475,6 +1561,7 @@ EXPORT void savePNG(const char*filename, unsigned char*data, int width, int heig
 
     if(!numcolors) {
        int num = png_get_number_of_palette_entries((COL*)data, width, height, palette, &has_alpha);
+       num = 256;
        if(num<=255) {
            //printf("image has %d different colors (alpha=%d)\n", num, has_alpha);
            data2 = malloc(width*height);