1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.media.videoeditor;
18
19import android.graphics.Bitmap;
20import android.graphics.BitmapFactory;
21import java.io.DataOutputStream;
22import java.io.File;
23import java.io.FileOutputStream;
24import java.io.IOException;
25import java.nio.ByteBuffer;
26import java.nio.IntBuffer;
27
28/**
29 * This class allows to render an "alpha blending" transition according to a
30 * bitmap mask. The mask shows the shape of the transition all along the
31 * duration of the transition: just before the transition, video 1 is fully
32 * displayed. When the transition starts, as the time goes on, pixels of video 2
33 * replace pixels of video 1 according to the gray scale pixel value of the
34 * mask.
35 * {@hide}
36 */
37public class TransitionAlpha extends Transition {
38    /** This is the input JPEG file for the mask */
39    private final String mMaskFilename;
40
41    /**
42     * This is percentage (between 0 and 100) of blending between video 1 and
43     * video 2 if this value equals 0, then the mask is strictly applied if this
44     * value equals 100, then the mask is not at all applied (no transition
45     * effect)
46     */
47    private final int mBlendingPercent;
48
49    /**
50     * If true, this value inverts the direction of the mask: white pixels of
51     * the mask show video 2 pixels first black pixels of the mask show video 2
52     * pixels last.
53     */
54    private final boolean mIsInvert;
55
56
57    private int mWidth;
58    private int mHeight;
59    private String mRGBMaskFile;
60
61    /**
62     * An object of this type cannot be instantiated by using the default
63     * constructor
64     */
65    @SuppressWarnings("unused")
66    private TransitionAlpha() {
67        this(null, null, null, 0, 0, null, 0, false);
68    }
69
70    /**
71     * Constructor
72     *
73     * @param transitionId The transition id
74     * @param afterMediaItem The transition is applied to the end of this media
75     *            item
76     * @param beforeMediaItem The transition is applied to the beginning of this
77     *            media item
78     * @param durationMs duration of the transition in milliseconds
79     * @param behavior behavior is one of the behavior defined in Transition
80     *            class
81     * @param maskFilename JPEG file name. The dimension of the image
82     *           corresponds to 720p (16:9 aspect ratio). Mask files are
83     *           shared between video editors and can be created in the
84     *           projects folder (the parent folder for all projects).
85     * @param blendingPercent The blending percent applied
86     * @param invert true to invert the direction of the alpha blending
87     * @throws IllegalArgumentException if behavior is not supported, or if
88     *             direction are not supported.
89     */
90    public TransitionAlpha(String transitionId, MediaItem afterMediaItem,
91            MediaItem beforeMediaItem, long durationMs, int behavior,
92            String maskFilename, int blendingPercent, boolean invert) {
93        super(transitionId, afterMediaItem, beforeMediaItem, durationMs, behavior);
94
95        /**
96         * Generate a RGB file for the supplied mask file
97         */
98        final BitmapFactory.Options dbo = new BitmapFactory.Options();
99        dbo.inJustDecodeBounds = true;
100        if (!new File(maskFilename).exists())
101            throw new IllegalArgumentException("File not Found " + maskFilename);
102        BitmapFactory.decodeFile(maskFilename, dbo);
103
104        mWidth = dbo.outWidth;
105        mHeight = dbo.outHeight;
106
107        mRGBMaskFile = String.format(mNativeHelper.getProjectPath() +
108                "/" + "mask" + transitionId+ ".rgb");
109
110
111        FileOutputStream fl = null;
112
113        try{
114             fl = new FileOutputStream(mRGBMaskFile);
115        } catch (IOException e) {
116            /* catch IO exception */
117        }
118        final DataOutputStream dos = new DataOutputStream(fl);
119
120        if (fl != null) {
121            /**
122             * Write to rgb file
123             */
124            Bitmap imageBitmap = BitmapFactory.decodeFile(maskFilename);
125            final int [] framingBuffer = new int[mWidth];
126            ByteBuffer byteBuffer = ByteBuffer.allocate(framingBuffer.length * 4);
127            IntBuffer intBuffer;
128
129            byte[] array = byteBuffer.array();
130            int tmp = 0;
131            while (tmp < mHeight) {
132                imageBitmap.getPixels(framingBuffer, 0, mWidth, 0, tmp,mWidth, 1);
133                intBuffer = byteBuffer.asIntBuffer();
134                intBuffer.put(framingBuffer,0,mWidth);
135                try {
136                    dos.write(array);
137                } catch (IOException e) {
138                    /* catch file write error */
139                }
140                tmp += 1;
141            }
142
143            imageBitmap.recycle();
144            try{
145                fl.close();
146            }catch (IOException e) {
147                /* file close error */
148            }
149        }
150
151        /**
152         * Capture the details
153         */
154        mMaskFilename = maskFilename;
155        mBlendingPercent = blendingPercent;
156        mIsInvert = invert;
157    }
158
159    public int getRGBFileWidth() {
160        return mWidth;
161    }
162
163    public int getRGBFileHeight() {
164        return mHeight;
165    }
166
167    public String getPNGMaskFilename() {
168        return mRGBMaskFile;
169    }
170
171    /**
172     * Get the blending percentage
173     *
174     * @return The blending percentage
175     */
176    public int getBlendingPercent() {
177        return mBlendingPercent;
178    }
179
180    /**
181     * Get the filename of the mask.
182     *
183     * @return The mask filename
184     */
185    public String getMaskFilename() {
186        return mMaskFilename;
187    }
188
189    /**
190     * Check if the alpha blending direction is inverted.
191     *
192     * @return true if the direction of the alpha blending is inverted
193     */
194    public boolean isInvert() {
195        return mIsInvert;
196    }
197
198    /*
199     * {@inheritDoc}
200     */
201    @Override
202    public void generate() {
203        super.generate();
204    }
205}
206