-- ImagerAlphaDeviceImpl.mesa
-- Copyright © 1985 by Xerox Corporation. All rights reserved.
-- Mik Lamming - October 17, 1985 8:56:36 am PDT
Last edited by: Mik Lamming - October 21, 1985 4:28:56 pm PDT
-- Implements a3 ← a1 + a2 - a1*a2
-- v3 ← (v1*a1 + v2*a2 -v1*a1*a2) / a3
DIRECTORY
CountedVM USING [Handle, SimpleAllocate],
Imager USING [Context],
ImagerAlphaDevice USING [],
ImagerColorDefs USING [ConstantColor, ConstantColorImplRep],
ImagerColorPrivate USING [ConstantColorImpl, ConstantColorImplRep],
ImagerOps USING [PixelArrayFromPixelMaps],
ImagerFunctionDevice USING [ClientFunc, Create, MakeConstantColor],
ImagerPixelArray USING [FromAIS, Join, PixelArray],
ImagerPixelMap USING [Create, Fill, PixelMap],
ImagerSample USING [GetPointer, NewBuffer, PutSample, SampleBuffer, UnsafeSamples],
ImagerTransformation USING [Transformation],
Real USING [RoundC],
Rope USING [ROPE];
ImagerAlphaDeviceImpl: CEDAR PROGRAM
IMPORTS CountedVM, ImagerFunctionDevice, ImagerOps, ImagerPixelArray, ImagerPixelMap, ImagerSample, Real
EXPORTS ImagerAlphaDevice, ImagerColorDefs
~ BEGIN
ConstantColor: TYPE ~ ImagerColorDefs.ConstantColor;
ConstantColorImpl: TYPE ~ ImagerColorPrivate.ConstantColorImpl;
ConstantColorImplRep: PUBLIC TYPE ~ ImagerColorPrivate.ConstantColorImplRep;
Create: PUBLIC PROC [
devicePms: LIST OF ImagerPixelMap.PixelMap,
deviceToPixel: ImagerTransformation.Transformation ← NIL, -- transformation from device space
initialScale: REAL ← 1.0]
RETURNS [Imager.Context] ~ {
Length: PROC [l:LIST OF ImagerPixelMap.PixelMap] RETURNS [n:NAT] ~ {
IF l=NIL THEN RETURN [0] ELSE RETURN [Length[l.rest]+1]
};
IF Length[devicePms]#4 THEN ERROR; -- need 4 equally sized pixel maps!
RETURN [
ImagerFunctionDevice.Create[4, devicePms, deviceToPixel, initialScale, ApplyAlpha]
]
};
CreateAlphaTable: PROC [] ~ TRUSTED {
FOR i: CARDINAL IN [0..255] DO
FOR j: CARDINAL IN [0..255] DO
alphaTable[i*256+j] ← (i*j+128)/255;
ENDLOOP;
ENDLOOP;
};
AlphaTable: TYPE = LONG POINTER TO AlphaTableRec;
AlphaTableRec: TYPE = RECORD [
t: PACKED SEQUENCE COMPUTED CARDINAL OF [0..255]
];
handle: CountedVM.Handle ← CountedVM.SimpleAllocate[LONG[256]*(256/2)];
alphaTable: AlphaTable ← LOOPHOLE[handle.pointer];
ApplyAlpha: ImagerFunctionDevice.ClientFunc ~ TRUSTED {
alphaCSamples: ImagerSample.UnsafeSamples ← colorSamples.GetPointer[3, fMin, fSize];
alphaDSamples: ImagerSample.UnsafeSamples ← deviceSamples.GetPointer[3, fMin, fSize];
FOR i: NAT IN [0..2] DO
cSamples: ImagerSample.UnsafeSamples ← colorSamples.GetPointer[i, fMin, fSize];
dSamples: ImagerSample.UnsafeSamples ← deviceSamples.GetPointer[i, fMin, fSize];
FOR j: NAT IN[0..fSize) DO
alpha: NAT ← alphaTable[cSamples[j]*256+alphaSamples[j]];
notAlpha: NAT ← alphaTable[dSamples[j]*256+(255-alphaSamples[j])];
dSamples[j] ← MIN[alpha + notAlpha, 255];
ENDLOOP;
ENDLOOP;
};
MakeConstantColor: PUBLIC PROC [color: ImagerColorDefs.ConstantColor, alpha: REAL ← 1.0]
RETURNS [alphaColor: ConstantColor] ~ {
PixelFromIntensity: PROC[i: REAL, maxValue: CARDINAL] RETURNS[CARDINAL] ~ {
IF i<=0.0 THEN RETURN[0];
IF i>=1.0 THEN RETURN[maxValue];
RETURN[Real.RoundC[i*maxValue]];
};
oneSample: ImagerSample.SampleBuffer ← ImagerSample.NewBuffer[4, 1];
WITH color SELECT FROM
xcolor: ConstantColor => {
impl: ConstantColorImpl ~ xcolor.impl;
WITH impl: impl SELECT FROM
rgb => {
ImagerSample.PutSample[oneSample, 0, 0, PixelFromIntensity[impl.val.R,255]];
ImagerSample.PutSample[oneSample, 1, 0, PixelFromIntensity[impl.val.G,255]];
ImagerSample.PutSample[oneSample, 2, 0, PixelFromIntensity[impl.val.B,255]];
};
ENDCASE => {
grey:NAT ← PixelFromIntensity[impl.Y, 255];
ImagerSample.PutSample[oneSample, 0, 0, grey];
ImagerSample.PutSample[oneSample, 1, 0, grey];
ImagerSample.PutSample[oneSample, 2, 0, grey];
};
};
ENDCASE => ERROR; -- unknown color variant
ImagerSample.PutSample[oneSample, 3, 0, Real.RoundC[alpha*255]];
RETURN [ImagerFunctionDevice.MakeConstantColor[oneSample]]
};
MakePixelArrayFromAIS: PUBLIC PROC [
r,g,b: Rope.ROPE,
a: Rope.ROPENIL,
defaultAlpha: REAL ← 1.0
] RETURNS [pa: ImagerPixelArray.PixelArray] ~ {
Makes a pixel array suitable for Imager.SetSampledColor on this device.
If 'a' is defaulted then an AIS file the same size as 'r' is assumed. Its value will be defaultAlpha throughout.
paR, paG, paB, paA: ImagerPixelArray.PixelArray;
paR ← ImagerPixelArray.FromAIS[r];
paG ← ImagerPixelArray.FromAIS[g];
paB ← ImagerPixelArray.FromAIS[b];
IF a=NIL THEN {
pm: ImagerPixelMap.PixelMap ← ImagerPixelMap.Create[3, [0,0, paR.sSize, paR.fSize]];
pm.Fill[[0, 0, pm.sSize, pm.fSize], Real.RoundC[255*defaultAlpha], [null, null]];
paA ← ImagerOps.PixelArrayFromPixelMaps[LIST[pm], paR.m];
}
ELSE paA ← ImagerPixelArray.FromAIS[a];
RETURN [ImagerPixelArray.Join[LIST[paR, paG, paB, paA]]]
};
CreateAlphaTable[];
END.