Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. #include "fitz.h"
  2.  
  3. #define SLOWCMYK
  4.  
  5. fz_colorspace *
  6. fz_new_colorspace(char *name, int n)
  7. {
  8.         fz_colorspace *cs = fz_malloc(sizeof(fz_colorspace));
  9.         cs->refs = 1;
  10.         fz_strlcpy(cs->name, name, sizeof cs->name);
  11.         cs->n = n;
  12.         cs->to_rgb = NULL;
  13.         cs->from_rgb = NULL;
  14.         cs->free_data = NULL;
  15.         cs->data = NULL;
  16.         return cs;
  17. }
  18.  
  19. fz_colorspace *
  20. fz_keep_colorspace(fz_colorspace *cs)
  21. {
  22.         if (cs->refs < 0)
  23.                 return cs;
  24.         cs->refs ++;
  25.         return cs;
  26. }
  27.  
  28. void
  29. fz_drop_colorspace(fz_colorspace *cs)
  30. {
  31.         if (cs && cs->refs < 0)
  32.                 return;
  33.         if (cs && --cs->refs == 0)
  34.         {
  35.                 if (cs->free_data && cs->data)
  36.                         cs->free_data(cs);
  37.                 fz_free(cs);
  38.         }
  39. }
  40.  
  41. /* Device colorspace definitions */
  42.  
  43. static void gray_to_rgb(fz_colorspace *cs, float *gray, float *rgb)
  44. {
  45.         rgb[0] = gray[0];
  46.         rgb[1] = gray[0];
  47.         rgb[2] = gray[0];
  48. }
  49.  
  50. static void rgb_to_gray(fz_colorspace *cs, float *rgb, float *gray)
  51. {
  52.         float r = rgb[0];
  53.         float g = rgb[1];
  54.         float b = rgb[2];
  55.         gray[0] = r * 0.3f + g * 0.59f + b * 0.11f;
  56. }
  57.  
  58. static void rgb_to_rgb(fz_colorspace *cs, float *rgb, float *xyz)
  59. {
  60.         xyz[0] = rgb[0];
  61.         xyz[1] = rgb[1];
  62.         xyz[2] = rgb[2];
  63. }
  64.  
  65. static void bgr_to_rgb(fz_colorspace *cs, float *bgr, float *rgb)
  66. {
  67.         rgb[0] = bgr[2];
  68.         rgb[1] = bgr[1];
  69.         rgb[2] = bgr[0];
  70. }
  71.  
  72. static void rgb_to_bgr(fz_colorspace *cs, float *rgb, float *bgr)
  73. {
  74.         bgr[0] = rgb[2];
  75.         bgr[1] = rgb[1];
  76.         bgr[2] = rgb[0];
  77. }
  78.  
  79. static void cmyk_to_rgb(fz_colorspace *cs, float *cmyk, float *rgb)
  80. {
  81. #ifdef SLOWCMYK /* from poppler */
  82.         float c = cmyk[0], m = cmyk[1], y = cmyk[2], k = cmyk[3];
  83.         float c1 = 1 - c, m1 = 1 - m, y1 = 1 - y, k1 = 1 - k;
  84.         float r, g, b, x;
  85.  
  86.         /* this is a matrix multiplication, unrolled for performance */
  87.         x = c1 * m1 * y1 * k1;  /* 0 0 0 0 */
  88.         r = g = b = x;
  89.         x = c1 * m1 * y1 * k;   /* 0 0 0 1 */
  90.         r += 0.1373 * x;
  91.         g += 0.1216 * x;
  92.         b += 0.1255 * x;
  93.         x = c1 * m1 * y * k1;   /* 0 0 1 0 */
  94.         r += x;
  95.         g += 0.9490 * x;
  96.         x = c1 * m1 * y * k;    /* 0 0 1 1 */
  97.         r += 0.1098 * x;
  98.         g += 0.1020 * x;
  99.         x = c1 * m * y1 * k1;   /* 0 1 0 0 */
  100.         r += 0.9255 * x;
  101.         b += 0.5490 * x;
  102.         x = c1 * m * y1 * k;    /* 0 1 0 1 */
  103.         r += 0.1412 * x;
  104.         x = c1 * m * y * k1;    /* 0 1 1 0 */
  105.         r += 0.9294 * x;
  106.         g += 0.1098 * x;
  107.         b += 0.1412 * x;
  108.         x = c1 * m * y * k;     /* 0 1 1 1 */
  109.         r += 0.1333 * x;
  110.         x = c * m1 * y1 * k1;   /* 1 0 0 0 */
  111.         g += 0.6784 * x;
  112.         b += 0.9373 * x;
  113.         x = c * m1 * y1 * k;    /* 1 0 0 1 */
  114.         g += 0.0588 * x;
  115.         b += 0.1412 * x;
  116.         x = c * m1 * y * k1;    /* 1 0 1 0 */
  117.         g += 0.6510 * x;
  118.         b += 0.3137 * x;
  119.         x = c * m1 * y * k;     /* 1 0 1 1 */
  120.         g += 0.0745 * x;
  121.         x = c * m * y1 * k1;    /* 1 1 0 0 */
  122.         r += 0.1804 * x;
  123.         g += 0.1922 * x;
  124.         b += 0.5725 * x;
  125.         x = c * m * y1 * k;     /* 1 1 0 1 */
  126.         b += 0.0078 * x;
  127.         x = c * m * y * k1;     /* 1 1 1 0 */
  128.         r += 0.2118 * x;
  129.         g += 0.2119 * x;
  130.         b += 0.2235 * x;
  131.  
  132.         rgb[0] = CLAMP(r, 0, 1);
  133.         rgb[1] = CLAMP(g, 0, 1);
  134.         rgb[2] = CLAMP(b, 0, 1);
  135. #else
  136.         rgb[0] = 1 - MIN(1, cmyk[0] + cmyk[3]);
  137.         rgb[1] = 1 - MIN(1, cmyk[1] + cmyk[3]);
  138.         rgb[2] = 1 - MIN(1, cmyk[2] + cmyk[3]);
  139. #endif
  140. }
  141.  
  142. static void rgb_to_cmyk(fz_colorspace *cs, float *rgb, float *cmyk)
  143. {
  144.         float c, m, y, k;
  145.         c = 1 - rgb[0];
  146.         m = 1 - rgb[1];
  147.         y = 1 - rgb[2];
  148.         k = MIN(c, MIN(m, y));
  149.         cmyk[0] = c - k;
  150.         cmyk[1] = m - k;
  151.         cmyk[2] = y - k;
  152.         cmyk[3] = k;
  153. }
  154.  
  155. static fz_colorspace k_device_gray = { -1, "DeviceGray", 1, gray_to_rgb, rgb_to_gray };
  156. static fz_colorspace k_device_rgb = { -1, "DeviceRGB", 3, rgb_to_rgb, rgb_to_rgb };
  157. static fz_colorspace k_device_bgr = { -1, "DeviceRGB", 3, bgr_to_rgb, rgb_to_bgr };
  158. static fz_colorspace k_device_cmyk = { -1, "DeviceCMYK", 4, cmyk_to_rgb, rgb_to_cmyk };
  159.  
  160. fz_colorspace *fz_device_gray = &k_device_gray;
  161. fz_colorspace *fz_device_rgb = &k_device_rgb;
  162. fz_colorspace *fz_device_bgr = &k_device_bgr;
  163. fz_colorspace *fz_device_cmyk = &k_device_cmyk;
  164.  
  165. fz_colorspace *
  166. fz_find_device_colorspace(char *name)
  167. {
  168.         if (!strcmp(name, "DeviceGray"))
  169.                 return fz_device_gray;
  170.         if (!strcmp(name, "DeviceRGB"))
  171.                 return fz_device_rgb;
  172.         if (!strcmp(name, "DeviceBGR"))
  173.                 return fz_device_bgr;
  174.         if (!strcmp(name, "DeviceCMYK"))
  175.                 return fz_device_cmyk;
  176.         fz_warn("unknown device colorspace: %s", name);
  177.         return NULL;
  178. }
  179.  
  180. /* Fast pixmap color conversions */
  181.  
  182. static void fast_gray_to_rgb(fz_pixmap *src, fz_pixmap *dst)
  183. {
  184.         unsigned char *s = src->samples;
  185.         unsigned char *d = dst->samples;
  186.         int n = src->w * src->h;
  187.         while (n--)
  188.         {
  189.                 d[0] = s[0];
  190.                 d[1] = s[0];
  191.                 d[2] = s[0];
  192.                 d[3] = s[1];
  193.                 s += 2;
  194.                 d += 4;
  195.         }
  196. }
  197.  
  198. static void fast_gray_to_cmyk(fz_pixmap *src, fz_pixmap *dst)
  199. {
  200.         unsigned char *s = src->samples;
  201.         unsigned char *d = dst->samples;
  202.         int n = src->w * src->h;
  203.         while (n--)
  204.         {
  205.                 d[0] = 0;
  206.                 d[1] = 0;
  207.                 d[2] = 0;
  208.                 d[3] = s[0];
  209.                 d[4] = s[1];
  210.                 s += 2;
  211.                 d += 5;
  212.         }
  213. }
  214.  
  215. static void fast_rgb_to_gray(fz_pixmap *src, fz_pixmap *dst)
  216. {
  217.         unsigned char *s = src->samples;
  218.         unsigned char *d = dst->samples;
  219.         int n = src->w * src->h;
  220.         while (n--)
  221.         {
  222.                 d[0] = ((s[0]+1) * 77 + (s[1]+1) * 150 + (s[2]+1) * 28) >> 8;
  223.                 d[1] = s[3];
  224.                 s += 4;
  225.                 d += 2;
  226.         }
  227. }
  228.  
  229. static void fast_bgr_to_gray(fz_pixmap *src, fz_pixmap *dst)
  230. {
  231.         unsigned char *s = src->samples;
  232.         unsigned char *d = dst->samples;
  233.         int n = src->w * src->h;
  234.         while (n--)
  235.         {
  236.                 d[0] = ((s[0]+1) * 28 + (s[1]+1) * 150 + (s[2]+1) * 77) >> 8;
  237.                 d[1] = s[3];
  238.                 s += 4;
  239.                 d += 2;
  240.         }
  241. }
  242.  
  243. static void fast_rgb_to_cmyk(fz_pixmap *src, fz_pixmap *dst)
  244. {
  245.         unsigned char *s = src->samples;
  246.         unsigned char *d = dst->samples;
  247.         int n = src->w * src->h;
  248.         while (n--)
  249.         {
  250.                 unsigned char c = 255 - s[0];
  251.                 unsigned char m = 255 - s[1];
  252.                 unsigned char y = 255 - s[2];
  253.                 unsigned char k = MIN(c, MIN(m, y));
  254.                 d[0] = c - k;
  255.                 d[1] = m - k;
  256.                 d[2] = y - k;
  257.                 d[3] = k;
  258.                 d[4] = s[3];
  259.                 s += 4;
  260.                 d += 5;
  261.         }
  262. }
  263.  
  264. static void fast_bgr_to_cmyk(fz_pixmap *src, fz_pixmap *dst)
  265. {
  266.         unsigned char *s = src->samples;
  267.         unsigned char *d = dst->samples;
  268.         int n = src->w * src->h;
  269.         while (n--)
  270.         {
  271.                 unsigned char c = 255 - s[2];
  272.                 unsigned char m = 255 - s[1];
  273.                 unsigned char y = 255 - s[0];
  274.                 unsigned char k = MIN(c, MIN(m, y));
  275.                 d[0] = c - k;
  276.                 d[1] = m - k;
  277.                 d[2] = y - k;
  278.                 d[3] = k;
  279.                 d[4] = s[3];
  280.                 s += 4;
  281.                 d += 5;
  282.         }
  283. }
  284.  
  285. static void fast_cmyk_to_gray(fz_pixmap *src, fz_pixmap *dst)
  286. {
  287.         unsigned char *s = src->samples;
  288.         unsigned char *d = dst->samples;
  289.         int n = src->w * src->h;
  290.         while (n--)
  291.         {
  292.                 unsigned char c = fz_mul255(s[0], 77);
  293.                 unsigned char m = fz_mul255(s[1], 150);
  294.                 unsigned char y = fz_mul255(s[2], 28);
  295.                 d[0] = 255 - MIN(c + m + y + s[3], 255);
  296.                 d[1] = s[4];
  297.                 s += 5;
  298.                 d += 2;
  299.         }
  300. }
  301.  
  302. static void fast_cmyk_to_rgb(fz_pixmap *src, fz_pixmap *dst)
  303. {
  304.         unsigned char *s = src->samples;
  305.         unsigned char *d = dst->samples;
  306.         int n = src->w * src->h;
  307.         while (n--)
  308.         {
  309. #ifdef SLOWCMYK
  310.                 float cmyk[4], rgb[3];
  311.                 cmyk[0] = s[0] / 255.0f;
  312.                 cmyk[1] = s[1] / 255.0f;
  313.                 cmyk[2] = s[2] / 255.0f;
  314.                 cmyk[3] = s[3] / 255.0f;
  315.                 cmyk_to_rgb(NULL, cmyk, rgb);
  316.                 d[0] = rgb[0] * 255;
  317.                 d[1] = rgb[1] * 255;
  318.                 d[2] = rgb[2] * 255;
  319. #else
  320.                 d[0] = 255 - MIN(s[0] + s[3], 255);
  321.                 d[1] = 255 - MIN(s[1] + s[3], 255);
  322.                 d[2] = 255 - MIN(s[2] + s[3], 255);
  323. #endif
  324.                 d[3] = s[4];
  325.                 s += 5;
  326.                 d += 4;
  327.         }
  328. }
  329.  
  330. static void fast_cmyk_to_bgr(fz_pixmap *src, fz_pixmap *dst)
  331. {
  332.         unsigned char *s = src->samples;
  333.         unsigned char *d = dst->samples;
  334.         int n = src->w * src->h;
  335.         while (n--)
  336.         {
  337. #ifdef SLOWCMYK
  338.                 float cmyk[4], rgb[3];
  339.                 cmyk[0] = s[0] / 255.0f;
  340.                 cmyk[1] = s[1] / 255.0f;
  341.                 cmyk[2] = s[2] / 255.0f;
  342.                 cmyk[3] = s[3] / 255.0f;
  343.                 cmyk_to_rgb(NULL, cmyk, rgb);
  344.                 d[0] = rgb[2] * 255;
  345.                 d[1] = rgb[1] * 255;
  346.                 d[2] = rgb[0] * 255;
  347. #else
  348.                 d[0] = 255 - MIN(s[2] + s[3], 255);
  349.                 d[1] = 255 - MIN(s[1] + s[3], 255);
  350.                 d[2] = 255 - MIN(s[0] + s[3], 255);
  351. #endif
  352.                 d[3] = s[4];
  353.                 s += 5;
  354.                 d += 4;
  355.         }
  356. }
  357.  
  358. static void fast_rgb_to_bgr(fz_pixmap *src, fz_pixmap *dst)
  359. {
  360.         unsigned char *s = src->samples;
  361.         unsigned char *d = dst->samples;
  362.         int n = src->w * src->h;
  363.         while (n--)
  364.         {
  365.                 d[0] = s[2];
  366.                 d[1] = s[1];
  367.                 d[2] = s[0];
  368.                 d[3] = s[3];
  369.                 s += 4;
  370.                 d += 4;
  371.         }
  372. }
  373.  
  374. static void
  375. fz_std_conv_pixmap(fz_pixmap *src, fz_pixmap *dst)
  376. {
  377.         float srcv[FZ_MAX_COLORS];
  378.         float dstv[FZ_MAX_COLORS];
  379.         int srcn, dstn;
  380.         int y, x, k, i;
  381.  
  382.         fz_colorspace *ss = src->colorspace;
  383.         fz_colorspace *ds = dst->colorspace;
  384.  
  385.         unsigned char *s = src->samples;
  386.         unsigned char *d = dst->samples;
  387.  
  388.         assert(src->w == dst->w && src->h == dst->h);
  389.         assert(src->n == ss->n + 1);
  390.         assert(dst->n == ds->n + 1);
  391.  
  392.         srcn = ss->n;
  393.         dstn = ds->n;
  394.  
  395.         /* Special case for Lab colorspace (scaling of components to float) */
  396.         if (!strcmp(ss->name, "Lab") && srcn == 3)
  397.         {
  398.                 for (y = 0; y < src->h; y++)
  399.                 {
  400.                         for (x = 0; x < src->w; x++)
  401.                         {
  402.                                 srcv[0] = *s++ / 255.0f * 100;
  403.                                 srcv[1] = *s++ - 128;
  404.                                 srcv[2] = *s++ - 128;
  405.  
  406.                                 fz_convert_color(ss, srcv, ds, dstv);
  407.  
  408.                                 for (k = 0; k < dstn; k++)
  409.                                         *d++ = dstv[k] * 255;
  410.  
  411.                                 *d++ = *s++;
  412.                         }
  413.                 }
  414.         }
  415.  
  416.         /* Brute-force for small images */
  417.         else if (src->w * src->h < 256)
  418.         {
  419.                 for (y = 0; y < src->h; y++)
  420.                 {
  421.                         for (x = 0; x < src->w; x++)
  422.                         {
  423.                                 for (k = 0; k < srcn; k++)
  424.                                         srcv[k] = *s++ / 255.0f;
  425.  
  426.                                 fz_convert_color(ss, srcv, ds, dstv);
  427.  
  428.                                 for (k = 0; k < dstn; k++)
  429.                                         *d++ = dstv[k] * 255;
  430.  
  431.                                 *d++ = *s++;
  432.                         }
  433.                 }
  434.         }
  435.  
  436.         /* 1-d lookup table for separation and similar colorspaces */
  437.         else if (srcn == 1)
  438.         {
  439.                 unsigned char lookup[FZ_MAX_COLORS * 256];
  440.  
  441.                 for (i = 0; i < 256; i++)
  442.                 {
  443.                         srcv[0] = i / 255.0f;
  444.                         fz_convert_color(ss, srcv, ds, dstv);
  445.                         for (k = 0; k < dstn; k++)
  446.                                 lookup[i * dstn + k] = dstv[k] * 255;
  447.                 }
  448.  
  449.                 for (y = 0; y < src->h; y++)
  450.                 {
  451.                         for (x = 0; x < src->w; x++)
  452.                         {
  453.                                 i = *s++;
  454.                                 for (k = 0; k < dstn; k++)
  455.                                         *d++ = lookup[i * dstn + k];
  456.                                 *d++ = *s++;
  457.                         }
  458.                 }
  459.         }
  460.  
  461.         /* Memoize colors using a hash table for the general case */
  462.         else
  463.         {
  464.                 fz_hash_table *lookup;
  465.                 unsigned char *color;
  466.  
  467.                 lookup = fz_new_hash_table(509, srcn);
  468.  
  469.                 for (y = 0; y < src->h; y++)
  470.                 {
  471.                         for (x = 0; x < src->w; x++)
  472.                         {
  473.                                 color = fz_hash_find(lookup, s);
  474.                                 if (color)
  475.                                 {
  476.                                         memcpy(d, color, dstn);
  477.                                         s += srcn;
  478.                                         d += dstn;
  479.                                         *d++ = *s++;
  480.                                 }
  481.                                 else
  482.                                 {
  483.                                         for (k = 0; k < srcn; k++)
  484.                                                 srcv[k] = *s++ / 255.0f;
  485.                                         fz_convert_color(ss, srcv, ds, dstv);
  486.                                         for (k = 0; k < dstn; k++)
  487.                                                 *d++ = dstv[k] * 255;
  488.  
  489.                                         fz_hash_insert(lookup, s - srcn, d - dstn);
  490.  
  491.                                         *d++ = *s++;
  492.                                 }
  493.                         }
  494.                 }
  495.  
  496.                 fz_free_hash(lookup);
  497.         }
  498. }
  499.  
  500. void
  501. fz_convert_pixmap(fz_pixmap *sp, fz_pixmap *dp)
  502. {
  503.         fz_colorspace *ss = sp->colorspace;
  504.         fz_colorspace *ds = dp->colorspace;
  505.  
  506.         assert(ss && ds);
  507.  
  508.         if (sp->mask)
  509.                 dp->mask = fz_keep_pixmap(sp->mask);
  510.         dp->interpolate = sp->interpolate;
  511.  
  512.         if (ss == fz_device_gray)
  513.         {
  514.                 if (ds == fz_device_rgb) fast_gray_to_rgb(sp, dp);
  515.                 else if (ds == fz_device_bgr) fast_gray_to_rgb(sp, dp); /* bgr == rgb here */
  516.                 else if (ds == fz_device_cmyk) fast_gray_to_cmyk(sp, dp);
  517.                 else fz_std_conv_pixmap(sp, dp);
  518.         }
  519.  
  520.         else if (ss == fz_device_rgb)
  521.         {
  522.                 if (ds == fz_device_gray) fast_rgb_to_gray(sp, dp);
  523.                 else if (ds == fz_device_bgr) fast_rgb_to_bgr(sp, dp);
  524.                 else if (ds == fz_device_cmyk) fast_rgb_to_cmyk(sp, dp);
  525.                 else fz_std_conv_pixmap(sp, dp);
  526.         }
  527.  
  528.         else if (ss == fz_device_bgr)
  529.         {
  530.                 if (ds == fz_device_gray) fast_bgr_to_gray(sp, dp);
  531.                 else if (ds == fz_device_rgb) fast_rgb_to_bgr(sp, dp); /* bgr = rgb here */
  532.                 else if (ds == fz_device_cmyk) fast_bgr_to_cmyk(sp, dp);
  533.                 else fz_std_conv_pixmap(sp, dp);
  534.         }
  535.  
  536.         else if (ss == fz_device_cmyk)
  537.         {
  538.                 if (ds == fz_device_gray) fast_cmyk_to_gray(sp, dp);
  539.                 else if (ds == fz_device_bgr) fast_cmyk_to_bgr(sp, dp);
  540.                 else if (ds == fz_device_rgb) fast_cmyk_to_rgb(sp, dp);
  541.                 else fz_std_conv_pixmap(sp, dp);
  542.         }
  543.  
  544.         else fz_std_conv_pixmap(sp, dp);
  545. }
  546.  
  547. /* Convert a single color */
  548.  
  549. static void
  550. fz_std_conv_color(fz_colorspace *srcs, float *srcv, fz_colorspace *dsts, float *dstv)
  551. {
  552.         float rgb[3];
  553.         int i;
  554.  
  555.         if (srcs != dsts)
  556.         {
  557.                 assert(srcs->to_rgb && dsts->from_rgb);
  558.                 srcs->to_rgb(srcs, srcv, rgb);
  559.                 dsts->from_rgb(dsts, rgb, dstv);
  560.                 for (i = 0; i < dsts->n; i++)
  561.                         dstv[i] = CLAMP(dstv[i], 0, 1);
  562.         }
  563.         else
  564.         {
  565.                 for (i = 0; i < srcs->n; i++)
  566.                         dstv[i] = srcv[i];
  567.         }
  568. }
  569.  
  570. void
  571. fz_convert_color(fz_colorspace *ss, float *sv, fz_colorspace *ds, float *dv)
  572. {
  573.         if (ss == fz_device_gray)
  574.         {
  575.                 if ((ds == fz_device_rgb) || (ds == fz_device_bgr))
  576.                 {
  577.                         dv[0] = sv[0];
  578.                         dv[1] = sv[0];
  579.                         dv[2] = sv[0];
  580.                 }
  581.                 else if (ds == fz_device_cmyk)
  582.                 {
  583.                         dv[0] = 0;
  584.                         dv[1] = 0;
  585.                         dv[2] = 0;
  586.                         dv[3] = sv[0];
  587.                 }
  588.                 else
  589.                         fz_std_conv_color(ss, sv, ds, dv);
  590.         }
  591.  
  592.         else if (ss == fz_device_rgb)
  593.         {
  594.                 if (ds == fz_device_gray)
  595.                 {
  596.                         dv[0] = sv[0] * 0.3f + sv[1] * 0.59f + sv[2] * 0.11f;
  597.                 }
  598.                 else if (ds == fz_device_bgr)
  599.                 {
  600.                         dv[0] = sv[2];
  601.                         dv[1] = sv[1];
  602.                         dv[2] = sv[0];
  603.                 }
  604.                 else if (ds == fz_device_cmyk)
  605.                 {
  606.                         float c = 1 - sv[0];
  607.                         float m = 1 - sv[1];
  608.                         float y = 1 - sv[2];
  609.                         float k = MIN(c, MIN(m, y));
  610.                         dv[0] = c - k;
  611.                         dv[1] = m - k;
  612.                         dv[2] = y - k;
  613.                         dv[3] = k;
  614.                 }
  615.                 else
  616.                         fz_std_conv_color(ss, sv, ds, dv);
  617.         }
  618.  
  619.         else if (ss == fz_device_bgr)
  620.         {
  621.                 if (ds == fz_device_gray)
  622.                 {
  623.                         dv[0] = sv[0] * 0.11f + sv[1] * 0.59f + sv[2] * 0.3f;
  624.                 }
  625.                 else if (ds == fz_device_bgr)
  626.                 {
  627.                         dv[0] = sv[2];
  628.                         dv[1] = sv[1];
  629.                         dv[2] = sv[0];
  630.                 }
  631.                 else if (ds == fz_device_cmyk)
  632.                 {
  633.                         float c = 1 - sv[2];
  634.                         float m = 1 - sv[1];
  635.                         float y = 1 - sv[0];
  636.                         float k = MIN(c, MIN(m, y));
  637.                         dv[0] = c - k;
  638.                         dv[1] = m - k;
  639.                         dv[2] = y - k;
  640.                         dv[3] = k;
  641.                 }
  642.                 else
  643.                         fz_std_conv_color(ss, sv, ds, dv);
  644.         }
  645.  
  646.         else if (ss == fz_device_cmyk)
  647.         {
  648.                 if (ds == fz_device_gray)
  649.                 {
  650.                         float c = sv[0] * 0.3f;
  651.                         float m = sv[1] * 0.59f;
  652.                         float y = sv[2] * 0.11f;
  653.                         dv[0] = 1 - MIN(c + m + y + sv[3], 1);
  654.                 }
  655.                 else if (ds == fz_device_rgb)
  656.                 {
  657. #ifdef SLOWCMYK
  658.                         cmyk_to_rgb(NULL, sv, dv);
  659. #else
  660.                         dv[0] = 1 - MIN(sv[0] + sv[3], 1);
  661.                         dv[1] = 1 - MIN(sv[1] + sv[3], 1);
  662.                         dv[2] = 1 - MIN(sv[2] + sv[3], 1);
  663. #endif
  664.                 }
  665.                 else if (ds == fz_device_bgr)
  666.                 {
  667. #ifdef SLOWCMYK
  668.                         float rgb[3];
  669.                         cmyk_to_rgb(NULL, sv, rgb);
  670.                         dv[0] = rgb[2];
  671.                         dv[1] = rgb[1];
  672.                         dv[2] = rgb[0];
  673. #else
  674.                         dv[0] = 1 - MIN(sv[2] + sv[3], 1);
  675.                         dv[1] = 1 - MIN(sv[1] + sv[3], 1);
  676.                         dv[2] = 1 - MIN(sv[0] + sv[3], 1);
  677. #endif
  678.                 }
  679.                 else
  680.                         fz_std_conv_color(ss, sv, ds, dv);
  681.         }
  682.  
  683.         else
  684.                 fz_std_conv_color(ss, sv, ds, dv);
  685. }
  686.