/* * Copyright 2012 Uwe Krueger. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.mandelsoft.mand.movie; import com.mandelsoft.mand.Environment; import com.mandelsoft.mand.IllegalConfigurationException; import com.mandelsoft.mand.MandelData; import com.mandelsoft.mand.MandelName; import com.mandelsoft.mand.Settings; import com.mandelsoft.mand.cm.Colormap; import com.mandelsoft.mand.image.MandelImage; import com.mandelsoft.mand.scan.MandelHandle; import com.mandelsoft.mand.scan.MandelScanner; import com.mandelsoft.mand.tool.Decoration; import com.mandelsoft.mand.tools.Command; import com.mandelsoft.mand.util.MandUtils; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.concurrent.TimeUnit; import com.xuggle.mediatool.IMediaWriter; import com.xuggle.mediatool.ToolFactory; import com.xuggle.xuggler.ICodec; import com.xuggle.xuggler.IRational; import java.awt.Color; import java.awt.Graphics; import java.io.File; /** * * @author Uwe Krueger */ public class MovieMaker { private static final int GAP=5000; private static final int FRAME_RATE=25; private static final int MILLISECONDS_PER_FRAME=1000/FRAME_RATE; private static final int ALPHA_TIME=2000; private static final double ALPHA_DELTA=255.0/((double)ALPHA_TIME/MILLISECONDS_PER_FRAME); private static String outputFilename="zoom.mp4"; private static double scale=1; public static MandelImage getImage(MandelScanner scanner, MandelImage.Factory f, MandelName n) { MandelHandle h=scanner.getMandelData(n); if (h==null) return null; try { MandelData md=h.getData(); MandelData pure=new MandelData(md.getInfo()); pure.setRaster(md.getRaster()); MandelImage image=f.getImage(pure); //f.setColormapSource(image.getColormap()); return image; } catch (IOException ex) { System.out.println("cannt read "+h.getFile()+": "+ex); return null; } } private static class MovieWriter { IMediaWriter writer; double fps; MovieDecoration deco; public MovieWriter(int fps, int width, int height, String outputFilename) { this.fps=fps; writer=ToolFactory.makeWriter(outputFilename); writer.addVideoStream(0, 0, ICodec.ID.CODEC_ID_MPEG4, IRational.make(fps, 1), width, height); } public void setDecoration(MovieDecoration deco) { this.deco=deco; } public void encodeVideo(long time, BufferedImage im) { BufferedImage bgr=convertToType(im, BufferedImage.TYPE_3BYTE_BGR); if (deco!=null && deco.isActive(time)) { if (bgr==im) { bgr=new BufferedImage(im.getWidth(), im.getHeight(), BufferedImage.TYPE_3BYTE_BGR); bgr.getGraphics().drawImage(im, 0, 0, null); } Graphics g=bgr.getGraphics(); deco.paintDecoration(time, g, bgr.getWidth(), bgr.getHeight()); } writer.encodeVideo(0, bgr, time, TimeUnit.MILLISECONDS); } public void close() { writer.close(); } } public static void main(String[] args) { try { outputFilename=new File(".").getCanonicalFile().getName()+".mp4"; System.out.println("OUT: "+outputFilename); } catch (IOException ex) { Command.Error("cannot determine directory name"); } Environment env=null; try { env=new Environment(args); } catch (IllegalConfigurationException ex) { System.out.println("cannot initial image base: "+ex); System.exit(1); } Decoration decoration=new Decoration(); decoration.setShowDecoration(true); decoration.setDecoration(env.getCopyright()); Decoration mag=new Decoration("magnification"); mag.setShowDecoration(true); mag.setFont("Times Roman Bold-20"); Decoration url=new Decoration("url"); url.setHAlign(Decoration.ALIGN_LEFT); url.setFont("Times Roman-15"); String u=env.getProperty(Settings.HOMEPAGE); if (u!=null) { url.setDecoration(u); url.setShowDecoration(true); } MandelScanner scanner=env.getImageDataScanner(); Colormap cm=env.getDefaultColormap(); MandelImage.Factory f=new MandelImage.Factory(cm); MandelName name=MandelName.ROOT; MandelImage image=getImage(scanner,f,name); SimpleMovieDecoration mmag; MovieWriter mw=new MovieWriter(FRAME_RATE, (int)(image.getImage().getWidth()*scale), (int)(image.getImage().getHeight()*scale), outputFilename); CompoundMovieDecoration d=new CompoundMovieDecoration(); d.addMovieDecoration(new SimpleMovieDecoration(decoration,0,1000,4000,4000)); VerticalListMovieDecoration v=new VerticalListMovieDecoration(40,0, 500, 4000,4000); v.addDecoration(createTitleLine("The Beauty")); v.addDecoration(createTitleLine("of Chaos")); d.addMovieDecoration(v); d.addMovieDecoration(mmag=new SimpleMovieDecoration(mag,9000,1000,Long.MAX_VALUE,GAP/3)); mw.setDecoration(d); long time=0; double alpha=255; BufferedImage im=image.getImage(); while (time<GAP) { mw.encodeVideo(time, im); time+=MILLISECONDS_PER_FRAME; } while (image!=null) { // take the screen shot im=image.getImage(); mag.setDecoration("10^-"+MandUtils.getMagnification(image.getInfo())); mw.encodeVideo(time, im); time+=MILLISECONDS_PER_FRAME; name=name.sub('z'); image=getImage(scanner,f,name); if (image==null) { long end=time+GAP; mmag.setShowTime(time-mmag.getStart()-mmag.getFadeInTime()); d.addMovieDecoration(new SimpleMovieDecoration(url,time,GAP/3,GAP,0)); while (time<end) { mw.encodeVideo(time, im); time+=MILLISECONDS_PER_FRAME; } } } // tell the writer to close and write the trailer if needed mw.close(); } public static Decoration createTitleLine(String txt) { Decoration t=new Decoration(txt); t.setHAlign(Decoration.ALIGN_CENTER); t.setVAlign(Decoration.ALIGN_CENTER); t.setHInset(80); t.setVInset(-5); t.setFontSize(45); t.setColor(new Color(0x77,0x77,0)); t.setShowDecoration(true); return t; } public static BufferedImage convertToType(BufferedImage sourceImage, int targetType) { BufferedImage image; // if the source image is already the target type, return the source image if (sourceImage.getType()==targetType) { image=sourceImage; } // otherwise create a new image of the target type and draw the new image else { image=new BufferedImage(sourceImage.getWidth(), sourceImage.getHeight(), targetType); image.getGraphics().drawImage(sourceImage, 0, 0, null); } return image; } }