去年公司的設計作 Flash Banner 時,遇到一個奇怪的問題
大量使用 Filter, Blend Mode, Alpha, Mask 之後
(這是不良的習慣,請勿仿效)
最終渲染的結果圖片上會出現奇怪的斑點

可明明用的都是 Hard Light,圖片也都是高亮色系
怎麼反而出現暗色斑點呢?

經過反覆測試,拆解之後
發現主要會出現問題的是 Hard Light, Overlay 這兩種混色模式
當一個 MovieClip 套用這兩種混色模式,且後面的背景是純白色時
前景再疊上一層帶有 Alpha 50% 左右的色塊
就很容易產生問題

以下則是使用 Flex 4 MXML 作更進一步的測試程式:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
  xmlns:s="library://ns.adobe.com/flex/spark"
  xmlns:mx="library://ns.adobe.com/flex/mx">
 <fx:Library>
  <fx:Definition name="HRule">
   <s:Line width="100%">
    <s:stroke><s:SolidColorStroke color="#000000" /></s:stroke>
   </s:Line>
  </fx:Definition>
  <fx:Definition name="Border">
   <s:Rect>
    <s:stroke>
     <s:SolidColorStroke color="#000000" alpha="0.7" weight="4" joints="bevel" />
    </s:stroke>
   </s:Rect>
  </fx:Definition>
 </fx:Library>
 
 <fx:Metadata>
  [SWF(width="500", height="400")]
 </fx:Metadata>
 
 <fx:Declarations>
  <s:ArrayList id="blendModes">
   {[BlendMode.NORMAL, BlendMode.HARDLIGHT,
    BlendMode.OVERLAY, BlendMode.ADD,
    BlendMode.ALPHA, BlendMode.DARKEN,
    BlendMode.DIFFERENCE, BlendMode.ERASE,
    BlendMode.INVERT, BlendMode.LAYER,
    BlendMode.LIGHTEN, BlendMode.MULTIPLY,
    BlendMode.SCREEN, BlendMode.SUBTRACT]}
  </s:ArrayList>
  <s:ArrayList id="opaqueBgColors">
   {[{label: "Null", data: null},
    {label: "#000000", data: 0x000000},
    {label: "#808080", data: 0x808080},
    {label: "#FFFFFF", data: 0xFFFFFF},
    {label: "#FF0000", data: 0xFF0000},
    {label: "#00FF00", data: 0x00FF00},
    {label: "#0000FF", data: 0x0000FF}]}
  </s:ArrayList>
 </fx:Declarations>
 
 <s:layout>
  <s:HorizontalLayout verticalAlign="middle" horizontalAlign="center" gap="40" />
 </s:layout>
 
 <!-- Graphics Group -->
 <s:Group id="graphicsGroup" width="200" height="250" alpha="{alphaSlider.value}" blendMode="normal">
 
  <s:Group id="underGroup" top="24" bottom="44" left="4" right="4"
     opaqueBackground="{underOpaqueBgList.selectedItem.data}"
     blendMode="{underBlendModeList.selectedItem ? underBlendModeList.selectedItem : 'normal'}">
   <s:Rect top="0" bottom="0" left="0" right="0">
    <s:fill>
     <s:LinearGradient rotation="90">
      <s:GradientEntry color="#FF0000" ratio="0" />
      <s:GradientEntry color="#FFFF00" ratio=".15" />
      <s:GradientEntry color="#00FF00" ratio=".3" />
      <s:GradientEntry color="#00FFFF" ratio=".45" />
      <s:GradientEntry color="#0000FF" ratio=".60" />
      <s:GradientEntry color="#FF00FF" ratio=".75" />
      <s:GradientEntry color="#FF0000" ratio=".9" />
      <s:GradientEntry color="#FFFFFF" ratio=".90001" />
      <s:GradientEntry color="#FFFFFF" ratio=".95" />
      <s:GradientEntry color="#000000" ratio=".95001" />
      <s:GradientEntry color="#000000" ratio="1" />
     </s:LinearGradient>
    </s:fill>
   </s:Rect>
  </s:Group>
 
  <fx:Border top="20" bottom="40" left="0" right="0" />
  <s:Label top="30" left="-20" text="Under Graphic (Colour Gradient)" rotation="-90" />
 
  <s:Group top="4" bottom="4" left="24" right="44" cacheAsBitmap="{cacheAsBitmapCk.selected}">
   <s:Rect top="0" bottom="0" left="0" right="0">
    <s:fill>
     <s:LinearGradient>
      <s:GradientEntry color="#000000" ratio="0" alpha="1" />
      <s:GradientEntry color="#000000" ratio="1" alpha="0" />
     </s:LinearGradient>
    </s:fill>
   </s:Rect>
  </s:Group>
 
  <fx:Border top="0" bottom="0" left="20" right="40" />
  <s:Label top="-20" left="0" text="Over Graphic (#000000, 0-100% Alpha)" />
 </s:Group>
 
 <!-- Graphic Control Group -->
 <s:VGroup gap="10">
  <s:Label text="Under Graphic Blend Mode:" />
  <s:List id="underBlendModeList" height="100" dataProvider="{blendModes}" requireSelection="true" />
  <s:Label text="Under Graphic Opaque Background:" />
  <s:List id="underOpaqueBgList" height="100" dataProvider="{opaqueBgColors}" requireSelection="true" />
 
  <fx:HRule width="100%" />
 
  <s:CheckBox id="cacheAsBitmapCk" label="Over Graphic Cache As Bitmap" />
 
  <fx:HRule width="100%" />
 
  <s:Label text="Graphic Group Alpha: {alphaSlider.value}" />
  <s:HSlider id="alphaSlider" width="80%" value="1" stepSize="0.01" minimum="0" maximum="1" />
 </s:VGroup>
 
</s:Application>

前景是黑色,Alpha 0-100% 漸層
中景是各種顏色漸層色塊,配合各種 Blend Mode 測試
背景是純白色

Online Demo:

This movie requires Flash Player 9

Hard Light 模式結果:

Overlay 模式結果:

可以很明顯的發現混色結果怪怪的,就連黑白色混出來的結果也是
反覆測試之後發現有幾種方式可以繞過這個問題

  • 包含中景、前景的整個 MovieClip,套用一個非 100% 的 Alpha 值
  • 前景打開點陣圖快取
  • 背景不要用純白色,只要帶一點點灰就能避開這問題,e.g. #FEFEFE
    需要注意的是 RGB 都要非 256
    因為這個問題是三色 Channel 個別發生的

以上的問題似乎會發生在 Flash Player 9, 10 所有版本上
包含目前最新版本 10.3.181.22,OS Win7
而更早期的 Flash Player 8 卻是正常的