Hi all,

I propose to default to straight RGBA color space in FreeType. This is
especially important before the next FreeType release 2.10 with
CPAL/COLR support. I will quote from PNG documentation for the
overarching reason:

"PNG also uses only unassociated alpha, wherein the actual gray or
color values are stored unchanged and are only affected by the alpha
channel at display time. The alternative is associated or
premultiplied alpha, in which the pixel values are effectively
precomposited against a black background; although this allows
slightly faster software compositing, it amounts to a lossy
transformation of the image data and was therefore rejected in the
design of PNG."

For example, the loss of precision in premultiplied data prevents
blending with gamma correction.

The only reason why FreeType has not made this choice yet is
uncompressed CBDT data, which comes premultiplied. Correct me if I am
wrong in all other instances in PNG-compressed CBDT and in CPAL the
bitmap data are straight.

So as a first step in this direction. the attached patch introduces
straight FT_PIXEL_MODE_RGBA and removes premultiplication from
PNG-encoded CBDT data, thus faithfully transmitting the data to the
user.

The second step is to default tt_face_colr_blend_layer and
FT_Bitmap_Blend to FT_PIXEL_MODE_RGBA, with the least data loss. The
third step is to implement gamma corrected blending.

Please comment with your support or objection.

Alexei
diff --git a/include/freetype/freetype.h b/include/freetype/freetype.h
index 60e9b15..27cf8b7 100644
--- a/include/freetype/freetype.h
+++ b/include/freetype/freetype.h
@@ -3084,16 +3084,18 @@ FT_BEGIN_HEADER
    *     font format.
    *
    *     [Since 2.5] Load embedded color bitmap images.  The resulting color
-   *     bitmaps, if available, will have the @FT_PIXEL_MODE_BGRA format,
-   *     with pre-multiplied color channels.  If the flag is not set and
-   *     color bitmaps are found, they are converted to 256-level gray
-   *     bitmaps, using the @FT_PIXEL_MODE_GRAY format.
+   *     bitmaps, if available, will have the either straight
+   *     @FT_PIXEL_MODE_RGBA or premultiplied @FT_PIXEL_MODE_BGRA format,
+   *     i.e., FreeType provides original image data without modifications.
+   *     If the flag is not set and color bitmaps are found, they are
+   *     converted to 256-level gray bitmaps, using the @FT_PIXEL_MODE_GRAY
+   *     format.
    *
    *     [Since 2.10] If the glyph index contains an entry in the face's
    *     `COLR' table with a `CPAL' palette table (as defined in the
    *     OpenType specification), make @FT_Render_Glyph provide a default
    *     blending of the color glyph layers associated with the glyph index,
-   *     using the same bitmap format as embedded color bitmap images.  This
+   *     using straight @FT_PIXEL_MODE_RGBA bitmap format.  This
    *     is mainly for convenience; for full control of color layers use
    *     @FT_Get_Color_Glyph_Layer and FreeType's color functions like
    *     @FT_Palette_Select instead of setting FT_LOAD_COLOR for rendering
diff --git a/include/freetype/ftimage.h b/include/freetype/ftimage.h
index a3fa0b6..5c6d713 100644
--- a/include/freetype/ftimage.h
+++ b/include/freetype/ftimage.h
@@ -176,12 +176,23 @@ FT_BEGIN_HEADER
    *
    *   FT_PIXEL_MODE_BGRA ::
    *     [Since 2.5] An image with four 8-bit channels per pixel,
-   *     representing a color image (such as emoticons) with alpha
+   *     representing a color image (emoticon or emoji) with alpha
    *     channel.  For each pixel, the format is BGRA, which means, the
    *     blue channel comes first in memory.  The color channels are
    *     pre-multiplied and in the sRGB colorspace.  For example, full
    *     red at half-translucent opacity will be represented as
-   *     `00,00,80,80', not `00,00,FF,80'.  See also @FT_LOAD_COLOR.
+   *     `00,00,80,80', not `00,00,FF,80'.  This format is only used in
+   *     uncompressed CBDT tables.  See also @FT_LOAD_COLOR.
+   *
+   *   FT_PIXEL_MODE_RGBA ::
+   *     [Since 2.10] An image with four 8-bit channels per pixel,
+   *     representing an sRGB color image (emoticon or emoji) with alpha
+   *     channel.  For each pixel, the format is straignt RGBA, which means,
+   *     color channels are not premultiplied by alpha and the red channel
+   *     comes first in memory.  For example, full red at half-translucent
+   *     opacity will be represented as `FF,00,00,80'.  This format is used
+   *     in PNG-compressed CBDT tables and chosen as FreeType default for
+   *     other color font formats.  See also @FT_LOAD_COLOR.
    */
   typedef enum  FT_Pixel_Mode_
   {
@@ -193,6 +204,7 @@ FT_BEGIN_HEADER
     FT_PIXEL_MODE_LCD,
     FT_PIXEL_MODE_LCD_V,
     FT_PIXEL_MODE_BGRA,
+    FT_PIXEL_MODE_RGBA,
 
     FT_PIXEL_MODE_MAX      /* do not remove */
 
diff --git a/src/sfnt/pngshim.c b/src/sfnt/pngshim.c
index 0674bda..599379a 100644
--- a/src/sfnt/pngshim.c
+++ b/src/sfnt/pngshim.c
@@ -49,7 +49,7 @@
   }
 
 
-  /* Premultiplies data and converts RGBA bytes => BGRA. */
+  /* Defunct. Premultiplies data and converts RGBA bytes => BGRA. */
   static void
   premultiply_data( png_structp    png,
                     png_row_infop  row_info,
@@ -178,9 +178,9 @@
       unsigned int    blue  = base[2];
 
 
-      base[0] = (unsigned char)blue;
+      base[0] = (unsigned char)red;
       base[1] = (unsigned char)green;
-      base[2] = (unsigned char)red;
+      base[2] = (unsigned char)blue;
       base[3] = 0xFF;
     }
   }
@@ -279,7 +279,7 @@
          ( (FT_UInt)x_offset + metrics->width  > map->width ||
            (FT_UInt)y_offset + metrics->height > map->rows  ||
            pix_bits != 32                                   ||
-           map->pixel_mode != FT_PIXEL_MODE_BGRA            ) )
+           map->pixel_mode != FT_PIXEL_MODE_RGBA            ) )
     {
       error = FT_THROW( Invalid_Argument );
       goto Exit;
@@ -332,7 +332,7 @@
 
       map->width      = metrics->width;
       map->rows       = metrics->height;
-      map->pixel_mode = FT_PIXEL_MODE_BGRA;
+      map->pixel_mode = FT_PIXEL_MODE_RGBA;
       map->pitch      = (int)( map->width * 4 );
       map->num_grays  = 256;
 
@@ -396,19 +396,10 @@
     if ( metrics_only )
       goto DestroyExit;
 
-    switch ( color_type )
+    switch ( color_type == PNG_COLOR_TYPE_RGB )
     {
-    default:
-      /* Shouldn't happen, but fall through. */
-
-    case PNG_COLOR_TYPE_RGB_ALPHA:
-      png_set_read_user_transform_fn( png, premultiply_data );
-      break;
-
-    case PNG_COLOR_TYPE_RGB:
       /* Humm, this smells.  Carry on though. */
       png_set_read_user_transform_fn( png, convert_bytes_to_data );
-      break;
     }
 
     if ( populate_map_and_metrics )
_______________________________________________
Freetype-devel mailing list
Freetype-devel@nongnu.org
https://lists.nongnu.org/mailman/listinfo/freetype-devel

Reply via email to