]> mj.ucw.cz Git - libucw.git/blobdiff - images/color.c
Opt: Documented opt and its interaction with conf
[libucw.git] / images / color.c
index 193a0f138477d313734c410901cbc4d2bfc0ff40..2d3a02d3e2eb526c11c49f600c77887df51d124c 100644 (file)
@@ -9,14 +9,15 @@
 
 #undef LOCAL_DEBUG
 
-#include "sherlock/sherlock.h"
-#include "lib/math.h"
-#include "images/images.h"
-#include "images/color.h"
-#include "images/error.h"
-#include "images/math.h"
+#include <ucw/lib.h>
+#include <ucw/time.h>
+#include <images/images.h>
+#include <images/color.h>
+#include <images/error.h>
+#include <images/math.h>
 
 #include <string.h>
+#include <math.h>
 
 uns color_space_channels[COLOR_SPACE_MAX] = {
   [COLOR_SPACE_UNKNOWN] = 0,
@@ -154,7 +155,7 @@ color_put(struct image_context *ctx, struct color *color, byte *dest, uns dest_s
 struct image_conv_options image_conv_defaults = {
   .flags = IMAGE_CONV_COPY_ALPHA | IMAGE_CONV_FILL_ALPHA | IMAGE_CONV_APPLY_ALPHA,
   .background = { .color_space = COLOR_SPACE_GRAYSCALE } };
-  
+
 /* Grayscale <-> RGB */
 
 #define IMAGE_WALK_PREFIX(x) walk_##x
@@ -163,7 +164,7 @@ struct image_conv_options image_conv_defaults = {
 #define IMAGE_WALK_SEC_COL_STEP 1
 #define IMAGE_WALK_UNROLL 4
 #define IMAGE_WALK_DO_STEP do{ walk_pos[0] = walk_pos[1] = walk_pos[2] = walk_sec_pos[0]; }while(0)
-#include "images/image-walk.h"
+#include <images/image-walk.h>
 
 #define IMAGE_WALK_PREFIX(x) walk_##x
 #define IMAGE_WALK_FUNC_NAME image_conv_rgb_n_to_gray_1
@@ -171,7 +172,25 @@ struct image_conv_options image_conv_defaults = {
 #define IMAGE_WALK_COL_STEP 1
 #define IMAGE_WALK_UNROLL 2
 #define IMAGE_WALK_DO_STEP do{ walk_pos[0] = rgb_to_gray_func(walk_sec_pos[0], walk_sec_pos[1], walk_sec_pos[2]); }while(0)
-#include "images/image-walk.h"
+#include <images/image-walk.h>
+
+/* Grayscale <-> YCbCr */
+
+#define IMAGE_WALK_PREFIX(x) walk_##x
+#define IMAGE_WALK_FUNC_NAME image_conv_gray_1_to_ycbcr_n
+#define IMAGE_WALK_DOUBLE
+#define IMAGE_WALK_SEC_COL_STEP 1
+#define IMAGE_WALK_UNROLL 4
+#define IMAGE_WALK_DO_STEP do{ walk_pos[0] = walk_sec_pos[0]; walk_pos[1] = walk_pos[2] = 0; }while(0)
+#include <images/image-walk.h>
+
+#define IMAGE_WALK_PREFIX(x) walk_##x
+#define IMAGE_WALK_FUNC_NAME image_conv_ycbcr_n_to_gray_1
+#define IMAGE_WALK_DOUBLE
+#define IMAGE_WALK_COL_STEP 1
+#define IMAGE_WALK_UNROLL 4
+#define IMAGE_WALK_DO_STEP do{ walk_pos[0] = walk_sec_pos[0]; }while(0)
+#include <images/image-walk.h>
 
 /* YCbCr <-> RGB */
 
@@ -191,7 +210,7 @@ pixel_conv_ycbcr_to_rgb(byte *dest, byte *src)
 #define IMAGE_WALK_FUNC_NAME image_conv_ycbcr_n_to_rgb_n
 #define IMAGE_WALK_DOUBLE
 #define IMAGE_WALK_DO_STEP do{ pixel_conv_ycbcr_to_rgb(walk_pos, walk_sec_pos); }while(0)
-#include "images/image-walk.h"
+#include <images/image-walk.h>
 
 static inline void
 pixel_conv_rgb_to_ycbcr(byte *dest, byte *src)
@@ -209,7 +228,7 @@ pixel_conv_rgb_to_ycbcr(byte *dest, byte *src)
 #define IMAGE_WALK_FUNC_NAME image_conv_rgb_n_to_ycbcr_n
 #define IMAGE_WALK_DOUBLE
 #define IMAGE_WALK_DO_STEP do{ pixel_conv_rgb_to_ycbcr(walk_pos, walk_sec_pos); }while(0)
-#include "images/image-walk.h"
+#include <images/image-walk.h>
 
 /* CMYK <-> RGB */
 
@@ -227,7 +246,7 @@ pixel_conv_cmyk_to_rgb(byte *dest, byte *src)
 #define IMAGE_WALK_DOUBLE
 #define IMAGE_WALK_SEC_COL_STEP 4
 #define IMAGE_WALK_DO_STEP do{ pixel_conv_cmyk_to_rgb(walk_pos, walk_sec_pos); }while(0)
-#include "images/image-walk.h"
+#include <images/image-walk.h>
 
 static inline void
 pixel_conv_rgb_to_cmyk(byte *dest, byte *src)
@@ -246,7 +265,80 @@ pixel_conv_rgb_to_cmyk(byte *dest, byte *src)
 #define IMAGE_WALK_DOUBLE
 #define IMAGE_WALK_COL_STEP 4
 #define IMAGE_WALK_DO_STEP do{ pixel_conv_rgb_to_cmyk(walk_pos, walk_sec_pos); }while(0)
-#include "images/image-walk.h"
+#include <images/image-walk.h>
+
+/* CMYK <-> YCbCr */
+
+#define IMAGE_WALK_PREFIX(x) walk_##x
+#define IMAGE_WALK_FUNC_NAME image_conv_cmyk_4_to_ycbcr_n
+#define IMAGE_WALK_DOUBLE
+#define IMAGE_WALK_SEC_COL_STEP 4
+#define IMAGE_WALK_DO_STEP do{ pixel_conv_cmyk_to_rgb(walk_pos, walk_sec_pos); pixel_conv_rgb_to_ycbcr(walk_pos, walk_pos); }while(0)
+#include <images/image-walk.h>
+
+#define IMAGE_WALK_PREFIX(x) walk_##x
+#define IMAGE_WALK_FUNC_NAME image_conv_ycbcr_n_to_cmyk_4
+#define IMAGE_WALK_DOUBLE
+#define IMAGE_WALK_COL_STEP 4
+#define IMAGE_WALK_DO_STEP do{ pixel_conv_ycbcr_to_rgb(walk_pos, walk_sec_pos); pixel_conv_rgb_to_cmyk(walk_pos, walk_pos); }while(0)
+#include <images/image-walk.h>
+
+/* YCCK <-> RGB */
+
+static inline void
+pixel_conv_ycck_to_rgb(byte *dest, byte *src)
+{
+  int y = src[0], cb = src[1] - 128, cr = src[2] - 128;
+  uns d = (255 - src[3]) * (0xffffffffU / 255 /255);
+  dest[0] = (d * CLAMP(y + (91881 * cr) / 0x10000, 0, 255) >> 24);
+  dest[1] = (d * CLAMP(y - (22553 * cb + 46801 * cr) / 0x10000, 0, 255) >> 24);
+  dest[2] = (d * CLAMP(y + (116129 * cb) / 0x10000, 0, 255) >> 24);
+}
+
+#define IMAGE_WALK_PREFIX(x) walk_##x
+#define IMAGE_WALK_FUNC_NAME image_conv_ycck_4_to_rgb_n
+#define IMAGE_WALK_DOUBLE
+#define IMAGE_WALK_SEC_COL_STEP 4
+#define IMAGE_WALK_DO_STEP do{ pixel_conv_ycck_to_rgb(walk_pos, walk_sec_pos); }while(0)
+#include <images/image-walk.h>
+
+static inline void
+pixel_conv_rgb_to_ycck(byte *dest, byte *src)
+{
+  uns k = MAX(src[0], src[1]);
+  k = MAX(k, src[2]);
+  uns d = fast_div_u32_u8(0x7fffffffU, k); /* == 0 for zero K */
+  uns r = 255 - ((d * (k - src[0])) >> 23);
+  uns g = 255 - ((d * (k - src[1])) >> 23);
+  uns b = 255 - ((d * (k - src[2])) >> 23);
+  dest[0] = (19595 * r + 38470 * g + 7471 * b) / 0x10000;
+  dest[1] = (0x800000 + 0x8000 * b - 11058 * r - 21710 * g) / 0x10000;
+  dest[2] = (0x800000 + 0x8000 * r - 27439 * g - 5329 * b) / 0x10000;
+  dest[3] = 255 - k;
+}
+
+#define IMAGE_WALK_PREFIX(x) walk_##x
+#define IMAGE_WALK_FUNC_NAME image_conv_rgb_n_to_ycck_4
+#define IMAGE_WALK_DOUBLE
+#define IMAGE_WALK_COL_STEP 4
+#define IMAGE_WALK_DO_STEP do{ pixel_conv_rgb_to_ycck(walk_pos, walk_sec_pos); }while(0)
+#include <images/image-walk.h>
+
+/* YCCK <-> YCbCr */
+
+#define IMAGE_WALK_PREFIX(x) walk_##x
+#define IMAGE_WALK_FUNC_NAME image_conv_ycck_4_to_ycbcr_n
+#define IMAGE_WALK_DOUBLE
+#define IMAGE_WALK_SEC_COL_STEP 4
+#define IMAGE_WALK_DO_STEP do{ pixel_conv_ycck_to_rgb(walk_pos, walk_sec_pos); pixel_conv_rgb_to_ycbcr(walk_pos, walk_pos); }while(0)
+#include <images/image-walk.h>
+
+#define IMAGE_WALK_PREFIX(x) walk_##x
+#define IMAGE_WALK_FUNC_NAME image_conv_ycbcr_n_to_ycck_4
+#define IMAGE_WALK_DOUBLE
+#define IMAGE_WALK_COL_STEP 4
+#define IMAGE_WALK_DO_STEP do{ pixel_conv_ycbcr_to_rgb(walk_pos, walk_sec_pos); pixel_conv_rgb_to_ycck(walk_pos, walk_pos); }while(0)
+#include <images/image-walk.h>
 
 /* Main functions */
 
@@ -265,6 +357,13 @@ image_conv_color_space(struct image_context *ctx UNUSED, struct image *dest, str
                  return 1;
                }
              break;
+            case COLOR_SPACE_YCBCR:
+              if (dest->pixel_size == 1)
+               {
+                 image_conv_ycbcr_n_to_gray_1(dest, src);
+                 return 1;
+               }
+             break;
          }
        break;
       case COLOR_SPACE_RGB:
@@ -287,28 +386,82 @@ image_conv_color_space(struct image_context *ctx UNUSED, struct image *dest, str
                  return 1;
                }
              break;
+           case COLOR_SPACE_YCCK:
+             if (src->pixel_size == 4)
+               {
+                 image_conv_ycck_4_to_rgb_n(dest, src);
+                 return 1;
+               }
+             break;
        }
        break;
       case COLOR_SPACE_YCBCR:
         switch (src->flags & IMAGE_CHANNELS_FORMAT)
          {
+            case COLOR_SPACE_GRAYSCALE:
+              if (src->pixel_size == 1)
+               {
+                  image_conv_gray_1_to_ycbcr_n(dest, src);
+                 return 1;
+               }
+             break;
            case COLOR_SPACE_RGB:
              image_conv_rgb_n_to_ycbcr_n(dest, src);
              return 1;
+           case COLOR_SPACE_CMYK:
+             if (src->pixel_size == 4)
+               {
+                 image_conv_cmyk_4_to_ycbcr_n(dest, src);
+                 return 1;
+               }
+             break;
+           case COLOR_SPACE_YCCK:
+             if (src->pixel_size == 4)
+               {
+                 image_conv_ycck_4_to_ycbcr_n(dest, src);
+                 return 1;
+               }
+             break;
          }
        break;
       case COLOR_SPACE_CMYK:
         switch (src->flags & IMAGE_CHANNELS_FORMAT)
           {
-           case COLOR_SPACE_RGB:
+           case COLOR_SPACE_RGB:
              if (dest->pixel_size == 4)
                {
                  image_conv_rgb_n_to_cmyk_4(dest, src);
                  return 1;
                }
              break;
+           case COLOR_SPACE_YCBCR:
+             if (dest->pixel_size == 4)
+               {
+                 image_conv_ycbcr_n_to_cmyk_4(dest, src);
+                 return 1;
+               }
+             break;
           }
         break;
+      case COLOR_SPACE_YCCK:
+       switch (src->flags & IMAGE_CHANNELS_FORMAT)
+         {
+           case COLOR_SPACE_RGB:
+             if (dest->pixel_size == 4)
+               {
+                 image_conv_rgb_n_to_ycck_4(dest, src);
+                 return 1;
+               }
+             break;
+           case COLOR_SPACE_YCBCR:
+             if (dest->pixel_size == 4)
+               {
+                 image_conv_ycbcr_n_to_ycck_4(dest, src);
+                 return 1;
+               }
+             break;
+         }
+       break;
     }
   return 0;
 }
@@ -332,7 +485,7 @@ image_conv_copy(struct image *dest, struct image *src)
 #             define IMAGE_WALK_SEC_IMAGE src
 #            define IMAGE_WALK_UNROLL 4
 #            define IMAGE_WALK_DO_STEP do{ walk_pos[0] = walk_sec_pos[0]; }while(0)
-#            include "images/image-walk.h"
+#            include <images/image-walk.h>
             }
            return;
          case 2:
@@ -343,7 +496,7 @@ image_conv_copy(struct image *dest, struct image *src)
 #             define IMAGE_WALK_SEC_IMAGE src
 #            define IMAGE_WALK_UNROLL 4
 #            define IMAGE_WALK_DO_STEP do{ walk_pos[0] = walk_sec_pos[0]; walk_pos[1] = walk_sec_pos[1]; }while(0)
-#            include "images/image-walk.h"
+#            include <images/image-walk.h>
            return;
          case 3:
 #            define IMAGE_WALK_PREFIX(x) walk_##x
@@ -353,7 +506,7 @@ image_conv_copy(struct image *dest, struct image *src)
 #             define IMAGE_WALK_SEC_IMAGE src
 #            define IMAGE_WALK_UNROLL 2
 #            define IMAGE_WALK_DO_STEP do{ walk_pos[0] = walk_sec_pos[0]; walk_pos[1] = walk_sec_pos[1]; walk_pos[2] = walk_sec_pos[2]; }while(0)
-#            include "images/image-walk.h"
+#            include <images/image-walk.h>
            return;
          case 4:
 #            define IMAGE_WALK_PREFIX(x) walk_##x
@@ -363,7 +516,7 @@ image_conv_copy(struct image *dest, struct image *src)
 #             define IMAGE_WALK_SEC_IMAGE src
 #            define IMAGE_WALK_UNROLL 2
 #            define IMAGE_WALK_DO_STEP do{ walk_pos[0] = walk_sec_pos[0]; walk_pos[1] = walk_sec_pos[1]; walk_pos[2] = walk_sec_pos[2]; walk_pos[3] = walk_sec_pos[3]; }while(0)
-#            include "images/image-walk.h"
+#            include <images/image-walk.h>
            return;
          default:
 #            define IMAGE_WALK_PREFIX(x) walk_##x
@@ -372,7 +525,7 @@ image_conv_copy(struct image *dest, struct image *src)
 #             define IMAGE_WALK_IMAGE dest
 #             define IMAGE_WALK_SEC_IMAGE src
 #            define IMAGE_WALK_DO_STEP do{ for (uns i = 0; i < channels; i++) walk_pos[i] = walk_sec_pos[i]; }while(0)
-#             include "images/image-walk.h"
+#             include <images/image-walk.h>
            return;
        }
     }
@@ -405,7 +558,7 @@ image_conv_fill_alpha(struct image *dest)
 #           define IMAGE_WALK_COL_STEP 2
 #           define IMAGE_WALK_UNROLL 4
 #           define IMAGE_WALK_DO_STEP do{ walk_pos[1] = 255; }while(0)
-#           include "images/image-walk.h"
+#           include <images/image-walk.h>
            return;
          }
        break;
@@ -418,7 +571,7 @@ image_conv_fill_alpha(struct image *dest)
 #           define IMAGE_WALK_COL_STEP 4
 #           define IMAGE_WALK_UNROLL 4
 #           define IMAGE_WALK_DO_STEP do{ walk_pos[3] = 255; }while(0)
-#           include "images/image-walk.h"
+#           include <images/image-walk.h>
            return;
          }
        break;
@@ -429,7 +582,7 @@ image_conv_fill_alpha(struct image *dest)
 #   define IMAGE_WALK_IMAGE dest
 #   define IMAGE_WALK_UNROLL 4
 #   define IMAGE_WALK_DO_STEP do{ walk_pos[dest->channels - 1] = 255; }while(0)
-#   include "images/image-walk.h"
+#   include <images/image-walk.h>
   }
 }
 
@@ -445,7 +598,7 @@ image_conv_copy_alpha(struct image *dest, struct image *src)
 #     define IMAGE_WALK_SEC_IMAGE src
 #     define IMAGE_WALK_UNROLL 4
 #     define IMAGE_WALK_DO_STEP do{ walk_pos[dest->channels - 1] = walk_sec_pos[src->channels - 1]; }while(0)
-#     include "images/image-walk.h"
+#     include <images/image-walk.h>
     }
 }
 
@@ -478,7 +631,7 @@ image_conv_apply_alpha_from(struct image_context *ctx, struct image *dest, struc
 #        define IMAGE_WALK_UNROLL 2
 #         define IMAGE_WALK_DO_STEP do{ \
               walk_pos[0] = image_conv_alpha_func(walk_pos[0], walk_sec_pos[src->channels - 1], a[0], b[0]); }while(0)
-#         include "images/image-walk.h"
+#         include <images/image-walk.h>
        }
        return 1;
       case 3:
@@ -492,7 +645,7 @@ image_conv_apply_alpha_from(struct image_context *ctx, struct image *dest, struc
               walk_pos[0] = image_conv_alpha_func(walk_pos[0], walk_sec_pos[src->channels - 1], a[0], b[0]); \
               walk_pos[1] = image_conv_alpha_func(walk_pos[1], walk_sec_pos[src->channels - 1], a[1], b[1]); \
               walk_pos[2] = image_conv_alpha_func(walk_pos[2], walk_sec_pos[src->channels - 1], a[2], b[2]); }while(0)
-#         include "images/image-walk.h"
+#         include <images/image-walk.h>
        }
        return 1;
     }
@@ -504,7 +657,7 @@ image_conv_apply_alpha_from(struct image_context *ctx, struct image *dest, struc
 #   define IMAGE_WALK_DOUBLE
 #   define IMAGE_WALK_DO_STEP do{ for (uns i = 0; i < dest->channels; i++) \
         walk_pos[i] = image_conv_alpha_func(walk_pos[i], walk_sec_pos[src->channels - 1], a[i], b[i]); }while(0)
-#   include "images/image-walk.h"
+#   include <images/image-walk.h>
   }
   return 1;
 }
@@ -535,7 +688,7 @@ image_conv_apply_alpha_to(struct image_context *ctx, struct image *dest, struct
 #        define IMAGE_WALK_UNROLL 2
 #         define IMAGE_WALK_DO_STEP do{ \
               walk_pos[0] = image_conv_alpha_func(walk_sec_pos[0], walk_sec_pos[src->channels - 1], a[0], b[0]); }while(0)
-#         include "images/image-walk.h"
+#         include <images/image-walk.h>
        }
        return 1;
       case 3:
@@ -549,7 +702,7 @@ image_conv_apply_alpha_to(struct image_context *ctx, struct image *dest, struct
               walk_pos[0] = image_conv_alpha_func(walk_sec_pos[0], walk_sec_pos[src->channels - 1], a[0], b[0]); \
               walk_pos[1] = image_conv_alpha_func(walk_sec_pos[1], walk_sec_pos[src->channels - 1], a[1], b[1]); \
               walk_pos[2] = image_conv_alpha_func(walk_sec_pos[2], walk_sec_pos[src->channels - 1], a[2], b[2]); }while(0)
-#         include "images/image-walk.h"
+#         include <images/image-walk.h>
        }
        return 1;
     }
@@ -561,7 +714,7 @@ image_conv_apply_alpha_to(struct image_context *ctx, struct image *dest, struct
 #   define IMAGE_WALK_DOUBLE
 #   define IMAGE_WALK_DO_STEP do{ for (uns i = 0; i < dest->channels; i++) \
         walk_pos[i] = image_conv_alpha_func(walk_sec_pos[i], walk_sec_pos[src->channels - 1], a[i], b[i]); }while(0)
-#   include "images/image-walk.h"
+#   include <images/image-walk.h>
   }
   return 1;
 }
@@ -1196,18 +1349,19 @@ main(void)
   byte *a = xmalloc(3 * CNT), *b = xmalloc(3 * CNT);
   for (uns i = 0; i < 3 * CNT; i++)
     a[i] = random_max(256);
-  init_timer();
+  timestamp_t timer;
+  init_timer(&timer);
   for (uns i = 0; i < TESTS; i++)
     memcpy(b, a, CNT * 3);
-  DBG("memcpy time=%d", (uns)get_timer());
-  init_timer();
+  DBG("memcpy time=%d", get_timer(&timer));
+  init_timer(&timer);
   for (uns i = 0; i < TESTS; i++)
     srgb_to_luv_pixels(b, a, CNT);
-  DBG("direct time=%d", (uns)get_timer());
-  init_timer();
+  DBG("direct time=%d", get_timer(&timer));
+  init_timer(&timer);
   for (uns i = 0; i < TESTS; i++)
     color_conv_pixels(b, a, CNT, srgb_to_luv_grid);
-  DBG("grid time=%d", (uns)get_timer());
+  DBG("grid time=%d", get_timer(&timer));
 #endif
   return 0;
 }