📄 qtsvgviewer.java
字号:
/* * File: QTSVGViewer.java * Project: MPI Linguistic Application * Date: 02 May 2007 * * Copyright (C) 2001-2007 Max Planck Institute for Psycholinguistics * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */package mpi.eudico.client.annotator.svg;import mpi.eudico.server.corpora.clom.Annotation;import mpi.eudico.server.corpora.clom.Transcription;import mpi.eudico.server.corpora.clomimpl.abstr.MediaDescriptor;import mpi.eudico.server.corpora.clomimpl.abstr.SVGAlignableAnnotation;import mpi.eudico.server.corpora.clomimpl.abstr.TierImpl;import mpi.eudico.server.corpora.clomimpl.type.LinguisticType;import mpi.util.LogUtil;import quicktime.QTException;import quicktime.qd.PixMap;import quicktime.qd.QDColor;import quicktime.qd.QDConstants;import quicktime.qd.QDGraphics;import quicktime.qd.QDRect;import quicktime.std.StdQTConstants;import quicktime.std.StdQTException;import quicktime.std.image.GraphicsMode;import quicktime.std.image.ImageDescription;import quicktime.std.image.Matrix;import quicktime.std.movies.Atom;import quicktime.std.movies.AtomContainer;import quicktime.std.movies.Movie;import quicktime.std.movies.Track;import quicktime.std.movies.media.SpriteDescription;import quicktime.std.movies.media.SpriteMedia;import quicktime.std.movies.media.SpriteMediaHandler;import quicktime.util.EncodedImage;import quicktime.util.EndianDescriptor;import quicktime.util.EndianOrder;import quicktime.util.QTHandle;import quicktime.util.QTUtils;import java.awt.Dimension;import java.awt.Graphics2D;import java.awt.Shape;import java.awt.geom.Ellipse2D;import java.awt.geom.Line2D;import java.awt.geom.Point2D;import java.awt.geom.Rectangle2D;import java.awt.geom.RectangularShape;import java.util.Hashtable;import java.util.Iterator;import java.util.Map;import java.util.Vector;import java.util.logging.Logger;/** * A class that creates QuickTime Sprite tracks for each tier that has graphic * references. * * @author Han Sloetjes * @version Aug 2005 Identity removed */public class QTSVGViewer extends AbstractSVGViewer { /** a logger */ private static final Logger LOG = Logger.getLogger(QTSVGViewer.class.getName()); /** the QT movie object */ private Movie movie; /** stores created tracks with the tiername as key */ private Map trackTable; /** default sprite description */ private SpriteDescription spriteDesc; /** the duration of the media according to QT */ private int qtDuration; /** * the width of the media according to QT; in case of MPEG-1 media QT * (often) creates a movie of size 320240 (instead of 352288) */ private int qtMediaWidth; /** the height of the media according to QT */ private int qtMediaHeight; /** the media rect according to QT: 0, 0, qtMediaWidth, qtMediaHeight */ private QDRect qtMediaRect; /** the dimension of the media as read from the header of the mediafile */ private QDRect fileMediaRect; /** the color to use for the stroke of 2d annotations */ private final QDColor QD_STROKE_COLOR; /** * Creates a new QTSVGViewer instance * * @param transcription the transcription */ public QTSVGViewer(Transcription transcription) { super(transcription); trackTable = new Hashtable(); try { spriteDesc = new SpriteDescription(); } catch (QTException qte) { } float[] colors = new float[3]; colors = STROKE_COLOR.getRGBColorComponents(colors); QD_STROKE_COLOR = new QDColor(colors[0], colors[1], colors[2]); } /** * Sets the movie object that will contain the new Tracks. * * @param movie the QT movie */ public void setMovie(Movie movie) { this.movie = movie; try { qtDuration = movie.getDuration(); qtMediaWidth = movie.getNaturalBoundsRect().getWidth(); qtMediaHeight = movie.getNaturalBoundsRect().getHeight(); } catch (QTException qte) { qtMediaWidth = 320; qtMediaHeight = 240; qtDuration = Integer.MAX_VALUE; } qtMediaRect = new QDRect(0, 0, qtMediaWidth, qtMediaHeight); fileMediaRect = new QDRect(0, 0, 352, 288); initViewer(); } /** * Sets the dimension of the (mpeg) movie, as read from the mpeg header. * * @param d the image width and height of the video */ public void setMediaFileDimension(Dimension d) { if (d == null) { // hardwired for now fileMediaRect = new QDRect(0, 0, 352, 288); } else { fileMediaRect = new QDRect(0, 0, (int) d.getWidth(), (int) d.getHeight()); } } /** * Initializes the viewer by extracting the graphical annotations.<br> * It then creates SpriteTracks and adds them to the Movie. */ void initViewer() { if (movie == null) { return; } TierImpl tier; Iterator tierIt = transcription.getTiers().iterator(); while (tierIt.hasNext()) { tier = (TierImpl) tierIt.next(); createTrackFromTier(tier); } QTUtils.reclaimMemory(); } /** * This methods loops over all annotations on the specified tier and * creates a sample for each one containing a graphical annotation. It * seems that only a duration can be specified for a sample, not a start * time. Therefore empty samples are inserted in the gaps between * annotations. * * @param tier the tier containing the annotations for the track */ private void createTrackFromTier(TierImpl tier) { if ((tier == null) || (tier.getLinguisticType() == null) || !tier.getLinguisticType().hasGraphicReferences()) { return; } try { String tierName = tier.getName(); Track track = null; SpriteMedia spriteMedia = null; if (trackTable.containsKey(tierName)) { track = (Track) trackTable.get(tierName); if (track != null) { movie.removeTrack(track); trackTable.remove(tierName); track.disposeQTObject(); } } track = movie.newTrack(qtMediaWidth, qtMediaHeight, 0f); spriteMedia = new SpriteMedia(track, movie.getTimeScale(), null); AtomContainer sampleContainer; AtomContainer emptyAC; Vector annos = tier.getAnnotations(); long curEndTime = 0L; Iterator annIt = annos.iterator(); Annotation ann; SVGAlignableAnnotation svgAnn; spriteMedia.beginEdits(); while (annIt.hasNext()) { ann = (Annotation) annIt.next(); if (!(ann instanceof SVGAlignableAnnotation)) { // this can happen when an existing lin. type is changed // but annotations have not yet been converted break; } svgAnn = (SVGAlignableAnnotation) ann; if (svgAnn.getShape() != null) { if (curEndTime < svgAnn.getBeginTimeBoundary()) { // add empty sample emptyAC = new AtomContainer(); int duration = (int) (svgAnn.getBeginTimeBoundary() - curEndTime); spriteMedia.addSample(emptyAC, 0, // dataOffset emptyAC.getSize(), duration, // duration in ms (ticks : one frame * 25?) spriteDesc, 1, // 1 samples 0); // flags - this is a sync sample) } // now add a sample for svgAnn sampleContainer = createSample(svgAnn); if (sampleContainer != null) { int duration = (int) (svgAnn.getEndTimeBoundary() - svgAnn.getBeginTimeBoundary()); spriteMedia.addSample(sampleContainer, 0, // dataOffset sampleContainer.getSize(), duration, // duration in ms spriteDesc, 1, // 1 sample 0); // sync sample } curEndTime = svgAnn.getEndTimeBoundary(); } } if (curEndTime < qtDuration) { int duration = (int) (qtDuration - curEndTime); emptyAC = new AtomContainer(); spriteMedia.addSample(emptyAC, 0, // dataOffset emptyAC.getSize(), duration, // duration in ms (ticks : one frame * 25?) spriteDesc, 1, // 1 samples 0); } spriteMedia.endEdits(); /* add sprite media to track */ track.insertMedia(0, 0, spriteMedia.getDuration(), 1); // track properties AtomContainer spriteTrackProperties = new AtomContainer(); /* QDColor bgColor = QDColor.blue; EndianOrder.flipNativeToBigEndian(bgColor, 0, QDColor.getEndianDescriptorRGBColor()); spriteTrackProperties.insertChild(new Atom(StdQTConstants.kParentAtomIsContainer), StdQTConstants.kSpriteTrackPropertyBackgroundColor, 1, 1, bgColor); */ /* int idleAsFastAsPossible = 0; spriteTrackProperties.insertChild( new Atom(StdQTConstants.kParentAtomIsContainer), StdQTConstants.kSpriteTrackPropertyQTIdleEventsFrequency, 1, 1, EndianOrder.flipNativeToBigEndian32(idleAsFastAsPossible)); */ spriteTrackProperties.insertChild(new Atom( StdQTConstants.kParentAtomIsContainer), StdQTConstants.kSpriteTrackPropertyScaleSpritesToScaleWorld, 1, 1, EndianOrder.flipNativeToBigEndian16((short) 1)); /* does not work (yet) spriteTrackProperties.insertChild( new Atom(StdQTConstants.kParentAtomIsContainer), StdQTConstants.kSpriteTrackPropertyVisible, 1, 1, EndianOrder.flipNativeToBigEndian16((short)1));//visible */ spriteMedia.setPropertyAtom(spriteTrackProperties); SpriteMediaHandler handler = spriteMedia.getSpriteHandler(); handler.setGraphicsMode(new GraphicsMode(QDConstants.transparent, QDColor.black)); // store the track reference for later use Object t = trackTable.put(tierName, track); /* if (t instanceof Track) { ((Track)t).disposeQTObject(); } */ // reclaim memory QTUtils.reclaimMemory(); } catch (QTException qte) { LOG.warning(LogUtil.formatStackTrace(qte)); } } /** * First creates an image from the annotation's shape and then creates an * AtomContainer with the right property and data atoms. * * @param svgAnn the annotation that holds a graphical shape/annotation * * @return a dressed up AtomContainer or Sample */ private AtomContainer createSample(SVGAlignableAnnotation svgAnn) { if ((svgAnn == null) || (svgAnn.getShape() == null)) { return null; } AtomContainer sampleContainer = null; try {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -