001/** 002 * Copyright (c) 2011, The University of Southampton and the individual contributors. 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without modification, 006 * are permitted provided that the following conditions are met: 007 * 008 * * Redistributions of source code must retain the above copyright notice, 009 * this list of conditions and the following disclaimer. 010 * 011 * * Redistributions in binary form must reproduce the above copyright notice, 012 * this list of conditions and the following disclaimer in the documentation 013 * and/or other materials provided with the distribution. 014 * 015 * * Neither the name of the University of Southampton nor the names of its 016 * contributors may be used to endorse or promote products derived from this 017 * software without specific prior written permission. 018 * 019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030package org.openimaj.video.processing.effects; 031 032import java.util.LinkedList; 033 034import org.openimaj.image.FImage; 035import org.openimaj.image.MBFImage; 036import org.openimaj.image.colour.RGBColour; 037import org.openimaj.image.processing.convolution.FGaussianConvolve; 038import org.openimaj.image.processing.convolution.FImageConvolveSeparable; 039import org.openimaj.video.Video; 040import org.openimaj.video.processor.VideoProcessor; 041 042/** 043 * {@link VideoProcessor} that produces a slit-scan effect. 044 * 045 * @author Sina Samangooei (ss@ecs.soton.ac.uk) 046 * 047 */ 048public class SlitScanProcessor extends VideoProcessor<MBFImage> { 049 LinkedList<float[][][]> cache = new LinkedList<float[][][]>(); 050 051 final float[] blurKern = FGaussianConvolve.makeKernel(0.5f); 052 int cacheSize = 240; 053 054 /** 055 * Default constructor for using the video processor in an ad-hoc manner. 056 * 057 * @param cacheSize 058 * The number of frames to retain for creating the slitscan 059 * effect 060 */ 061 public SlitScanProcessor(int cacheSize) 062 { 063 this.cacheSize = cacheSize; 064 } 065 066 /** 067 * Constructor for creating a video processor which is chainable. 068 * 069 * @param video 070 * The video to process 071 * @param cacheSize 072 * The number of frames to retain for creating the slitscan 073 * effect 074 */ 075 public SlitScanProcessor(Video<MBFImage> video, int cacheSize) { 076 super(video); 077 this.cacheSize = cacheSize; 078 } 079 080 @Override 081 public MBFImage processFrame(MBFImage frame) { 082 addToCache(frame); 083 084 final int height = frame.getHeight(); 085 final float prop = (float) (cacheSize) / height; 086 frame.fill(RGBColour.BLACK); 087 final float[][] framer = frame.getBand(0).pixels; 088 final float[][] frameg = frame.getBand(1).pixels; 089 final float[][] frameb = frame.getBand(2).pixels; 090 for (int y = 0; y < height; y++) { 091 final int index = (int) (y * prop); 092 if (index >= cache.size()) { 093 break; 094 } 095 // System.out.println("y = " + y); 096 // System.out.println("index = " + index); 097 final float[][][] cacheImage = cache.get(index); 098 System.arraycopy(cacheImage[0][y], 0, framer[y], 0, cacheImage[0][y].length); 099 System.arraycopy(cacheImage[1][y], 0, frameg[y], 0, cacheImage[1][y].length); 100 System.arraycopy(cacheImage[2][y], 0, frameb[y], 0, cacheImage[2][y].length); 101 } 102 103 for (final FImage f : frame.bands) { 104 FImageConvolveSeparable.convolveVertical(f, blurKern); 105 } 106 107 if (cache.size() >= cacheSize) 108 cache.removeLast(); 109 110 return frame; 111 } 112 113 private void addToCache(MBFImage frame) { 114 final MBFImage f = frame.clone(); 115 116 final float[][][] entry = new float[3][][]; 117 118 entry[0] = f.getBand(0).pixels; 119 entry[1] = f.getBand(1).pixels; 120 entry[2] = f.getBand(2).pixels; 121 122 cache.addFirst(entry); 123 } 124}