{"id":20011290,"url":"https://github.com/pdlporters/pdl-transform-color","last_synced_at":"2025-07-29T06:33:35.850Z","repository":{"id":46310378,"uuid":"82826373","full_name":"PDLPorters/PDL-Transform-Color","owner":"PDLPorters","description":null,"archived":false,"fork":false,"pushed_at":"2025-01-20T18:18:27.000Z","size":117,"stargazers_count":4,"open_issues_count":0,"forks_count":2,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-05-04T20:40:58.694Z","etag":null,"topics":["pdl","perl"],"latest_commit_sha":null,"homepage":"https://p3rl.org/PDL::Transform::Color","language":"Perl","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/PDLPorters.png","metadata":{"files":{"readme":"README.pod","changelog":"CHANGES","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2017-02-22T16:25:01.000Z","updated_at":"2025-01-20T18:18:25.000Z","dependencies_parsed_at":"2024-06-21T02:16:05.146Z","dependency_job_id":"6aaed9ef-d6c5-4731-b475-3c356e185e1c","html_url":"https://github.com/PDLPorters/PDL-Transform-Color","commit_stats":{"total_commits":75,"total_committers":5,"mean_commits":15.0,"dds":0.56,"last_synced_commit":"885c7a8840940acfb8d4750b7b15ea6edaa90e14"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/PDLPorters/PDL-Transform-Color","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PDLPorters%2FPDL-Transform-Color","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PDLPorters%2FPDL-Transform-Color/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PDLPorters%2FPDL-Transform-Color/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PDLPorters%2FPDL-Transform-Color/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PDLPorters","download_url":"https://codeload.github.com/PDLPorters/PDL-Transform-Color/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PDLPorters%2FPDL-Transform-Color/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267639569,"owners_count":24119780,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-29T02:00:12.549Z","response_time":2574,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["pdl","perl"],"created_at":"2024-11-13T07:25:09.959Z","updated_at":"2025-07-29T06:33:35.825Z","avatar_url":"https://github.com/PDLPorters.png","language":"Perl","funding_links":[],"categories":[],"sub_categories":[],"readme":"=head1 OVERVIEW\n\nThis module provides transformations for manipulating color.  This repository \nstores the history for the PDL::Transform::Color module on CPAN. \n\n=cut\n\n=encoding utf8\n\n=head1 NAME\n\nPDL::Transform::Color - Useful color system conversions for PDL\n\n=head1 SYNOPSIS\n\n     ### Shrink an RGB image with proper linear interpolation:\n     ### DEcode the sRGB image values, then interpolate, then ENcode sRGB\n     $im = rpic(\"big_colorimage.jpg\");\n     $im2 = $im-\u003einvert(t_srgb())-\u003ematch([500,500],{m=\u003e'g'})-\u003eapply(t_srgb());\n\n=head1 DESCRIPTION\n\nPDL::Transform::Color includes a variety of useful color conversion\ntransformations.  It can be used for simple hacks on machine-native\ncolor representations (RGB \u003c-\u003e HSV, etc.), for simple\nencoding/decoding of machine-native color representations such as\nsRGB, or for more sophisticated manipulation of absolute color\nstandards including large-gamut or perceptual systems.\n\nThe color transforms in this module can be used for converting between\nproper color systems, for gamma-converting pixel values, or for\ngenerating pseudocolor from one or two input parameters.  In addition\nto transforming color data between different representations, Several\nnamed \"color maps\" (also called \"color tables\") are provided.\n\nThe module uses linearized sRGB (lsRGB) as a fundamental color basis.\nsRGB is the standard color system used by most consumer- to mid-grade\ncomputer equipment, so casual users can use this color representation\nwithout much regard for gamuts, colorimetric standards, etc.\n\nMost of the transform generators convert from lsRGB to various\nother systems.  Notable simple ones are HSV (Hue, Saturation, Value),\nHSL (Hue, Saturation, Lightness), and CMYK (Cyan, Magenta, Yellow,\nblacK).\n\nIf you aren't familiar with PDL::Transform, you should read that POD\nnow, as this is a subclass of PDL::Transform.  Transforms represent\nand encapsulate vector transformations -- one- or two-way vector\nfunctions that may be applied, composed, or (if possible) inverted.\nThey are created through constructor methods that often allow\nparametric adjustment at creation time.\n\nIf you just want to \"manipulate some RGB images\" and not learn about\nthe esoterica of color representations, you can treat all the routines\nas working \"from RGB\" on the interval [0,1], and use C\u003ct_srgb\u003e to\nimport/export color images from/to \"24-bit color\" that your computer\nprobably expects.  If you care about the esoterica, read on.\n\nThe output transfer function for sRGB is nonlinear -- the luminance of\na pixel on-screen varies somewhat faster than the square of the input\nvalue -- which is inconvenient for blending, merging, and manipulating\ncolor.  Many common operations work best with a linear photometric\nrepresentation.  PDL::Transform::Color works with an internal model\nthat is a floating-point linear system representing pixels as\n3-vectors whose components are proportional to photometric brightness\nin the sRGB primary colors.  This system is called \"lsRGB\" within the\nmodule.\n\nNote that, in general, RGB representations are limited to a particular\nnarrow gamut of physically accessible values.  While the human eye has\nthree dominant colorimetric input channels and hence color can be\nrepresented as a 3-vector, the human eye does not cleanly separate the\nspectra responsible for red, green, and blue stimuli.  As a result, no\ntrio of physical primary colors (which must have positive-definite\nspectra and positive-definite overall intensities) can represent every\nperceivable color -- even though they form a basis of color space.\n\nBut in digital representation, there is no hard limit on the values\nof the RGB vectors -- they can be negative or arbitrarily large.  This\npermits representation of out-of-gamut values using negative or\nover-unity intensities.  So floating-point lsRGB allows you to\nrepresent literally any color value that the human eye can perceive,\nand many that it can't.  This is useful even though many such colors\ncan't be rendered on a monitor.  For example, you can change between\nseveral color representations and not be limited by the formal gamut\nof each representation -- only by the final export standard.\n\nThree major output formats are supported: sRGB (standard \"24-bit\ncolor\" with the industry standard transfer function); bRGB (bytescaled\nRGB with a controllable gamma function (default 2.2, matching the\naverage gamma value of most CRTs and calibrated flat monitors); or\nCMYK (direct linear inversion of the RGB values, with byte\nscaling). These are created by applying the transforms C\u003ct_srgb\u003e,\nC\u003ct_brgb\u003e, and C\u003ct_cmyk\u003e, respectively, to an lsRGB color triplet.\n\nThe C\u003ct_srgb\u003e export routine will translate represented colors in\nfloating-point lsRGB to byte-encoded sRGB (or, if inverted, vice\nversa), using the correct (slightly more complicated than gamma\nfunctions) nonlinear scaling.  In general, you can use C\u003c!t_srgb\u003e to\nimport existing images you may have found lying around the net;\nmanipulate their hue, etc.; and re-export with C\u003ct_srgb\u003e.\n\nIf you prefer to work with direct gamma functions or straight\nscaling, you can import/export from/to byte values with C\u003ct_brgb\u003e\ninstead.  For example, to export a color in the CIE RGB system\n(different primaries than sRGB), use C\u003ct_brgb() x t_ciergb\u003e.\n\nThere are also some pseudocolor transformations, which convert a\nsingle data value to normalized RGB.  These transformations are\nC\u003ct_pc\u003e for photometric (typical scientific) values and C\u003ct_pcp\u003e for\nperceptual (typical consumer camera) values.  They are described\nbelow, along with a collection of named pseudocolor maps that are\nsupplied with the module.\n\n=head1 OVERVIEW OF COLOR THEORY\n\nBecause of the biophysics of the human eye, color is well represented\nas a 3-vector of red, green, and blue brightness values representing\nbrightness in the long, middle, and short portions of the visible\nspectrum.  However, the absorption/sensitivity bands overlap\nsignificantly, therefore no physical light (of any wavelength) can\nform a proper \"primary color\" (orthonormal basis element) of this\nspace.  While any vector in color space can be represented as a linear\nsum of three independent basis vectors (\"primary colors\"), there is no\nsuch thing as a negative intensity and therefore any tricolor\nrepresentation of the color space is limited to a \"gamut\" that can be\nformed by I\u003cpositive\u003e linear combinations of the selected primary colors.\n\nSome professional color representations (e.g. 5- and 7-color dye\nprocesses) expand this gamut to better match the overall spectral\nresponse of the human eye, at the cost of over-determining color\nvalues in what is fundamentally a 3-space.\n\nRGB color representations require the specification of particular\nprimary colors that represent particular spectral profiles.  The\nchoice of primaries depends on the technical solution being used for\nI/O.  The most universal \"standard\" representation is the CIE RGB\nstandard developed in 1931 by the Commission Internationale de\nl'Eclairage (CIE; International Commission on Illumination).  The 1931\nCIE RGB system is also called simply CIERGB by many sources.  It uses\nprimary wavelengths of 700nm (red), 546.1 nm (green), and 435.8 nm\n(blue).\n\nThe most universal \"computer\" representation is the sRGB standard\ndefined by Anderson et al.  (1996), which uses on slightly different\nprimary colors than does the 1931 CIE RGB standard.  This is because\nsRGB is based on the colorimetric output of color television phosphors\nin CRTs, while CIE RGB was developed based on easily lab-reproducible\nspectra.\n\nThe C\u003cPDL::Transform::Color\u003e transformations are all relative to the\nsRGB color basis.  Negative values are permitted, allowing\nrepresentation of all colors -- possible or impossible.\n\nCIE defined several other important color systems: first, an XYZ\nsystem based on nonphysical primaries X, Y, and Z that correspond to\nred, green, and blue, respectively. The XYZ system can represent all\ncolors detectable to the human eye with positive-definite intensities\nof the \"primaries\": the necessary negative intensities are hidden in\nthe formal spectrum of each of the primaries.  The Y primary of this\nsystem corresponds closely to green, and is used by CIE as a proxy for\noverall luminance.\n\nThe CIE also separated \"chrominance\" and \"luminance\" signals, in a\nseparate system called \"xyY\", which represents color as sum-normalized\nvectors \"x=X/(X+Y+Z), \"y=Y/(X+Y+Z)\", and \"z=Z/(X+Y+Z)\".  By construction,\nx+y+z=1, so \"x\" and \"y\" alone describe the color range of the system, and\n\"Y\" stands in for overall luminance.\n\nA linear RGB system is specified exactly by the chrominance (CIE XYZ\nor xyY) coordinates of the three primaries, and a white point\nchrominance.  The white point chrominance sets the relative scaling\nbetween the brightnesses of the primaries to achieve a color-free\n(\"white\") luminance.  Different systems with the same R, G, B primary\nvectors can have different gains between those colors, yielding a\nslightly different shade of color at the R=G=B line.  This \"white\"\nreference chrominance varies across systems, with the most common\n\"white\" standard being CIE's D65 spectrum based on a 6500K black body\n-- but CIE, in particular, specifies a large number of white\nstandards, and some systems use none of those but instead specify CIE\nXYZ values for the white point.\n\nSimilarly, real RGB systems typically use dynamic range compression\nvia a nonlinear transfer function which is most typically a \"gamma\nfunction\".  A built-in database tracks about 15 standard named\nsystems, so you can convert color values between them.  Or you can\nspecify your own system with a standard hash format (see C\u003cget_rgb\u003e).\n\nProvision exists for converting between different RGB systems with\ndifferent primaries and different white points, by linearizing and\nthen scaling.  The most straightforward way to use this module to\nconvert between two RGB systems (neither of which is lsRGB) is to\ninverse-transform one to lsRGB, then transform forward to the other.\nThis is accomplished with the C\u003ct_shift_rgb\u003e transform.\n\nMany other representations than RGB exist to separate chromatic\nvalue from brightness.  In general, these can be divided into polar\ncoordinates that represent hue as a single value divorced from the rgb\nbasis, and those that represent it as a combination of two values like\nthe 'x' and 'y' of the CIE xyY space.  These are all based on the\nMunsell and Ostwald color systems, which were worked out at about the\nsame time as the CIE system.  Both Ostwald and Munsell worked around\nthe start of the 20th century pioneered colorimetric classification.\n\nOstwald worked with quasi-linear representations of chromaticity as a\n2-vector independent of brightness; these representations relate to\nCIERGB, CIEXYZ, and related systems via simple geometric projection;\nthe CIE xyY space is an example.  The most commonly used variant of\nxyY is CIELAB, a perceptual color space that separates color into a\nperceived lightness parameter L, and separate chromaticities 'a' and\n'b'.  CIELAB is commonly used by graphic artists and related\nprofessions, because it is an absolute space like XYZ (so that each\nLAB value corresponds to a particular perceivable color), and because\nthe Cartesian norm between vectors in LAB space is approximately\nproportional to perceived difference between the corresponding colors.\nThe system is thus useful for communicating color values precisely\nacross different groups or for developing perceptually-uniform display\nmaps for generated data.  The L, A, and B coordinates are highly\nnonlinear to approximately match the typical human visual system.\n\nOther related systems include YUV, YPbPr, and YCbCr -- which are used\nfor representing color for digital cinema and for video transmission.\n\nMunsell developed a color system based on separating the \"hue\" of a\ncolor into a single value separate from both its brightness and\nsaturation level.  This system is closely related to cylindrical polar\ncoordinates in an RGB space, with the center of the cylinder on top of\nthe line of values corresponding to neutral shades from \"black\"\nthrough \"grey\" to \"white\".\n\nTwo simple Munsell-like representations that work within the gamut of\na particular RGB basis are HSL and HSV.  Both of these systems are\nloose representations that are best defined relative to a particular\nRGB system. They are both designed specifically to represent an entire\nRGB gamut with a quasi-polar coordinate system, and are based on\nhexagonal angle -- i.e. they are not exactly polar in nature.\n\nHSL separates \"Hue\" and \"Saturation\" from \"Lightness\".  Hue represents\nthe spectral shade of the color as a direction from the central white\nreference line through RGB space: the R=G=B line.  Saturation is a\nnormalized chromaticity measuring fraction of the distance from the\nwhite locus to the nearest edge of the RGB gamut at a particular hue\nand lightness.  Lightness is an approximately hue- independent measure\nof total intensity.  Deeply objectively \"saturated\" colors are only\naccessible at L=0.5; the L=0.5 surface includes all the additive and\nsubtractive primary colors of the RGB system.  Darker colors are\nless-saturated shades, while brighter colors fade to pastels.\n\nHSV is similar to HSL, but tracks only the brightest component among\nthe RGB triplet as \"Value\" rather than the derived \"Lightness\".  As a\nresult, highly saturated HSV values have lower overall luminance than\nunsaturated HSV values with the same V, and the V=1 surface includes\nall the primary and secondary colors of the parent RGB system.  This system takes\nadvantage of the of the \"Helmholtz-Kolhrausch effect\" that\nI\u003cperceived\u003e brightness increases with saturation, so V better\napproximates perceived brightness at a given hue and saturation, than\ndoes L.\n\nModern display devices generally produce physical brightnesses that\nare proportional not to their input signal, but to a nonlinear\nfunction of the input signal.  The most common nonlinear function is a\nsimple power law (\"gamma function\"): output is approximately\nproportional to the \"gamma\" power of the input.  Raising a signal\nvalue to the power \"1/gamma\" is C\u003cgamma-encoding\u003e it, and raising it\nto the power \"gamma\" is C\u003cgamma-decoding\u003e it.\n\nThe sRGB 24-bit color standard specifies a slightly more complicated\ntransfer curve, that consists of a linear segment spliced onto a\nhorizontally-offset power law with gamma=2.4.  This reduces\nquantization noise for very dark pxels, but approximates an overall\npower law with gamma=2.2.  Hence, C\u003ct_brgb\u003e (which supports general\npower law transfer functions) defaults to an output gamma of 2.2, but\nC\u003ct_srgb\u003e yields a more accurate export transfer in typical use.  The\ngamma value of 2.2 was selected in the early days of the television\nera, to approximately match the perceptual response of the human eye,\nand for nearly 50 years cathode-ray-tube (CRT) displays were\nspecifically designed for a transfer gamma of 2.2 between applied\nvoltage at the electron gun input stage and luminance (luminous energy\nflux) at the display screen.\n\nIncidentally, some now-obsolete display systems (early MacOS systems\nand Silcon Graphics displays) operated with a gamma factor of 1.8,\nslightly less nonlinear than the standard.  This derives from early\nuse of checkerboard (and similar) pixelwise dithering to achieve a\nhigher-bit-depth color palette than was otherwise possible, with early\nequipment.  The display gamma of 2.2 interacted with direct dithering\nof digital values in the nonlinear space, to produce an effective gamma\ncloser to 1.8 than 2.2.\n\n\n=head1 STANDARD OPTIONS\n\n=over 3\n\n=item gamma\n\nThis is a gamma correction exponent used to get physical luminance\nvalues from the represented RGB values in the source RGB space.  Most\ncolor manipulation is performed in linear (gamma=1) representation --\ni.e. if you specify a gamma to a conversion transform, the normalized\nRGB values are B\u003cdecoded\u003e to linear physical values before processing\nin the forward direction, or B\u003cencoded\u003e after processing in the\nreverse direction.\n\nFor example, to square the normalized floating-point lsRGB values\nbefore conversion to bRGB, use C\u003ct_brgb(gamma=\u003e2)\u003e.  The \"gamma\"\noption specifies that the desired brightness of the output device\nvaries as the square of the pixel value in the stored data.\n\nSince lsRGB is the default working space for most transforms, you\ndon't normally need to specify C\u003cgamma\u003e -- the default value of 1.0\nis correct.\n\nContrariwise, the C\u003ct_brgb\u003e export transform has a C\u003cdisplay_gamma\u003e option\nthat specifies the gamma function for the output bytes.  Therefore,\nC\u003c\u003c t_brgb(display_gamma=\u003e2) \u003e\u003e square-roots the data before export (so that\nsquaring them would yield numbers proportional to the desired luminance\nof a display device).\n\nThe C\u003cgamma\u003e option is kept for completeness, but unless you know it's\nwhat you really want, you probably don't actually want it: instead,\nyou should consider working in a linear space and decoding/encoding\nthe gamma of your import/export color space only as you read in or write\nout values.  For example, generic images found on the internet are\ntypically in the sRGB system, and can be imported to lsRGB via the\nC\u003c!t_srgb\u003e transform or exported with C\u003ct_srgb\u003e -- or other\ngamma-corrected 24-bit color systems can be handled directly with\nC\u003ct_brgb\u003e and its C\u003cdisplay_gamma\u003e option.\n\n=back\n\n=head1 FUNCTIONS\n\n=cut\n=head2 t_gamma\n\n=for usage\n\n    $t = t_gamma($gamma);\n\n=for ref\n\nThis is an internal generator that is used to implement the standard\nC\u003cgamma\u003e parameter for all color transforms.  It is exported as well\nbecause many casual users just want to apply a gamma curve to existing\ndata rather than doing anything more rigorous.\n\nIn the forward direction, C\u003ct_gamma\u003e applies/decodes the gamma correction\nindicated -- e.g. if the C\u003c$gamma\u003e parameter at generation time is 2,\nthen the forward direction squares its input, and the inverse direction\ntakes the square root (encodes the gamma correction).\n\nGamma correction is implemented using a sign-tolerant approach:\nall values have their magnitude scaled with the power law, regardless\nof the sign of the value.\n\n=cut\n=head2 t_brgb\n\n=for usage\n\n    $t = t_brgb();\n\n=for ref\n\nConvert lsRGB (normalized to [0,1]) to byte-scaled RGB ( [0,255] ).\nBy default, C\u003ct_brgb\u003e prepares byte values tuned for a display gamma\nof 2.2, which approximates sRGB (the standard output color coding for\nmost computer displays).  The difference between C\u003ct_brgb\u003e and\nC\u003ct_srgb\u003e in this usage is that C\u003ct_srgb\u003e uses the actual\nspliced-curve approximation specified in the sRGB standard, while\nC\u003ct_brgb\u003e uses a simple gamma law for export.\n\nC\u003ct_brgb\u003e accepts the following options, all of which may be abbreviated:\n\n=over 3\n\n=item gamma (default 1)\n\nIf set, this is a gamma-encoding value for the original lsRGB, which\nis decoded before the transform.\n\n=item display_gamma (default 2.2)\n\nIf set, this is the gamma of the display for which the output is\nintended.  The default compresses the brightness vector before output\n(taking approximately the square root).  This matches the \"standard\ngamma\" applied by MacOS and Microsoft Windows displays, and approximates\nthe sRGB standard.  See also C\u003ct_srgb\u003e.\n\n=item clip (default 1)\n\nIf set, the output is clipped to [0,256) in the forward direction and\nto [0,1] in the reverse direction.\n\n=item byte (default 1)\n\nIf set, the output is converted to byte type in the forward direction.\nThis is a non-reversible operation, because precision is lost in the\nconversion to bytes. (The reverse transform always creates a floating\npoint value, since lsRGB exists on the interval [0,1] and an integer\ntype would be useless.)\n\n=back\n\n=cut\n=head2 t_srgb\n\n=for ref\n\nConverts lsRGB (the internal floating-point base representation) to\nsRGB - the typical RGB encoding used by most computing devices.  Since\nmost computer terminals use sRGB, the representation's gamut is well\nmatched to most computer monitors.\n\nsRGB is a spliced standard, rather than having a direct gamma\ncorrection.  Hence there is no way to adjust the output gamma.  If you\nwant to do that, use C\u003ct_brgb\u003e instead.\n\nC\u003ct_srgb\u003e accepts the following options, all of which may be abbreviated:\n\n=over 3\n\n=item gamma (default 1)\n\nIf set, this is a gamma-encoding value for the original lsRGB, which\nis decoded before the transform.\n\n=item byte (default 1)\n\nIf set, this causes the output to be clipped to the range [0,255] and rounded\nto a byte type PDL (\"24-bit color\").  (The reverse transform always creates\na floating point value, since lsRGB exists on the interval [0,1] and an integer\ntype would be useless.)\n\n=item clip (default 0)\n\nIf set, this causes output to be clipped to the range [0,255] even if the\nC\u003cbyte\u003e option is not set.\n\n=back\n\n=cut\n=head2 t_pc and t_pcp\n\n=for ref\n\nThese two transforms implement  a general purpose pseudocolor\ntransformation.  You input a monochromatic value (zero active dims)\nand get out an RGB value (one active dim, size 3).  Because the most\ncommon use case is to generate sRGB values, the default output is sRGB\n-- you have to set a flag for lsRGB output, for example if you want to\nproduce output in some other system by composing t_pc with a color\ntransformation.\n\nC\u003ct_pc\u003e generates pseudocolor transforms (\"color maps\") with\na photometric interpretation of the input:  the input data are\nconsidered to be proportional to some kind of measured luminance\nor similar physical parameter.   This produces \"correct\" renderings\nof scenes captured by scientific cameras and similar instrumentation.\n\nC\u003ct_pcp\u003e generates pseudocolor transforms (\"color maps\") with a\nperceptual interpretation of the input: the input data are considered\nto be proportional to the *perceptual* variation desired across the\ndisplay.  This produces \"correct\" renderings of many non-luminant\ntypes of data, such as temperature, Doppler shift, frequency plots,\netc.\n\nBoth C\u003ct_pc\u003e and C\u003ct_pcp\u003e generate transforms based on a collection\nof named transformations stored in an internal database (the global\nhash ref C\u003c$PDL::Transform::Color::pc_tab\u003e).  The transformations\ncome in two basic sorts:  quasi-photometric transformations,\nwhich use luminance as the dominant varying parameter; and non-\nphotometric transformations, which use hue or saturation as the\ndominant varying parameter.  Only the photometric transformations\nget modified by C\u003ct_pc\u003e vs C\u003ct_pcp\u003e -- for example, C\u003ct_pcp('rainbow')\u003e\nwill yield the same transform as C\u003ct_pc('rainbow')\u003e.\n\nSome of the color transformations are \"split\" and intended for display of signed\ndata -- for example, the C\u003cdop\u003e transformation fades red-to-white-to-blue and\nis intended for display of Doppler or similar signals.\n\nNOTE: C\u003ct_pc\u003e and C\u003ct_pcp\u003e work BACKWARDS from most of the\ntransformations in this package: they convert FROM a data value TO sRGB\nor lsRGB.\n\nThere are options to adjust input gamma and the domain of the\ntransformation (e.g. if your input data are on [0,1000] instead of\n[0,1]).\n\nIf you feed in no arguments at all, either C\u003ct_pc\u003e or C\u003ct_pcp\u003e will\nlist a collection of named pseudocolor transformations that work, on\nthe standard output.\n\nOptions accepted are:\n\n=over 3\n\n=item gamma (default 1) - presumed encoding gamma of the input\n\nThe input is *decoded* from this gamma value.  1 treats it as linear\nin luminance.\n\n=item lsRGB (default 0) - produce lsRGB output instead of sRGB.\n\n(this may be abbreviated \"l\" for \"linear\")\n\n=item domain - domain of the input; synonym for irange.\n\n=item irange (default [0,1]) - input range of the data\n\nInput data are by default clipped to [0,1] before application of the\ncolor map.  Specifying an undefined value causes the color map to be\nautoscaled to the input data, e.g. C\u003cir=\u003e[0,undef]\u003e causes the color map\nto be scaled from 0 to the maximum value of the input.  For full\nautoscaling, use C\u003cir=\u003e[]\u003e.\n\n=item combination (default 0) - recombine r,g,b post facto\n\nThis option allows you to perturb maps you like by mixing up r, g, and\nb after all the other calculations are done.  You feed in a number\nfrom 0 to 5.  If it's nonzero, you get a different combination of the\nthree primaries.  You can mock this up more compactly by appending\nC\u003c-Cn\u003e to the (possibly abbreviated) name of the table.  (Replace\nthe 'n' with a number).\n\nFor example, if you specify the color table C\u003csepia\u003e or C\u003csepia-c0\u003e you'll\nget the sepiatone color table.  If you specify C\u003csepia-c5\u003e you'll get\nalmost the exact same color table as C\u003cgrepia\u003e.\n\n=back\n\nYou can abbreviate color table names with unique abbreviations.\nTables currently accepted, and their intended uses are:\n\n=over 3\n\n=item QUASI-PHOTOMETRIC PSEUDOCOLOR MAPS FOR NORMAL USE\n\n=over 3\n\n=item  grey, gray, or mono (photometric)\n\nSimple monochrome.\n\n=item sepia, blepia, grepia, vepia, ryg - sepiatone and variants\n\nThese use color scaling to enhance contrast in a simple luminance\ntransfer.  C\u003csepia\u003e is a black-brown-white curve reminiscent of sepia\nink.  The others are similar, but emphasize different primary colors.\nThe 'ryg' duplicates sepiatone, but with green highlights to increase\ncontrast in near-saturated parts of an image.\n\n=item heat\n\nThis black-red-yellow-white is reminiscent of blackbody curves\n(but does not match them rigorously).\n\n=item pm3d, voy\n\n\"pm3d\" is the default color table for Gnuplot.  It's a colorblind-friendly,\nhighly saturated table with horrible aesthetics but good contrast throughout.\n\"voy\" is violet-orange-yellow.  It's a more aesthetically pleasing colorblind-\nfriendly map with a ton of contrast throughout the range.\n\n=item ocean\n\ndeep green through blue to white\n\n=item spring, summer, autumn, winter\n\nThese are reminiscent of the \"seasonal\" colors provided by MatLab.  The\n\"spring\" is horrendous but may be useful for certain aesthetic presentations.\nSummer and Winter are similar to the sepia-like tables, but with different\ncolor paths.  Autumn is similar to heat, but less garish.\n\n=back\n\n=item SPLIT PSEUDOCOLOR MAPS FOR SIGNED QUANTITIES\n\n=over 3\n\n=item dop, dop1, dop2, dop3\n\nThese are various presentations of signed information, originally\nintended to display Doppler shift.  They are all quasi-photometric\nand split.\n\n=item vbg\n\nThis is a violet-black-green signed fade useful for non-Doppler\nsigned quantities.  Quasi-photometric and split.\n\n=back\n\n=item NON-PHOTOMETRIC PSEUDOCOLOR MAPS\n\n=over 3\n\n\n=item rainbow\n\nColors of the rainbow, red through \"violet\" (magenta)\n\n=item wheel\n\nThe full \"color wheel\", including the controversial magenta-to-red segment\n\n=back\n\n=back\n\n\n=cut\n=head2 t_cieXYZ, t_xyz\n\n=for ref\n\nThe C\u003ct_cieXYZ\u003e transform (also C\u003ct_xyz\u003e, which is a synonym)\nconverts the module-native lsRGB to the CIE XYZ representation.  CIE\nXYZ is a nonphysical RGB-style system that minimally represents every\nphysical color it is possible for humans to perceive in steady\nillumination.  It is related to sRGB by a linear transformation\n(i.e. matrix multiplication) and forms the basis of many other color\nsystems (such as CIE xyY).\n\nCIE XYZ values are defined in such a way that they are positive\ndefinite for all human-perceptible colors, at the cost that the\nprimaries are nonphysical (they correspond to no possible spectral\ncolor)\n\nC\u003ct_ciexyz\u003e accepts the following options:\n\n=over 3\n\n=item gamma (default 1)\n\nThis is taken to be a coded gamma value in the original lsRGB, which\nis decoded before conversion to the CIE XYZ system.\n\n=item rgb_system (default undef)\n\nIf present, this must be either the name of an RGB system or an RGB system\ndescriptor hash as described in C\u003ct_shift_rgb\u003e.  If none is specified, then\nthe standard linearized sRGB used by the rest of the module is assumed.\n\n=item use_system_gamma (default 0)\n\nIf this flag is set, and C\u003crgb_system\u003e is set also, then the RGB side\nof the transform is taken to be gamma-encoded with the default value for\nthat RGB system.  Unless you explicitly specify an RGB system (with a name\nor a hash), this flag is ignored.\n\n=back\n\n=cut\n=head2 t_rgi\n\n=for ref\n\nConvert RGB to RG chroma with a separate intensity channel.\n\nNote that intensity is just the average of the R, G, and B values.\nIf you want perceptible luminance, use t_rgl or t_ycbcr instead.\n\n=cut\n=head2 t_xyy and t_xyY\n\n=for ref\n\nConvert from sRGB to CIE xyY.  The C\u003cxyY\u003e system is part of the CIE\n1931 color specification.  Luminance is in the 2 coordinate, and\nchrominance x and y are in the 0 and 1 coordinates.\n\nThis is the coordinate system in which \"chromaticity diagrams\" are\nplotted.  It is capable of representing every illuminant color that\ncan be perceived by the typical human eye, and also many that can't,\nwith positive-definite coordinates.\n\nMost of the domain space (which runs over [0-1] in all three dimensions)\nis inaccessible to most displays, because RGB gamuts are generally\nsmaller than the actual visual gamut, which in turn is a subset of the\nactual xyY data space.\n\n=cut\n=head2 t_cielab or t_lab\n\n=for usage\n\n    $t = t_cielab();\n\n=for ref\n\nConvert RGB to CIE Lab colors.  C\u003cLab\u003e stands for Lightness,\n\"a\", and \"b\", representing the overall luminance detection and\ntwo opponent systems (a: red/green, and b:yellow/blue) in the human\neye.  Lab colors are approximately perceptually uniform:  they're\nmapped using a nonlinear transformation involving cube roots.  Lab\nhas the property that Euclidean distances of equal size in the space\nyield approximately equal perceptual shifts in the represented color.\n\nLightness runs 0-100, and the a and b opponent systems run -100 to +100.\n\nThe Lab space includes the entire CIE XYZ gamut and many \"impossible colors\".\nthat cannot be represented directly with physical light.  Many of these\n\"impossible colors\" (also \"chimeric colors\") can be experienced directly\nusing visual fatigue effects, and can be classified using Lab.\n\nLab is easiest to convert directly from XYZ space, so the C\u003ct_lab\u003e constructor\nreturns a compound transform of C\u003ct_xyz2lab\u003e and C\u003ct_xyz\u003e.\n\n=head2 t_xyz2lab\n\n=for usage\n\n    $t = t_xyz2lab();\n\n=for ref\n\nConverts CIE XYZ to CIE Lab.\n\n=cut\n=head2 t_cmyk\n\nconverts rgb to cmyk in the most straightforward way (by subtracting\nRGB values from unity).\n\nCMYK and other process spaces are very complicated; this transform\npresents only a relatively simple conversion that does not take into\naccount ink gamut variation or many other effects.\n\nThere *is* a provision for halftone gamma correction: \"htgamma\", which\nworks exactly like the rgb gamma correction but is applied to the CMYK\noutput.\n\nOptions:\n\n=over 3\n\n=item gamma (default 1)\n\nThe standard gamma affecting the RGB cube\n\n=item htgamma (default 1)\n\nA \"halftone gamma\" that is suitable for non-wash output processes\nsuch as halftoning. it acts on the CMYK values themselves.\n\n=item byte (default 0)\n\nIf present, the CMYK side is scaled to 0-255 and converted to a byte type.\n\n=back\n\n=cut\n=head2 t_hsl and t_hsv\n\n=for usage\n\n    $rgb = $hsl-\u003einvert($t_hsl());\n\n=for ref\n\nHSL stands for Hue, Saturation, Lightness.  It's not an absolute\ncolor space, simply derived from each RGB (by default, linearized\nsRGB).  it has the same gamut as the host RGB system.  The coordinates\nare hexagonal on the (RYGCBM) hexagon, following the nearest face of\nthe (diagonally sliced) RGB cube.\n\nHSL is a double-cone system, so iso-L surfaces are close to the plane\nperpendicular to the double-diagonal white/illuminant line R=G=B.\nThis has the effect of reducing saturation at high lightness levels,\nbut maintains luminosity independent of saturation.  Maximum\nsaturation occurs when S=1 and L=0.5; at higher values of L, colors\ngrow less saturated and more pastel, so that L follows total\nluminosity of the output.\n\nHSV is a stacked-cone system: iso-V surfaces are parallel to the\nbright faces of the RGB cube, so maximal bright saturation occurs when\nS=1 and V=1.  This means that output luminosity drops with saturation,\nbut due to Helmholtz-Kolrausch effect (linking saturation to apparent\nbrightness) the I\u003cperceived\u003e brightness is less S-dependent: V follows\ntotal I\u003capparent brightness\u003e of the output, though output luminosity\ndrops with S.\n\nYou can represent out-of-gamut values in either system, by using\nS values greater than unity, or \"illegal\" V or L values.\n\nHue, Saturation, and (Lightness or Value) each run from 0 to 1.\n\nBy default, the hue value follows a sin**4 scaling along each side of\nthe RYGCBM hexagon.  This softens the boundaries near the edges of the\nRGB cube, giving a better peceptual \"color-wheel\" transition between\nhues.  There is a flag to switch to the linear behavior described in,\ne.g., the Wikipedia article on the HSV system.\n\nYou can encode the Lightness or Value with a gamma value (\"lgamma\") if\ndesired.\n\nOptions:\n\n=over 3\n\n=item gamma (default 1)\n\nTreat the base RGB as gamma-encoded (default 1 is linear)\n\n=item lgamma (default 1)\n\nTreat the L coordinate as gamma-encoded (default 1 is linear).\n\n=item hsv (default 0 if called as \"t_hsl\", 1 if called as \"t_hsv\")\n\nSets which of the HSL/HSV transform is to be used.\n\n=item hue_linear (default 0)\n\nThis flag determines how the hue (\"angle\") is calculated.  By default,\na sin**4 scaling is used along each branch of the RYGCBM hexagon,\nto soften the perceptual effects at the corners.  If you set this flag,\nthen the calculated \"hue\" is linear along each branch of the hexagon,\nto match (e.g.) the Wikipedia definition.\n\n=back\n\n=cut\n=head2 t_shift_illuminant\n\n=for ref\n\nC\u003ct_new_illuminant\u003e shifts a color from an old RGB system to a new one\nwith a different white point.  It accepts either a PDL containing a\nCIE xyY representation of the new illuminant, or a name of the new illuminant,\nand some options.\n\nBecause this is shifting RGB to RGB in the same representation, gamma\ntransformations get re-encoded afterward: if you use, for example,\nC\u003c\u003c gamma=\u003e2 \u003e\u003e, then the RGB values are squared, then transformed, then\nsquare-rooted.\n\nOptions are:\n\n=over 3\n\n=item gamma (default=1)\n\nIf present, this is the gamma coefficient for the representation of\nboth the source and destination RGB spaces.\n\n=item from (default=\"D65\")\n\nIf present, this is the xyY or name of the OLD illuminant.  The default\nis D65, the illuminant for sRGB (and therefore lsRGB as well).\n\n=item basis (default=\"sRGB\")\n\nIf present, this needs to be either \"sRGB\" or \"XYZ\" (case insensitive).\nIf it's sRGB, the input and output are treated as standard lsRGB coordinates.\nIf it's XYZ, then the input and output are in CIE XYZ coordinates.\n\n=item method (default=\"Bradford\")\n\nThis can be \"Bradford\", \"Von Kries\", \"XYZ\", or a 3x3 matrix Ma (see\nC\u003chttp://www.brucelindbloom.com/index.html?WorkingSpaceInfo.html\u003e)\n\n=back\n\n=cut\n=head2 t_shift_rgb\n\n=for usage\n\n  $t = t_shift_rgb(\"NTSC\",{from=\u003e\"sRGB\"});\n\n=for ref\n\nShifts the primary color basis of the lsrgb TO the destination system.\nMost named RGB systems have an associated preferred gamma, but that is\nignored by default: the RGB values are treated as if they are all\nlinear representations.  You can specify EITHER the name of the system\nOR the specific RGB parameters for that system.\n\nThe RGB parameters, if you specify them, need to be in the form of a\nhash ref.  The hash keys should be the same as would be returned by\nC\u003cPDL::Transform::Color::get_rgb\u003e.  All the keys must be present,\nexcept for gamma (which is ignored).\n\nAlternatively, you can use the name of a known system.  These are listed in the\ndocumentation for C\u003cPDL::Transform::Color::get_rgb\u003e.\n\nC\u003ct_shift_rgb\u003e takes several options.\n\n=over 3\n\n=item gamma (default 1)\n\nThe input triplets are assumed to be encoded with this gamma function.\nThe default assumes linear representation.\n\n=item ogamma (default gamma)\n\nThe output triplets are assumed to need encoding with this gamma function.\n\n=item use_system_gammas (default 0)\n\nThis overrides the settings of \"gamma\" and \"ogamma\", and\nencodes/decodes according to the original system.\n\n=item wp_method (default undef)\n\nThis is the whitepoint shift method used to change illuminant value between\nsystems with different whitepoints.  See C\u003ct_shift_illuminant\u003e for an\nexplanation.\n\n=item from (default \"sRGB\")\n\nThis is the RGB system to convert from, in the same format as the\nsystem to convert to (names or a hash ref as described).\n\n=back\n\n=cut\n=head2 PDL::Transform::Color::xyy_from_D\n\n=for usage\n\n     $xyy = PDL::Transform::Color::xyy_from_D($D_value)\n\n=for ref\n\nThis utility routine generates CIE xyY system colorimetric values for\nstandard CIE D-class illuminants (e.g., D50 or D65).  The illuminants are\ncalculated from a standard formula and correspond to black body\ntemperatures between 4,000K and 250,000K.  The D value is the\ntemperature in K divided by 100, e.g. broad daylight is D65,\ncorresponding to 6500 Kelvin.\n\nThis is used for calculating standard reference illuminants, to convert\nRGB values between illuminants.\n\nFor example, sRGB uses a D65 illuminant, but many other color standards\nrefer to a D50 illuminant.\n\nThe colorimetric values are xy only; the Y coordinate can be specified via\nan option, or defaults to 0.5.\n\nThis routine is mainly used by C\u003cxyy_from_illuminant\u003e, which handles most\nof the CIE-recognized standard illuminant sources including the D's.\n\nSee C\u003ct_xyy\u003e for a description of the CIE xyY absolute colorimetric system.\n\nC\u003cxyy_from_D\u003e accepts the following options:\n\n=over 3\n\n=item Y - the Y value of the output xyY coordinate\n\n=back\n\n=cut\n=head2 PDL::Transform::Color::xyy_from_illuminant\n\n=for usage\n\n     $xyy = PDL::Transform::Color::xyy_from_illuminant($name)\n\n=for ref\n\nThis utility routine generates CIE xyY system colorimetric values for\nall of the standard CIE illuminants.  The illuminants are looked up in\na table populated from the CIE publication I\u003cColorimetry\u003e, 3rd\nedition.\n\nThe illuminant of a system is equivalent to its white point -- it is\nthe location in xyY absolute colorimetric space that corresponds to\n\"white\".\n\nCIE recognizes many standard illuminants, and (as of 2017) is in the\nprocess of creating a new set -- the \"L\" series illuminants -- that is\nmeant to represent LED lighting.\n\nProper treatment of an illuminant requires a full spectral representation,\nwhich the CIE specifies for each illuminant.  Analysis of that spectrum is\na major part of what CIE calls \"Color rendering index (CRI)\" for a particular\nlight source.  PDL::Transform::Color is a strictly tri-coordinate system\nand does not handle the nuances of spectral effects on CRI.  In effect,\nall illuminants are treated as having a CRI of unity (perfect).\n\nIlluminants that are understood are:\n\n=over 3\n\n=item * a 3-PDL in CIE xyY coordinates\n\n=item * a CIE standard name\n\n=back\n\nThe CIE names are:\n\n=over 3\n\n=item A - a gas-filled tungsten filament lamp at 2856K\n\n=item B - not supported (deprecated by CIE)\n\n=item C - early daylight simulant, replaced by the D[n] sources\n\n=item D[n] - Blackbody radiation at 100[n] Kelvin (e.g. D65)\n\n=item F[n] - Fluorescent lights of various types (n=1-12 or 3.1-3.15)\n\n=item HP[n] - High Pressure discharge lamps (n=1-5)\n\n=item L[n] - LED lighting (not yet supported)\n\n=back\n\n=cut\n=head2 PDL::Transform::Color::get_rgb\n\n=for usage\n\n    my $rgb_hash = get_rgb( $name );\n\n=for ref\n\nC\u003cPDL::Transform::Color::get_rgb\u003e is an internal routine that retrieves a set of\nRGB primary colors from an internal database.  There are several named RGB systems,\nwith different primary colors for each.  The primary colors are represented as\nCIE xyY values in a returned hash ref.\n\nThe return value is a hash ref with the following fields:\n\n=over 3\n\n=item gamma - the specified gamma of that RGB system (or 2.2, for sRGB)\n\n=item w_name - the name of the illuminant / white-point for that system\n\n=item w - the xyY value of the illuminant / white-point for that system\n\n=item r - the xyY value of the red primary color at unit intensity\n\n=item g - the xyY value of the green primary color at unit intensity\n\n=item b - the xyY value of the blue primary color at unit intensity\n\n=back\n\nAs of 1.007, because this module now uses L\u003cPDL::Graphics::ColorSpace\u003e\nfor some calculations, the hash ref will also include fields used by\nthat module.\n\nRecognized RGB system names are:\n\n=over 3\n\n=item Adobe - Adobe's 1998 RGB, intended to encompass nearly all of the CMYK gamut (gamma=2.2, white=D65)\n\n=item Apple - Apple's display standard from c. 1990 - c. 2010 (gamma=1.8, white=D65)\n\n=item Best - Wide-gamut RGB developed by Don Hutcheson (L\u003cwww.hutchcolor.com\u003e) (gamma=2.2, white=D50)\n\n=item Beta - Bruce Lindbloom's optimized ultra-wide-gamut RGB (gamma=2.2, white=D50)\n\n=item Bruce - Bruce Fraser's conservative-gamut RGB space for 8-bit editing (gamma=2.2, white=D65)\n\n=item BT 601 - ITU-R standard BT.601 (used for MPEG \u0026 SDTV) (gamma=2.2, white=D65)\n\n=item BT 709 - ITU-R standard BT.709 (used for HDTV) (gamma=2.2, white=D65)\n\n=item CIE - CIE 1931 calibrated color space (based on physical emission lines) (gamma=2.2, white=E)\n\n=item ColorMatch - quasi-standard from c.1990 -- matches Radius Pressview CRT monitors.  (gamma=1.8, white=D50)\n\n=item Don 4 - wide-gamut D50 working space gets the Ektachrome color gamut (gamma=2.2, white=D50)\n\n=item ECI v2 - RGB standard from the European Color Initiative (gamma=1, white=D50)\n\n=item Ekta PS5 - developed by Joseph Holms (L\u003cwww.josephholmes.com\u003e) for scanned Ektachrome slides (gamma=2.2, white=D50)\n\n=item NTSC - National Television System Committee (U.S. analog TV standard) (gamma=2.2, white=C)\n\n=item PAL - Phase Alternating Line (U.K. analog TV standard) (gamma = 2.2, white=D65)\n\n=item ProPhoto - Wide gamut from Kodak, designed for photo output. (gamma=1.8, white=D60)\n\n=item ROMM - Synonym for ProPhoto (gamma=1.8, white=D60)\n\n=item SECAM - Séquentiel de Couleur À Mémoire (French analog TV standard) (gamma=2.2, white=D65)\n\n=item SMPTE-C - Soc. Motion Pict. \u0026 TV Engineers (current U.S. TV standard) (gamma=2.2, white=D65)\n\n=item sRGB - Standard for consumer computer monitors (gamma~2.2, white=D65)\n\n=item wgRGB - Wide Gamut RGB (gamma=2.2, white=D50)\n\n=back\n\n=cut\n=head1 AUTHOR\n\nCopyright 2017, Craig DeForest (deforest@boulder.swri.edu).  This\nmodule may be modified and distributed under the same terms as PDL\nitself.  The module comes with NO WARRANTY.\n\n=cut\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpdlporters%2Fpdl-transform-color","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpdlporters%2Fpdl-transform-color","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpdlporters%2Fpdl-transform-color/lists"}