尝试获得完美的图像动画效果命令。
这是我从图像创建视频的命令,但我想在两个图像之间添加图像过渡效果(例如fadein / fadeout)。
init();
function init() {
var el=document.getElementById('chart');
var map = L.map( 'map', {
center: [20.5937,78.9629],
minZoom: 2,
zoom: 4
});
L.tileLayer( 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
subdomains: ['a','b','c']
}).addTo( map );
var mywms = L.tileLayer.wms("http://localhost:7770/geoserver/cite/wms", {
layers: 'cite:state1',
format: 'image/png',
transparent: true
});
mywms.addTo(map);
data=[
[
{ x: 1999, y : 1838.21, color: "#ccccff"},
{ x: 2000, y : 2148.01,color: "#b2b2ff" },
{ x: 2001, y : 2537.06,color: "#9999ff" },
{ x: 2002, y : 2089.29 ,color: "#7f7fff"},
{ x: 2003, y : 3276.78 ,color: "#6666ff"},
{ x: 2004, y : 2544.60,color: "#4c4cff"},
{ x: 2005, y : 2676.42 ,color: "#3232ff"}
],
[
{ x: 1999, y : 1475.22, color: "#ccccff"},
{ x: 2000, y : 1354.99,color: "#b2b2ff" },
{ x: 2001, y : 1861.67,color: "#9999ff" },
{ x: 2002, y : 1427.08 ,color: "#7f7fff"},
{ x: 2003, y : 1717.2 ,color: "#6666ff"},
{ x: 2004, y : 1676.91,color: "#4c4cff"},
{ x: 2005, y : 1900.02 ,color: "#3232ff"}
],
[
{ x: 1999, y : 2645.43, color: "#ccccff"},
{ x: 2000, y : 2649.38,color: "#b2b2ff" },
{ x: 2001, y : 2883.1,color: "#9999ff" },
{ x: 2002, y : 2689.88 ,color: "#7f7fff"},
{ x: 2003, y : 3332.6 ,color: "#6666ff"},
{ x: 2004, y :3473.52,color: "#4c4cff"},
{ x: 2005, y : 3721.04 ,color: "#3232ff"}
]
],
loc=[
[25.7532,71.4181],
[24.7467,72.8043],
[27.6094,75.1399],
[25.7711, 73.3234],
[27.1854,74.0300],
[28.1289,75.3995],
[28.3254,74.4057],
[29.9038,73.8772],
[29.1547,74.4995],
[26.9157,70.9083],
[25.1257,72.1416],
[26.28, 73.02],
[28.0229,73.3119],
];
for(var i=0;i<loc.length;i++){
var marker=L.marker(loc[i]).addTo(map).bindPopup(el),
options={index:i,marker:marker};
marker.on('click', onMarkerClick, options);//'options' object will be assigned to 'this' object, when click event occures
marker.on('mouseover', function(a) {
//open popup;
var popup = L.popup()
.setLatLng(a.loc)
.setContent('District:')
.openOn(map);
});
}
function onMarkerClick(e) {
//'this' object will be having 'options' object
var index=this.index,
marker=this.marker;
$('#chart').css('display', 'block');
var chart = new CanvasJS.Chart(el, {
title:{
text: "My First Chart in CanvasJS"
},
backgroundColor: "#ffffff",
zoomEnabled: true,
animationEnabled: true,
animationDuration: 4000,
axisY:{
title:"GDP (in Rs. Cr.)",
valueFormatString:"#####.00",
lineColor: "black",
labelFontSize: 15,
labelFontColor: "red",
titleFontColor: "black",
},
axisX:{
title:"Year",
valueFormatString:"####",
labelFontSize: 15,
labelFontColor: "red",
lineColor: "black",
titleFontColor: "black",
titleFontSize: 20,
},
data: [
{
type: "column",
xValueFormatString:"Year ####",
dataPoints:data[index]
}
]
});
chart.render();
marker.openPopup();
}
}
答案 0 :(得分:2)
在此项目中,您可以有4种效果
的slideIn
将图像添加到Parcelable [],这些将是您的输入图像。(您也可以使用位图数组或其他内容)
<强> Effectactivity.java 强>
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.request.target.Target;
import com.hini.slideshow.R;
import com.hini.slideshow.SlideApplication;
import com.hini.slideshow.draw.SlideShow;
import com.hini.slideshow.encoding.SlideEncoder;
import java.util.concurrent.ExecutionException;
/**
* Created by PrakashSaurav.
*/
public class EffectActivity extends Activity implements View.OnClickListener {
private static final String TAG = "EffectActivity";
private ViewPager mViewPager;
private Button mBtnBitRate, mBtnTime, mBtnEffect, mBtnNext, mBtnPrev;
private TextView mTvBitRate, mTvTime, mTvEffect;
private Parcelable[] mParcelableUris;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_effect);
mParcelableUris = getIntent().getParcelableArrayExtra("parcelableUris");
if (mParcelableUris == null) {
Toast.makeText(getApplicationContext(), "There is no path info for the photo.", Toast.LENGTH_SHORT).show();
return;
}
mViewPager = (ViewPager) findViewById(R.id.pager_image);
mViewPager.setAdapter(new CustomPageAdapter());
mBtnBitRate = (Button) findViewById(R.id.btn_bgm);
mTvBitRate = (TextView) findViewById(R.id.tv_bitrate);
mBtnTime = (Button) findViewById(R.id.btn_time);
mTvTime = (TextView) findViewById(R.id.tv_time);
mBtnEffect = (Button) findViewById(R.id.btn_effect);
mTvEffect = (TextView) findViewById(R.id.tv_effect);
mBtnNext = (Button) findViewById(R.id.btn_next);
mBtnPrev = (Button) findViewById(R.id.btn_prev);
mBtnBitRate.setOnClickListener(this);
mBtnTime.setOnClickListener(this);
mBtnEffect.setOnClickListener(this);
mBtnNext.setOnClickListener(this);
mBtnPrev.setOnClickListener(this);
}
int timeCheck = 0;
int effectCheck = 0;
boolean isClicked;
@Override
public void onClick(View v) {
// BGM Setting
if (v == mBtnBitRate) {
isClicked = !isClicked;
int bitRate;
if (isClicked)
bitRate = 2000 * 1024;
else
bitRate = 500 * 1024;
SlideApplication.BIT_RATE = bitRate;
mTvBitRate.setText(String.valueOf(bitRate / 1024) + "kbps");
Toast.makeText(getApplicationContext(), SlideApplication.BIT_RATE / 1024 + "kbps", Toast.LENGTH_SHORT).show();
}
// Time Setting
else if (v == mBtnTime) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
final String[] items = {"2s", "3s", "5s", "10s"};
if (SlideApplication.SLIDE_TIME == 2) timeCheck = 0;
else if (SlideApplication.SLIDE_TIME == 3) timeCheck = 1;
else if (SlideApplication.SLIDE_TIME == 5) timeCheck = 2;
else if (SlideApplication.SLIDE_TIME == 10) timeCheck = 3;
builder.setSingleChoiceItems(items, timeCheck, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
timeCheck = which;
Toast.makeText(getApplicationContext(), items[which], Toast.LENGTH_SHORT).show();
}
});
builder.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
builder.setPositiveButton("Confirm", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
SlideApplication.SLIDE_TIME = Integer.parseInt(items[timeCheck].split("초")[0]);
mTvTime.setText(Integer.toString(SlideApplication.SLIDE_TIME));
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
// Effect Setting
else if (v == mBtnEffect) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
final String[] items = {"None", "FadeIn", "Rotate", "SlideIn"};
if (SlideApplication.SLIDE_EFFECT == SlideShow.NONE) effectCheck = 0;
else if (SlideApplication.SLIDE_EFFECT == SlideShow.FADE_IN) effectCheck = 1;
else if (SlideApplication.SLIDE_EFFECT == SlideShow.ROTATE) effectCheck = 2;
else if (SlideApplication.SLIDE_EFFECT == SlideShow.SLIDE_IN) effectCheck = 3;
builder.setSingleChoiceItems(items, effectCheck, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
effectCheck = which;
Toast.makeText(getApplicationContext(), items[which], Toast.LENGTH_SHORT).show();
}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
builder.setPositiveButton("Confirm", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
SlideApplication.SLIDE_EFFECT = effectCheck;
mTvEffect.setText(items[SlideApplication.SLIDE_EFFECT]);
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
// Next
else if (v == mBtnNext) {
new BitmapChangerTask().execute();
}
// Prev
else if (v == mBtnPrev) {
finish();
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1) {
if (resultCode == RESULT_OK) {
if (data != null && data.getStringExtra("bgm_path") != null) {
SlideApplication.BGM_PATH = data.getStringExtra("bgm_path");
}
}
}
}
private class BitmapChangerTask extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... params) {
for (int i = 0; i < mParcelableUris.length; i++) {
try {
Bitmap bm = Glide.with(getApplicationContext()).load(mParcelableUris[i].toString())
.asBitmap()
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
.get();
int width = bm.getWidth();
int height = bm.getHeight();
// Land ( 1280 x 720 )
if (width > height) {
bm = Bitmap.createScaledBitmap(bm, SlideEncoder.WIDTH, ((SlideEncoder.WIDTH * height) / width), true);
}
// Port ( 720 x 1280 )
else if (width < height) {
bm = Bitmap.createScaledBitmap(bm, ((SlideEncoder.HEIGHT * width) / height), SlideEncoder.HEIGHT, true);
}
// Square ( 800 x 800 )
else {
bm = Bitmap.createScaledBitmap(bm, SlideEncoder.WIDTH, SlideEncoder.HEIGHT, true);
}
SlideApplication.bitmapList.add(bm);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
Intent i = new Intent(getApplicationContext(), EncodingActivity.class);
startActivity(i);
}
}
private class CustomPageAdapter extends PagerAdapter {
@Override
public int getCount() {
return mParcelableUris.length;
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
ImageView iv = new ImageView(getApplicationContext());
Glide.with(getApplicationContext())
.load(mParcelableUris[position].toString())
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(iv);
try {
container.addView(iv);
} catch (IllegalStateException ise) {
ise.printStackTrace();
}
return iv;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
}
}
EffectActivity.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:id="@+id/pager_image"
android:layout_width="match_parent"
android:layout_height="350dp">
</android.support.v4.view.ViewPager>
<Button
android:id="@+id/btn_bgm"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/pager_image"
android:layout_marginStart="80dp"
android:layout_marginTop="30dp"
android:text="BitRate"/>
<TextView
android:id="@+id/tv_bitrate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/btn_bgm"
android:layout_alignParentEnd="true"
android:layout_below="@+id/pager_image"
android:layout_marginEnd="80dp"
android:singleLine="true"
android:ellipsize="marquee"
android:text="500Kbps"
android:textSize="20dp"/>
<Button
android:id="@+id/btn_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/btn_bgm"
android:layout_marginStart="80dp"
android:text="time"/>
<TextView
android:id="@+id/tv_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/btn_time"
android:layout_alignParentEnd="true"
android:layout_below="@+id/pager_image"
android:layout_marginEnd="80dp"
android:text="2s"
android:textSize="20dp"/>
<Button
android:id="@+id/btn_effect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/btn_time"
android:layout_marginStart="80dp"
android:text="EFFECT"/>
<TextView
android:id="@+id/tv_effect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/btn_effect"
android:layout_alignParentEnd="true"
android:layout_below="@+id/pager_image"
android:layout_marginEnd="80dp"
android:text="none"
android:textSize="20dp"/>
<Button
android:id="@+id/btn_prev"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
android:text="Previous"/>
<Button
android:id="@+id/btn_next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:text="NEXT"/>
</RelativeLayout>
<强> EncodingActivity.java 强>
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import com.hini.slideshow.SlideApplication;
import com.hini.slideshow.draw.SlideShow;
import com.hini.slideshow.encoding.SlideEncoder;
import java.io.File;
import java.io.IOException;
public class EncodingActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new EncodingTask().execute();
}
class EncodingTask extends AsyncTask<Void, String, Void> {
File f = new File(Environment.getExternalStorageDirectory().getAbsolutePath()
+ "/test_" + SlideApplication.BIT_RATE / 1024 + "_" + SlideApplication.SLIDE_EFFECT + ".mp4");
ProgressDialog dialog;
@Override
protected void onPreExecute() {
super.onPreExecute();
dialog = new ProgressDialog(EncodingActivity.this);
dialog.setTitle("Generating Video..");
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dialog.setCancelable(false);
dialog.show();
}
@Override
protected Void doInBackground(Void... params) {
long startTime = System.currentTimeMillis();
if (f.exists()) f.delete();
SlideEncoder slideEncoder = new SlideEncoder();
try {
slideEncoder.prepareEncoder(f);
Bitmap prevBm = null;
dialog.setMax(SlideApplication.bitmapList.size());
for (int idx = 0; idx < SlideApplication.bitmapList.size(); idx++) {
publishProgress(String.valueOf(idx + 1));
SlideShow.init();
if (idx > 0) prevBm = SlideApplication.bitmapList.get(idx - 1);
Bitmap curBm = SlideApplication.bitmapList.get(idx);
for (int i = 0; i < (SlideApplication.FRAME_PER_SEC * SlideApplication.SLIDE_TIME); i++) {
// Drain any data from the encoder into the muxer.
slideEncoder.drainEncoder(false);
// Generate a frame and submit it.
slideEncoder.generateFrame(prevBm, curBm);
}
}
slideEncoder.drainEncoder(true);
} catch (IOException e) {
e.printStackTrace();
} finally {
slideEncoder.releaseEncoder();
}
Log.e("TAG", "total time : " + (System.currentTimeMillis() - startTime));
return null;
}
@Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
dialog.setProgress(Integer.parseInt(values[0]));
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
if (dialog.isShowing()) dialog.dismiss();
for (Bitmap bm : SlideApplication.bitmapList) bm.recycle();
SlideApplication.bitmapList.clear();
Intent i = new Intent(EncodingActivity.this, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
}
}
*****SlideEncoder.java*****
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.media.MediaMuxer;
import android.view.Surface;
import com.hini.slideshow.SlideApplication;
import com.hini.slideshow.draw.SlideShow;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
public class SlideEncoder {
private static final String MIME_TYPE = MediaFormat.MIMETYPE_VIDEO_AVC;
public static final int WIDTH = 800;
public static final int HEIGHT = 800;
private static final int IFRAME_INTERVAL = 3;
private MediaCodec.BufferInfo mBufferInfo;
private MediaCodec mEncoder;
private Surface mInputSurface;
private MediaMuxer mMuxer;
private int mTrackIndex;
private boolean mMuxerStarted;
private long mFakePts;
void prepareEncoder(File outputFile) throws IOException {
mBufferInfo = new MediaCodec.BufferInfo();
MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, WIDTH, HEIGHT);
// Set some properties. Failing to specify some of these can cause the MediaCodec
// configure() call to throw an unhelpful exception.
format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
format.setInteger(MediaFormat.KEY_BIT_RATE, SlideApplication.BIT_RATE);
format.setInteger(MediaFormat.KEY_FRAME_RATE, SlideApplication.FRAME_PER_SEC);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
// Create a MediaCodec encoder, and configure it with our format. Get a Surface
// we can use for input and wrap it with a class that handles the EGL work.
mEncoder = MediaCodec.createEncoderByType(MIME_TYPE);
mEncoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
mInputSurface = mEncoder.createInputSurface();
mEncoder.start();
// Create a MediaMuxer. We can't add the video track and start() the muxer here,
// because our MediaFormat doesn't have the Magic Goodies. These can only be
// obtained from the encoder after it has started processing data.
//
// We're not actually interested in multiplexing audio. We just want to convert
// the raw H.264 elementary stream we get from MediaCodec into a .mp4 file.
mMuxer = new MediaMuxer(outputFile.toString(),
MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
mTrackIndex = -1;
mMuxerStarted = false;
}
/**
* MediaCodec, InputSurface, MediaMuxer 해제
*/
public void releaseEncoder() {
if (mEncoder != null) {
mEncoder.stop();
mEncoder.release();
mEncoder = null;
}
if (mInputSurface != null) {
mInputSurface.release();
mInputSurface = null;
}
if (mMuxer != null) {
mMuxer.stop();
mMuxer.release();
mMuxer = null;
}
}
/**
* Extracts all pending data from the encoder.
* <p/>
* If endOfStream is not set, this returns when there is no more data to drain. If it
* is set, we send EOS to the encoder, and then iterate until we see EOS on the output.
* Calling this with endOfStream set should be done once, right before stopping the muxer.
*/
public void drainEncoder(boolean endOfStream) {
final int TIMEOUT_USEC = 10000;
if (endOfStream) {
mEncoder.signalEndOfInputStream();
}
ByteBuffer[] encoderOutputBuffers = mEncoder.getOutputBuffers();
while (true) {
int encoderStatus = mEncoder.dequeueOutputBuffer(mBufferInfo, TIMEOUT_USEC);
if (encoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) {
// no output available yet
if (!endOfStream) {
break; // out of while
} else {
}
} else if (encoderStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
// not expected for an encoder
encoderOutputBuffers = mEncoder.getOutputBuffers();
} else if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
// should happen before receiving buffers, and should only happen once
if (mMuxerStarted) {
throw new RuntimeException("format changed twice");
}
MediaFormat newFormat = mEncoder.getOutputFormat();
// now that we have the Magic Goodies, start the muxer
mTrackIndex = mMuxer.addTrack(newFormat);
mMuxer.start();
mMuxerStarted = true;
} else if (encoderStatus < 0) {
// let's ignore it
} else {
ByteBuffer encodedData = encoderOutputBuffers[encoderStatus];
if (encodedData == null) {
throw new RuntimeException("encoderOutputBuffer " + encoderStatus +
" was null");
}
if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
// The codec config data was pulled out and fed to the muxer when we got
// the INFO_OUTPUT_FORMAT_CHANGED status. Ignore it.
mBufferInfo.size = 0;
}
if (mBufferInfo.size != 0) {
if (!mMuxerStarted) {
throw new RuntimeException("muxer hasn't started");
}
// adjust the ByteBuffer values to match BufferInfo
encodedData.position(mBufferInfo.offset);
encodedData.limit(mBufferInfo.offset + mBufferInfo.size);
mBufferInfo.presentationTimeUs = mFakePts;
long timeStampLength = 1000000L / SlideApplication.FRAME_PER_SEC;
mFakePts += timeStampLength;
mMuxer.writeSampleData(mTrackIndex, encodedData, mBufferInfo);
}
mEncoder.releaseOutputBuffer(encoderStatus, false);
if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
if (!endOfStream) {
} else {
}
break; // out of while
}
}
}
}
/**
* Generates a frame, writing to the Surface via the "software" API (lock/unlock).
* <p/>
* There's no way to set the time stamp.
*/
public void generateFrame(Bitmap prevBm, Bitmap curBm) {
Canvas canvas = mInputSurface.lockCanvas(null);
try {
SlideShow.draw(canvas, prevBm, curBm);
} finally {
mInputSurface.unlockCanvasAndPost(canvas);
}
}
}
<强> SlideShow.java 强>
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import com.appwallet.slideshow.SlideApplication;
import com.appwallet.slideshow.encoding.SlideEncoder;
public class SlideShow {
// effect
public static final int NONE = 0;
public static final int FADE_IN = 1;
public static final int ROTATE = 2;
public static final int SLIDE_IN = 3;
// 위치
private static int curStartX;
private static int curStartY;
private static int prevStartX;
private static int prevStartY;
//Variables used for effect
private static float in_alpha = 0f;
private static float rotate = 0;
private static int slideX = SlideEncoder.WIDTH;
private static int slideCount = 1;
private static float out_alpha = 255f;
/**
*
* @param canvas canvas
* @param prevBm Background Bitmap
* @param curBm Foregound Bitmap
*/
public static void draw(Canvas canvas, Bitmap prevBm, Bitmap curBm) {
if (canvas == null || curBm == null) return;
setLocation(prevBm, curBm);
if (SlideApplication.SLIDE_EFFECT == ROTATE && prevBm == null)
canvas.drawColor(Color.BLACK);
if (prevBm != null) drawFadeOut(canvas, prevBm);
switch (SlideApplication.SLIDE_EFFECT) {
case NONE:
drawNone(canvas, curBm);
break;
case FADE_IN:
drawFadeIn(canvas, curBm);
break;
case ROTATE:
drawRotate(canvas, curBm);
break;
case SLIDE_IN:
drawSlideIn(canvas, curBm);
break;
default:
throw new IllegalStateException("unexpected state");
}
}
/*
*Adjust position according to figure
* @param prevBm Background Bitmap
* @param curBm Foreground Bitmap
*/
private static void setLocation(Bitmap prevBm, Bitmap curBm) {
if (curBm != null) {
int cWidth = curBm.getWidth();
int cHeight = curBm.getHeight();
if (cWidth > cHeight) {
curStartX = 0;
curStartY = (SlideEncoder.HEIGHT - cHeight) / 2;
} else if (cHeight > cWidth) {
curStartX = (SlideEncoder.WIDTH - cWidth) / 2;
curStartY = 0;
} else {
curStartX = 0;
curStartY = 0;
}
}
if (prevBm != null) {
int pWidth = prevBm.getWidth();
int pHeight = prevBm.getHeight();
if (pWidth > pHeight) {
prevStartX = 0;
prevStartY = (SlideEncoder.HEIGHT - pHeight) / 2;
} else if (pHeight > pWidth) {
prevStartX = (SlideEncoder.WIDTH - pWidth) / 2;
prevStartY = 0;
} else {
prevStartX = 0;
prevStartY = 0;
}
}
}
/**
*/
public static void init() {
in_alpha = 0f;
out_alpha = 255f;
rotate = 0f;
slideX = 800;
slideCount = 1;
curStartX = 0;
curStartY = 0;
prevStartX = 0;
prevStartY = 0;
}
/**
* drawNone
*
* @param c canvas
* @param bm bitmap
*/
private static void drawNone(Canvas c, Bitmap bm) {
c.drawBitmap(bm, curStartX, curStartY, null);
}
* Fade in effect *
private static void drawFadeIn(Canvas c, Bitmap bm) {
Paint p = new Paint();
int ratio = (int) Math.ceil(255 / SlideApplication.FRAME_PER_SEC);
in_alpha += ratio;
if (in_alpha > 255f) in_alpha = 255f;
p.setAlpha((int) in_alpha);
c.drawBitmap(bm, curStartX, curStartY, p);
}
Rotate effect
private static void drawRotate(Canvas c, Bitmap bm) {
Matrix matrix = new Matrix();
matrix.preTranslate(curStartX, curStartY);
float ratio = 360 / SlideApplication.FRAME_PER_SEC;
rotate += Math.ceil(ratio);
if (rotate > 360) rotate = 360;
matrix.postRotate(rotate, SlideEncoder.WIDTH / 2, SlideEncoder.HEIGHT / 2);
c.drawBitmap(bm, matrix, null);
}
/**
* drawSlideIn drawSlideIn
*
* @param c canvas
* @param bm bitmap
*/
private static void drawSlideIn(Canvas c, Bitmap bm) {
Matrix matrix = new Matrix();
int ratio = 1;
if (slideCount < 30) ratio = (int) Math.pow(slideCount++, 1.4);
slideX -= ratio;
if (slideX < curStartX) slideX = curStartX;
matrix.setTranslate(slideX, curStartY);
c.drawBitmap(bm, matrix, null);
}
/**
*
Fade-out effect (applies only to pictures that are drawn behind)
*
* @param c canvas
* @param bm bitmap
*/
private static void drawFadeOut(Canvas c, Bitmap bm) {
c.drawColor(Color.BLACK);
Paint p = new Paint();
int ratio = (int) Math.ceil(255 / SlideApplication.FRAME_PER_SEC);
out_alpha -= ratio;
if (out_alpha < 0f) out_alpha = 0f;
p.setAlpha((int) out_alpha);
c.drawBitmap(bm, prevStartX, prevStartY, p);
}
}
SlideApplication.java(保存变量)
import android.app.Application;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Parcelable;
import android.view.View;
import com.appwallet.slideshow.draw.SlideShow;
import java.util.ArrayList;
public class SlideApplication extends Application {
public static String BGM_PATH = "";
public static int SLIDE_TIME = 2;
public static int SLIDE_EFFECT = SlideShow.NONE;
public static int BIT_RATE = 2000 * 1024;
public static int FRAME_PER_SEC = 30;
public static ArrayList<Bitmap> bitmapList = new ArrayList<>();
public static int overlayEffect=0;
public static Parcelable[] images;
public static String deleteFolderPath;
}