#FEATURE by cg
authorClaus Gittinger <cg@exept.de>
Sun, 27 Aug 2017 20:00:15 +0200
changeset 8111 c20fb44519e3
parent 8110 19a15da94872
child 8112 0825f3c6a0cb
#FEATURE by cg class: Image added: #chromaBlueOfYCbCr: #chromaRedOfYCbCr: #lumaOfYCbCr: changed: #rgbFromValue:
Image.st
--- a/Image.st	Sun Aug 27 19:59:56 2017 +0200
+++ b/Image.st	Sun Aug 27 20:00:15 2017 +0200
@@ -13957,6 +13957,98 @@
     "Created: 22.10.1997 / 23:52:40 / cg"
 !
 
+chromaBlueOfYCbCr:pixel
+    "if the receiver is an YCbCr-image:
+     return the blue-chroma (Cb) component, scaled to (0 .. 1)"
+
+    |cbBits "{ Class: SmallInteger }"
+     crBits "{ Class: SmallInteger }"
+     s      "{ Class: SmallInteger }"|
+
+    photometric == #YCbCr ifTrue:[ 
+        samplesPerPixel == 3 ifTrue:[
+            "/ assume that the Y bits are the leftMost bits 
+            cbBits := bitsPerSample at:2.
+            cbBits == 0 ifTrue:[^ 0].
+            crBits := bitsPerSample at:3.
+
+            s := (1 bitShift:cbBits) - 1.
+
+            ^ 1.0 / s * ((pixel rightShift:crBits) bitAnd:(1 bitShift:cbBits)-1)
+        ].
+    ].
+    self subclassResponsibility
+
+    "Created: / 26-08-2017 / 22:09:31 / cg"
+!
+
+chromaRedOfYCbCr:pixel
+    "if the receiver is an YCbCr-image:
+     return the red-chroma (Cr) component, scaled to (0 .. 1)"
+
+    |crBits    "{ Class: SmallInteger }"
+     s         "{ Class: SmallInteger }"|
+
+    samplesPerPixel >= 3 ifTrue:[
+        "/ assume that the red bits are the leftMost bits
+
+        crBits := bitsPerSample at:3.
+        crBits == 0 ifTrue:[^ 0].
+
+        s := (1 bitShift:crBits) - 1.
+
+        ^ 1.0 / s * (pixel bitAnd:(1 bitShift:crBits)-1)
+    ].
+
+    self subclassResponsibility
+
+    "
+     (self basicNew
+        bitsPerSample:#(8 8 8);
+        photometric:#YCbCr;
+        samplesPerPixel:3;
+        yourself
+     ) chromaRedOfYCbCr: 16r10107F
+
+     (self basicNew
+        bitsPerSample:#(8 8 8);
+        photometric:#YCbCr;
+        samplesPerPixel:3;
+        yourself
+     ) chromaRedOfYCbCr: 16r1010FF
+
+     (self basicNew
+        bitsPerSample:#(8 8 8);
+        photometric:#YCbCr;
+        samplesPerPixel:3;
+        yourself
+     ) chromaBlueOfYCbCr: 16r107F10
+
+     (self basicNew
+        bitsPerSample:#(8 8 8);
+        photometric:#YCbCr;
+        samplesPerPixel:3;
+        yourself
+     ) chromaBlueOfYCbCr: 16r10FF10
+
+     (self basicNew
+        bitsPerSample:#(8 8 8);
+        photometric:#YCbCr;
+        samplesPerPixel:3;
+        yourself
+     ) lumaOfYCbCr: 16r7F1010
+
+     (self basicNew
+        bitsPerSample:#(8 8 8);
+        photometric:#YCbCr;
+        samplesPerPixel:3;
+        yourself
+     ) lumaOfYCbCr: 16rFF1010
+    "
+
+    "Created: / 26-08-2017 / 22:11:31 / cg"
+!
+
 colorFromValue:pixelValue
     "given a pixel value, return the corresponding color.
      Pixel values start with 0.
@@ -14223,6 +14315,23 @@
     "Created: 22.4.1997 / 14:12:02 / cg"
 !
 
+lumaOfYCbCr:pixel
+    "if the receiver is an YCbCr-image:
+     return the luma (Y) component, scaled to (0 .. 1)"
+
+    photometric == #YCbCr ifTrue:[ 
+        samplesPerPixel == 3 ifTrue:[
+            "/ assume that the Y bits are the leftMost bits 
+            (#[8 8 8] isSameSequenceAs:bitsPerSample)ifTrue:[
+                ^ 1.0 / 255 * ((pixel bitShift:-16) bitAnd:16rFF)
+            ]
+        ].
+    ].
+    self subclassResponsibility
+
+    "Created: / 26-08-2017 / 22:06:36 / cg"
+!
+
 magentaComponentOfCMY:pixel
     "if the receiver is a cmy-image:
      return the magenta component scaled to a percentage (0 .. 100) of a pixelValue."
@@ -14506,7 +14615,7 @@
      The implementation below is generic and slow
      - this method is typically redefined in subclasses."
 
-    |p maxPixel clr r g b c m y k|
+    |p maxPixel clr r g b c m y k cb cr|
 
     p := photometric.
     p isNil ifTrue:[
@@ -14567,9 +14676,40 @@
         ^ (Color cyan:c magenta:m yellow:y) rgbValue.
     ].
 
+    p == #YCbCr ifTrue:[
+        y := self lumaOfYCbCr:pixelValue.
+        cb := self chromaBlueOfYCbCr:pixelValue.
+        cr := self chromaRedOfYCbCr:pixelValue.
+        ^ (Color luma:y chromaBlue:cb chromaRed:cr) rgbValue. 
+    ].
+    
     self error:'invalid (unsupported) photometric'
 
-    "Modified: / 22-08-2017 / 18:31:36 / cg"
+    "
+     (self basicNew
+        bitsPerSample:#(8 8 8);
+        photometric:#YCbCr;
+        samplesPerPixel:3;
+        yourself
+     ) rgbFromValue: 16r7F1010
+
+     (self basicNew
+        bitsPerSample:#(8 8 8);
+        photometric:#YCbCr;
+        samplesPerPixel:3;
+        yourself
+     ) rgbFromValue: 16rFF1010
+
+     (self basicNew
+        bitsPerSample:#(8 8 8);
+        photometric:#YCbCr;
+        samplesPerPixel:3;
+        yourself
+     ) rgbFromValue: 16rFF0000
+    "
+
+    "Modified: / 26-08-2017 / 20:56:49 / cg"
+    "Modified (comment): / 26-08-2017 / 22:18:14 / cg"
 !
 
 usedColors