Magic with Merlin: Porter-Duff rules!

本文介绍了Java AlphaComposite类在版本1.4中支持的全部12种复合规则,并提供了交互式程序进行操作演示。
John Zukowski ( jaz@zukowski.net), President, JZ Ventures, Inc.

Summary:  Two-dimensional graphics programming with the Java language just got a little better. The AlphaComposite class, which previously supported only eight of the 12 Porter-Duff rules for digital image compositing, now supports all 12. In this installment of Magic with Merlin, John Zukowski describes all 12 rules and offers an interactive program to demonstrate how they operate.

Back in 1984, Thomas Porter and Tom Duff wrote a paper entitled "Compositing Digital Images" that described 12 rules combining two images. Support for these compositing rules is found in the AlphaComposite class, first introduced in version 1.2 of the Java language. Version 1.4, currently in beta 2, supports all 12 rules.

Support for compositing is necessary for applications like games that include multiple image types, including background images, player-character images, and the like. While it is easy to always draw the player in front of the background, if the player were to jump behind a tree, you would want to show the character image faded out somewhat behind the tree image. This is where compositing comes in handy.

Porter and Duff's 12 rules

The AlphaComposite class has 12 constants, one for each rule. It can be tricky to visualize how the rule is applied, so I've provided an illustration of each rule in action. The actual combinations will vary if the images aren't opaque. The demonstration program, shown in Listing 1 and available for download in the Resources section, allows you to try out different levels of transparency.

Note: Those rules newly added with the Merlin release are indicated with an asterisk (*).

Rule 1.AlphaComposite.CLEAR: Nothing will be drawn in the combined image.


AlphaComposite.CLEAR
AlphaComposite.CLEAR

Rule 2.AlphaComposite.SRC: SRC stands for source; only the source image will be in the combined image.


AlphaComposite.SRC
AlphaComposite.SRC

Rule 3.AlphaComposite.DST*: DST stands for destination; only the destination image will be in the combined image.


AlphaComposite.DST
AlphaComposite.DST

Rule 4.AlphaComposite.SRC_OVER: The source image will be drawn over the destination image.


AlphaComposite.SRC_OVER
AlphaComposite.SRC_OVER

Rule 5.AlphaComposite.DST_OVER: The destination image will be drawn over the source image.


AlphaComposite.DST_OVER
AlphaComposite.DST_OVER

Rule 6.AlphaComposite.SRC_IN: Only the part of the source image that overlaps the destination image will be drawn.


AlphaComposite.SRC_IN
AlphaComposite.SRC_IN

Rule 7.AlphaComposite.DST_IN: Only the part of the destination image that overlaps the source image will be drawn.


AlphaComposite.DST_IN
AlphaComposite.DST_IN

Rule 8.AlphaComposite.SRC_OUT: Only the part of the source image that doesn't overlap the destination image will be drawn.


AlphaComposite.SRC_OUT
AlphaComposite.SRC_OUT

Rule 9.AlphaComposite.DST_OUT: Only the part of the destination image that doesn't overlap the source image will be drawn.


AlphaComposite.DST_OUT
AlphaComposite.DstOut

Rule 10.AlphaComposite.SRC_ATOP*: The part of the source image that overlaps the destination image will be drawn with the part of the destination image that doesn't overlap the source image.


AlphaComposite.SRC_ATOP
AlphaComposite.SRC_ATOP

Rule 11.AlphaComposite.DST_ATOP*: The part of the destination image that overlaps the source image will be drawn with the part of the source image that doesn't overlap the destination image.


AlphaComposite.DST_ATOP
AlphaComposite.DST_ATOP

Rule 12.AlphaComposite.XOR*: The part of the source image that doesn't overlap the destination image will be drawn with the part of the destination image that doesn't overlap the source image.


AlphaComposite.XOR
AlphaComposite.XOR

A complete example

The following program is an interactive demonstration of the alpha compositing rules. Just alter the opacity for each triangle and select a rule to use to see the effect of blending the images.

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.image.*;
import java.lang.reflect.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.*;

public class CompositeIt extends JFrame {
  JSlider sourcePercentage = new JSlider();
  JSlider destinationPercentage = new JSlider();
  JComboBox alphaComposites = new JComboBox();
  DrawingPanel drawingPanel = new DrawingPanel();

  public CompositeIt() {
    super("Porter-Duff");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JPanel contentPane = (JPanel) this.getContentPane();
    Dictionary labels = new Hashtable();
    labels.put(new Integer(0),   new JLabel("0.0"));
    labels.put(new Integer(25),  new JLabel("0.25"));
    labels.put(new Integer(33),  new JLabel("0.33"));
    labels.put(new Integer(50),  new JLabel("0.50"));
    labels.put(new Integer(67),  new JLabel("0.67"));
    labels.put(new Integer(75),  new JLabel("0.75"));
    labels.put(new Integer(100), new JLabel("1.00"));
    sourcePercentage.setOrientation(JSlider.VERTICAL);
    sourcePercentage.setLabelTable(labels);
    sourcePercentage.setPaintTicks(true);
    sourcePercentage.setPaintLabels(true);
    sourcePercentage.setValue(100);
    sourcePercentage.addChangeListener(new ChangeListener() {
      public void stateChanged(ChangeEvent e) {
        int sourceValue = sourcePercentage.getValue();
        drawingPanel.setSourcePercentage(sourceValue/100.0f);
      }
    });
    destinationPercentage.setOrientation(JSlider.VERTICAL);
    destinationPercentage.setLabelTable(labels);
    destinationPercentage.setPaintTicks(true);
    destinationPercentage.setPaintLabels(true);
    destinationPercentage.setValue(100);
    destinationPercentage.addChangeListener(new ChangeListener() {
      public void stateChanged(ChangeEvent e) {
        int destinationValue = destinationPercentage.getValue();
        drawingPanel.setDestinationPercentage(destinationValue/100.0f);
      }
    });
    String rules[] = {
      "CLEAR",    "DST", 
      "DST_ATOP", "DST_IN", 
      "DST_OUT",  "DST_OVER", 
      "SRC",      "SRC_ATOP", 
      "SRC_IN",   "SRC_OUT", 
      "SRC_OVER", "XOR"};
    ComboBoxModel model = new DefaultComboBoxModel(rules);
    alphaComposites.setModel(model);
    alphaComposites.setSelectedItem("XOR");
    alphaComposites.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        String alphaValue = alphaComposites.getSelectedItem().toString();
        Class alphaClass = AlphaComposite.class;
        try {
          Field field = alphaClass.getDeclaredField(alphaValue);
          int rule = ((Integer)field.get(AlphaComposite.Clear)).intValue();
          drawingPanel.setCompositeRule(rule);
        } catch (Exception exception) {
          System.err.println("Unable to find field");
        }
      }
    });
    contentPane.add(sourcePercentage, BorderLayout.WEST);
    contentPane.add(destinationPercentage, BorderLayout.EAST);
    contentPane.add(alphaComposites, BorderLayout.SOUTH);
    contentPane.add(drawingPanel, BorderLayout.CENTER);
    pack();
  }

  public static void main(String args[]) {
    new CompositeIt().show();
  }

  class DrawingPanel extends JPanel {
    GeneralPath sourcePath, destPath;
    BufferedImage source, dest;
    float sourcePercentage = 1, destinationPercentage = 1;
    int compositeRule = AlphaComposite.XOR;
    Dimension dimension = new Dimension(200, 200);

    public DrawingPanel() {
      sourcePath = new GeneralPath();  
      sourcePath.moveTo(0,   0);   sourcePath.lineTo(150, 0);
      sourcePath.lineTo(0, 200);   sourcePath.closePath();
      source = new BufferedImage(200, 200, BufferedImage.TYPE_INT_ARGB);
      destPath = new GeneralPath();
      destPath.moveTo(200,  0);    destPath.lineTo(50, 0);
      destPath.lineTo(200, 200);    destPath.closePath();
      dest = new BufferedImage(200, 200, BufferedImage.TYPE_INT_ARGB);
    }

    public void setSourcePercentage(float value) {
      sourcePercentage = value;
       repaint();
    }

    public void setDestinationPercentage(float value) {
      destinationPercentage = value;
       repaint();
    }

    public void setCompositeRule(int value) {
      compositeRule = value;
       repaint();
    }

    public void paintComponent(Graphics g) {
      super.paintComponent(g);
      Graphics2D g2d = (Graphics2D)g;
      Graphics2D sourceG = source.createGraphics();
      Graphics2D destG = dest.createGraphics();

      destG.setComposite(AlphaComposite.Clear);
      destG.fillRect(0, 0, 200, 200);
      destG.setComposite(AlphaComposite.getInstance(
          AlphaComposite.XOR, destinationPercentage));
      destG.setPaint(Color.magenta);
      destG.fill(destPath);

      sourceG.setComposite(AlphaComposite.Clear);
      sourceG.fillRect(0, 0, 200, 200);
      sourceG.setComposite(AlphaComposite.getInstance(
        AlphaComposite.XOR, sourcePercentage));
      sourceG.setPaint(Color.green);
      sourceG.fill(sourcePath);

      destG.setComposite(AlphaComposite.getInstance(compositeRule));
      destG.drawImage(source, 0, 0, null);
      g2d.drawImage(dest, 0, 0, this);
    }

    public Dimension getPreferredSize() {
      return dimension;
    }
  }
}

内容概要:本文详细介绍了一个基于MATLAB实现的线性回归(LR)电力负荷预测项目实例,涵盖了从项目背景、模型架构、算法流程、代码实现到GUI界面设计的完整开发过程。项目通过整合历史负荷、气象数据、节假日信息等多源变量,构建多元线性回归模型,并结合特征工程、数据预处理、正则化方法(如岭回归、LASSO)和模型评估指标(RMSE、MAPE、R²等),提升预测精度与泛化能力。文中还展示了系统化的项目目录结构、自动化部署脚本、可视化分析及工程集成方案,支持批量预测与实时滚动更新,具备高度模块化、可解释性强、部署友好的特点。; 适合人群:具备一定MATLAB编程基础,从事电力系统分析、能源管理、智能电网或数据建模相关工作的工程师、研究人员及高校师生。; 使用场景及目标:①应用于城市电力调度、新能源消纳、智能楼宇用能管理等场景下的短期负荷预测;②帮助理解线性回归在实际工程项目中的建模流程、特征处理与模型优化方法;③通过GUI界面实现交互式预测与结果可视化,支持工程落地与决策辅助; 阅读建议:建议结合提供的完整代码与GUI示例进行实践操作,重点关注数据预处理、特征构造、正则化调优与模型评估部分,深入理解各模块的设计逻辑与工程封装思路,以便迁移到类似的时间序列预测任务中。
【轴承故障诊断】基于SE-TCN和SE-TCN-SVM西储大学轴承故障诊断研究(Matlab代码实现)内容概要:本文介绍了基于SE-TCN(Squeeze-and-Excitation Temporal Convolutional Network)和SE-TCN-SVM的轴承故障诊断方法研究,重点针对西储大学(Case Western Reserve University, CWRU)的轴承数据集进行实验验证。研究通过构建SE-TCN模型提取振动信号中的深层时序特征,并利用SE模块增强关键特征通道的权重,从而提升故障识别精度。为进一步提高分类性能,还将SE-TCN提取的特征输入支持向量机(SVM)进行分类,形成SE-TCN-SVM混合模型。文中提供了完整的Matlab代码实现,便于复现实验结果。该方法在多工况、多故障类型下表现出良好的诊断准确率和鲁棒性,适用于工业设备的智能运维与早期故障预警。; 适合人群:具备一定信号处理和机器学习基础的研究生、科研人员及工程技术人员,尤其适合从事机械故障诊断、智能运维、工业大数据分析等相关领域的研究人员;熟悉Matlab编程者更易上手。; 使用场景及目标:①应用于旋转机械设备(如电机、风机、齿轮箱等)的轴承故障诊断;②作为深度学习与传统分类器结合的典型案例,用于教学与科研参考;③目标是提升故障诊断的自动化水平与准确性,推动智能制造与预测性维护的发展。; 阅读建议:建议读者结合提供的Matlab代码,逐步运行并理解模型构建、特征提取与分类流程,同时尝试在其他公开数据集上迁移应用,以加深对SE-TCN架构与故障诊断流程的理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值