DIRECTORY CountedVM USING [Handle, SimpleAllocate], Imager USING [Context], ImagerAlpha4Device USING [], ImagerColorDefs USING [ConstantColor, ConstantColorImplRep], ImagerColorPrivate USING [ConstantColorImpl, ConstantColorImplRep], ImagerDevice USING [Device], ImagerOps USING [PixelArrayFromPixelMaps], ImagerFunctionDevice USING [ClientFunc, Create, DeviceFromPixelMap, MakeConstantColor], ImagerPixelArray USING [FromAIS, Join, PixelArray], ImagerPixelMap USING [Create, Fill, GetPixel, PutPixel, PixelMap], ImagerSample USING [GetPointer, NewBuffer, PutSample, SampleBuffer, UnsafeSamples], ImagerTransformation USING [Transformation], IO, PixelMapOps, Real USING [RoundC], Rope USING [Cat, ROPE]; ImagerAlpha4DeviceImpl: CEDAR PROGRAM IMPORTS IO, CountedVM, ImagerFunctionDevice, ImagerOps, ImagerPixelArray, ImagerPixelMap, ImagerSample, PixelMapOps, Real, Rope EXPORTS ImagerAlpha4Device, 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] ] }; CreateDevice: PUBLIC PROC [ devicePms: LIST OF ImagerPixelMap.PixelMap, deviceToPixel: ImagerTransformation.Transformation _ NIL -- transformation from device space ] RETURNS [ImagerDevice.Device] ~ { 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.DeviceFromPixelMap[4, devicePms, deviceToPixel, ApplyAlpha] ] }; ApplyAlpha: ImagerFunctionDevice.ClientFunc ~ TRUSTED { aCSamples: ImagerSample.UnsafeSamples _ colorSamples.GetPointer[3, fMin, fSize]; aDSamples: ImagerSample.UnsafeSamples _ deviceSamples.GetPointer[3, fMin, fSize]; FOR j: NAT IN[0..fSize) DO aC: NAT _ aCSamples[j]; aD: NAT _ aDSamples[j]; aDSamples[j] _ aD + aC - mult8x8[aD*256+aC]; ENDLOOP; 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 newValue:CARDINAL _ dSamples[j] + cSamples[j] - mult8x8[dSamples[j]*256+aCSamples[j]]; dSamples[j] _ MIN[newValue, 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[alpha*impl.val.R,255]]; ImagerSample.PutSample[oneSample, 1, 0, PixelFromIntensity[alpha*impl.val.G,255]]; ImagerSample.PutSample[oneSample, 2, 0, PixelFromIntensity[alpha*impl.val.B,255]]; }; ENDCASE => { grey:NAT _ PixelFromIntensity[alpha*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]] }; MakeConstantAIS: PROC [file: Rope.ROPE, sSize, fSize:NAT, value:NAT _ 255] ~ { aData: PixelMapOps.AISData; aData.pixelMap _ ImagerPixelMap.Create[3, [0, 0, sSize, fSize]]; aData.bitmap _ FALSE; aData.comment _ NIL; aData.pixelMap.Fill[[0, 0, sSize, fSize], value, [null, null]]; aData.comment _ Rope.Cat[aData.comment, "Constant ", IO.PutFR["%g", IO.card[value]]]; PixelMapOps.StoreAIS[file, aData]; }; PremultiplyAIS: PROC [r, g, b, a, ra, ga, ba: Rope.ROPE] ~ { rData: PixelMapOps.AISData _ PixelMapOps.LoadAIS[r]; gData: PixelMapOps.AISData _ PixelMapOps.LoadAIS[g]; bData: PixelMapOps.AISData _ PixelMapOps.LoadAIS[b]; aData: PixelMapOps.AISData _ PixelMapOps.LoadAIS[a]; pmR, pmG, pmB, pmA: ImagerPixelMap.PixelMap; pmR _ rData.pixelMap; pmG _ gData.pixelMap; pmB _ bData.pixelMap; pmA _ aData.pixelMap; FOR row: NAT IN [0..pmA.sSize) DO FOR col: NAT IN [0..pmA.fSize) DO TRUSTED { alpha: NAT _ pmA.GetPixel[row, col]; pmR.PutPixel[row, col, mult8x8[pmR.GetPixel[row, col]*256+alpha]]; pmG.PutPixel[row, col, mult8x8[pmG.GetPixel[row, col]*256+alpha]]; pmB.PutPixel[row, col, mult8x8[pmB.GetPixel[row, col]*256+alpha]]; } ENDLOOP; ENDLOOP; rData.comment _ Rope.Cat[rData.comment, "\nCopy of ", r, "\nNormalised for ", a]; gData.comment _ Rope.Cat[gData.comment, "\nCopy of ", g, "\nNormalised for ", a]; bData.comment _ Rope.Cat[bData.comment, "\nCopy of ", g, "\nNormalised for ", a]; PixelMapOps.StoreAIS[ra, rData]; PixelMapOps.StoreAIS[ga, gData]; PixelMapOps.StoreAIS[ba, bData]; }; GetComment: PROC [name:Rope.ROPE] RETURNS [Rope.ROPE] ~ { RETURN[PixelMapOps.LoadAIS[name].comment]; }; MakePixelArrayFromAIS: PUBLIC PROC [ r,g,b,a: Rope.ROPE _ NIL ] RETURNS [pa: ImagerPixelArray.PixelArray] ~ { 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], 255, [null, null]]; paA _ ImagerOps.PixelArrayFromPixelMaps[LIST[pm], paR.m]; } ELSE paA _ ImagerPixelArray.FromAIS[a]; RETURN [ImagerPixelArray.Join[LIST[paR, paG, paB, paA]]] }; CreateMult8x8: PROC [] ~ TRUSTED { FOR i: CARDINAL IN [0..255] DO FOR j: CARDINAL IN [0..255] DO mult8x8[i*256+j] _ (i*j+128)/255; ENDLOOP; ENDLOOP; }; Mult8x8: TYPE = LONG POINTER TO Mult8x8Rec; Mult8x8Rec: TYPE = RECORD [ t: PACKED SEQUENCE COMPUTED CARDINAL OF [0..255] ]; handle: CountedVM.Handle _ CountedVM.SimpleAllocate[LONG[256]*(256/2)]; mult8x8: Mult8x8 _ LOOPHOLE[handle.pointer]; CreateMult8x8[]; END. ζ-- ImagerAlpha4DeviceImpl.mesa -- Copyright c 1985 by Xerox Corporation. All rights reserved. -- Mik Lamming - October 17, 1985 8:56:36 am PDT Last edited by: Mik Lamming - November 18, 1985 9:14:18 am PST -- Implements a3 _ a1 + a2 - a1*a2 -- v3 _ (v1*a1 + v2*a2 -v1*a1*a2) / a3 -- RGB are stored pre-multiples by alpha 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. Κ{˜Jšœ™Jšœ Οmœ1™?™0Icode™>K™—KšœΟg™"Kš œžœžœžœžœžœ™4K™(J˜K˜šΟk ˜ Jšœ Ÿœ˜)JšœŸœ ˜JšœŸœ˜JšœŸœ'˜