ColorToYCbCr() and vice versa lazarus / 39-Graphics ---------------------------------------------------------------------- prof7bit · 2021-09-28 16:57 I have functions for converting TColor to and from YCbCr (YUV) with the profiles ITU-R BT.601, BT.709 and BT.2020. See below: Are there any objections to trying to get these functions into the GraphUtil unit where the other color space conversions are? This color space is especially useful when trying to determine whether a text color has a good contrast from the background (is readable) and also to adjust its brightness in YCbCr while maintaining its color, for example to automatically adapt syntax highlighter colors or plot colors when the user switches from a light to a dark theme, or stuff like that. This is what I am experimenting with currently. HLS is not usable for this (I tried it) because the luminance is not weighted by the human perception, while YCbCr has this weighting built in, first experiments using this color space are very promising. Here is my code (might still be subject to change): Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i { Conversion to and from YCbCr   Copyright (C) 2021 Bernd Kreuss prof7bit@gmail.com   This library is free software; you can redistribute it and/or modify it  under the terms of the GNU Library General Public License as published by  the Free Software Foundation; either version 2 of the License, or (at your  option) any later version with the following modification:   As a special exception, the copyright holders of this library give you  permission to link this library with independent modules to produce an  executable, regardless of the license terms of these independent modules,and  to copy and distribute the resulting executable under terms of your choice,  provided that you also meet, for each linked independent module, the terms  and conditions of the license of that module. An independent module is a  module which is not derived from or based on this library. If you modify  this library, you may extend this exception to your version of the library,  but you are not obligated to do so. If you do not wish to do so, delete this  exception statement from your version.   This program is distributed in the hope that it will be useful, but WITHOUT  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License  for more details.   You should have received a copy of the GNU Library General Public License  along with this library; if not, write to the Free Software Foundation,  Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA.}unit YCbCr; {$mode ObjFPC}{$H+} interface uses  Graphics; type  TItuRec = (    ituBT601,  // ITU-R BT.601, full range    ituBT709,  // ITU-R BT.709, full range    ituBT2020  // ITU-R BT.2020, full range  ); procedure ColorToYCbCr(C: TColor; out Y, Cb, Cr: Byte; Mode: TItuRec);function YCbCrToColor(Y, Cb, Cr: Byte; Mode: TItuRec): TColor; implementationuses  Math; type  TCoeff = array[0..10] of Double; var  BT601: TCoeff;  BT709: TCoeff;  BT2020: TCoeff; procedure ColorToYCbCr(C: TColor; out Y, Cb, Cr: Byte; constref K: TCoeff);var  RGB: LongInt;  R, G, B: Byte;begin  RGB := ColorToRGB(C);  R := Red(RGB);  G := Green(RGB);  B := Blue(RGB);  Y  := EnsureRange(Round(K[0] * R + K[1] * G + K[2] * B), 0, 255);  Cb := EnsureRange(Round(K[3] * R + K[4] * G +  0.5 * B + 128), 0, 255);  Cr := EnsureRange(Round( 0.5 * R + K[5] * G + K[6] * B + 128), 0, 255);end; function YCbCrToColor(Y, Cb, Cr: Byte; constref K: TCoeff): TColor;var  Cb0, Cr0: Integer;  R, G, B: Byte;begin  Cb0 := Cb - 128;  Cr0 := Cr - 128;  R := EnsureRange(Round(Y + K[7] * Cr0              ), 0, 255);  G := EnsureRange(Round(Y + K[8] * Cr0 + K[9]  * Cb0), 0, 255);  B := EnsureRange(Round(Y              + K[10] * Cb0), 0, 255);  Result := RGBToColor(R, G, B);end; procedure ColorToYCbCr(C: TColor; out Y, Cb, Cr: Byte; Mode: TItuRec);begin  case Mode of    ituBT601: ColorToYCbCr(C, Y, Cb, Cr, BT601);    ituBT709: ColorToYCbCr(C, Y, Cb, Cr, BT709);    ituBT2020: ColorToYCbCr(C, Y, Cb, Cr, BT2020);  end;end; function YCbCrToColor(Y, Cb, Cr: Byte; Mode: TItuRec): TColor;begin  case Mode of    ituBT601: Result := YCbCrToColor(Y, Cb, Cr, BT601);    ituBT709: Result := YCbCrToColor(Y, Cb, Cr, BT709);    ituBT2020: Result := YCbCrToColor(Y, Cb, Cr, BT2020);  end;end; procedure InitYCbCrCoef(out K: TCoeff; Kr, Kg: Double);begin                               //  example values for BT601  K[0] := Kr;                         //  0.299  K[1] := Kg;                       //  0.587  K[2] := 1 - Kr - Kg; // Kb          //  0.114  K[3] := -Kr / (2 * (Kr + Kg));      // -0.1687  K[4] := -Kg / (2 * (Kr + Kg));      // -0.3313  K[5] := -Kg / (2 * (Kg + K[2]));    // -0.4187  K[6] := -K[2] / (2 * (Kg + K[2]));  // -0.0813  K[7] := 2 * (Kg + K[2]);          //  1.402  K[8] := -Kr * 2 * (Kg + K[2]) / Kg; // -0.7141  K[9] := -K[2] * 2 * (Kr + Kg) / Kg; // -0.3441  k[10] := 2 * (Kr + Kg);             //  1.772end; initialization  InitYCbCrCoef(BT601, 0.299, 0.587);  InitYCbCrCoef(BT709, 0.2126, 0.7152);  InitYCbCrCoef(BT2020, 0.2627, 0.6780);end. ---------------------------------------------------------------------- wp · 2021-09-28 17:08 Hmmm, I'm not a friend of adding more and more rarely used stuff into the LCL which gets fatter and fatter with every release. Does Delphi have it? There are special color routines in package mbColorLib (including YCbCr). Isn't this enough? ---------------------------------------------------------------------- prof7bit · 2021-09-28 17:19 Quote from: wp on September 28, 2021, 07:08:42 pmHmmm, I'm not a friend of adding more and more rarely used stuff into the LCL which gets fatter and fatter with every release. Does Delphi have it? There are special color routines in package mbColorLib (including YCbCr). Isn't this enough? It would be part of some other functionality I am also working on which aims to automate the choosing of readable colors for syntax highlighters that work the same way on light and dark themes. I'm not a friend of requiring 42 external packages for every absolutely basic function when I have smart linking. The batteries should be included, this is the key to success! And the limitations of Delphi should not be the benchmark by which we judge the omission of functionality in its much more powerful successor Lazarus. And no, mbColorLib does not have YCbCr according to its documentation. ---------------------------------------------------------------------- wp · 2021-09-28 17:40 Quote from: prof7bit on September 28, 2021, 07:19:22 pmIt would be part of some other functionality I am also working on which aims to automate the choosing of readable colors for syntax highlighters that work the same way on light and dark themes. Using it in the highlighters is a good reason to include the routines. But many things look exciting when a project starts, but are abandoned when progress gets tough. So, let's talk about it when your highlighter modification is finished - it's a matter of a few minutes to copy&paste this code into the GraphUtils unit, or to include the YCbCr unit as it is. Quote from: prof7bit on September 28, 2021, 07:19:22 pmAnd no, mbColorLib does not have YCbCr according to its documentation. You are free to fix it. ---------------------------------------------------------------------- AlexTP · 2021-09-28 18:26 Agreed that we don't need the bloat, so it may be a unit in Lazarus CCR. Agree that if you disappear, no one will fix those functions. ---------------------------------------------------------------------- prof7bit · 2021-09-29 08:07 Quote from: Alextp on September 28, 2021, 08:26:04 pmAgreed that we don't need the bloat, so it may be a unit in Lazarus CCR. Are you trying to provoke me into some kind of inappropriate reaction by needlessly insulting my code? Why are you starting your disagreement with "Agreed", is this passive agressive behavior representative for the "friendly community" here? Is it intentional to drive contributors away, because you already have too many contributors? What exactly is bloated in my implementation, can you please point this out? Quote from: Alextp on September 28, 2021, 08:26:04 pmAgree that if you disappear, no one will fix those functions. Are you telling me that a simple matrix multiplication will degrade over time so that it needs fixing after a while? And then you won't find anybody anymore who can still remember the lost art of linear algebra? It was a mistake to ask here in this forum instead of talking to actual devs. This thread can be closed. Unsubscribing. ---------------------------------------------------------------------- Bart · 2021-09-29 08:32 Quote from: prof7bit on September 29, 2021, 10:07:18 amIt was a mistake to ask here in this forum instead of talking to actual devs. You already talked to the devs: see reply #3. So, we (the devs) are not saying it will never be in Lazarus, but we would like to see how it eventuelly will be used in the highlighters. And, please don't be offended. Bart ---------------------------------------------------------------------- AlexTP · 2021-09-29 09:40 Sorry that I insulted your code, I didn't want that. "Bloat" was bad word from my side.