├── .gitignore ├── LICENSE ├── README.md ├── app ├── .gitignore ├── app.iml ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── hw │ │ └── photomovie │ │ └── app │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── hw │ │ └── photomovie │ │ └── sample │ │ ├── DemoActivity.java │ │ ├── DemoPresenter.java │ │ ├── IDemoView.java │ │ ├── TestFilterRenderer.java │ │ ├── UilPhotoData.java │ │ ├── UriUtil.java │ │ ├── activityAnim │ │ ├── ActivityAnimSegment.java │ │ ├── ActivityMovieRenderer.java │ │ └── AnimActivity.java │ │ └── widget │ │ ├── FilterHolder.java │ │ ├── FilterItem.java │ │ ├── FilterType.java │ │ ├── MovieBottomView.java │ │ ├── MovieFilterView.java │ │ ├── MovieTransferView.java │ │ ├── SpaceItemDecoration.java │ │ └── TransferItem.java │ ├── res │ ├── drawable-nodpi │ │ ├── cameo.jpg │ │ ├── cancel_click.png │ │ ├── filter_default.jpg │ │ ├── gray.jpg │ │ ├── kuwahara.jpg │ │ ├── l1.jpg │ │ ├── l2.jpg │ │ ├── l3.jpg │ │ ├── l4.jpg │ │ ├── l5.jpg │ │ └── snow.jpg │ ├── drawable-v21 │ │ └── movie_next_shape.xml │ ├── drawable-xxhdpi │ │ └── watermark.png │ ├── drawable │ │ ├── ic_add.xml │ │ ├── ic_add_frame.xml │ │ ├── ic_check.xml │ │ ├── ic_filter_check_shape.xml │ │ ├── ic_movie_filter.xml │ │ ├── ic_movie_music.xml │ │ ├── ic_movie_transfer.xml │ │ ├── movie_next_shape.xml │ │ └── movie_text_cover.xml │ ├── layout │ │ ├── activity_demo.xml │ │ ├── demo_bottom_layout.xml │ │ ├── demo_filter_item.xml │ │ ├── demo_filter_layout.xml │ │ ├── demo_transfer_item.xml │ │ └── demo_transfer_layout.xml │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ ├── raw │ │ ├── bg.mid │ │ └── dynamic_window_segment.jar │ ├── values-w820dp │ │ └── dimens.xml │ ├── values-zh-rCN │ │ └── strings.xml │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── stringarray.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── uml │ └── PhotoMovie.uml ├── build.gradle ├── dynamicdemo ├── .gitignore ├── build.gradle ├── dynamicdemo.iml ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── hw │ │ └── dynamicdemo │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── hw │ └── dynamicdemo │ └── DynamicWindowSegment.java ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── library ├── .gitignore ├── build.gradle ├── library.iml ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── hw │ │ └── photomovie │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── assets │ ├── lut │ │ ├── lut_1.jpg │ │ ├── lut_2.jpg │ │ ├── lut_3.jpg │ │ ├── lut_4.jpg │ │ ├── lut_5.jpg │ │ └── lut_default.png │ └── shader │ │ ├── base.glsl │ │ ├── lut.glsl │ │ ├── snow.glsl │ │ ├── two_fragment.glsl │ │ └── two_vertex.glsl │ ├── java │ └── com │ │ └── hw │ │ └── photomovie │ │ ├── PhotoMovie.java │ │ ├── PhotoMovieFactory.java │ │ ├── PhotoMoviePlayer.java │ │ ├── dynamic │ │ └── DynamicLoader.java │ │ ├── filter │ │ ├── AlphaFilter.java │ │ ├── AlphaGradientFilter.java │ │ ├── BetweenLinesFilter.java │ │ ├── GLHelper.java │ │ ├── GrayFilter.java │ │ ├── MovieFilter.java │ │ └── OldMovieFilter.java │ │ ├── model │ │ ├── ErrorReason.java │ │ ├── PhotoData.java │ │ ├── PhotoInfo.java │ │ ├── PhotoSource.java │ │ └── SimplePhotoData.java │ │ ├── moviefilter │ │ ├── BaseMovieFilter.java │ │ ├── CameoMovieFilter.java │ │ ├── GrayMovieFilter.java │ │ ├── IMovieFilter.java │ │ ├── KuwaharaMovieFilter.java │ │ ├── LutMovieFilter.java │ │ ├── SnowMovieFilter.java │ │ └── TwoTextureMovieFilter.java │ │ ├── music │ │ ├── IMusicPlayer.java │ │ └── MusicPlayer.java │ │ ├── opengl │ │ ├── BasicTexture.java │ │ ├── BitmapTexture.java │ │ ├── CanvasTexture.java │ │ ├── ColorTexture.java │ │ ├── ExtTexture.java │ │ ├── FadeInTexture.java │ │ ├── FadeOutTexture.java │ │ ├── FadeTexture.java │ │ ├── FboTexture.java │ │ ├── GLES11Canvas.java │ │ ├── GLES11IdImpl.java │ │ ├── GLES20Canvas.java │ │ ├── GLES20IdImpl.java │ │ ├── GLESCanvas.java │ │ ├── GLId.java │ │ ├── GLPaint.java │ │ ├── MGLES20Canvas.java │ │ ├── MultiLineTexture.java │ │ ├── NinePatchChunk.java │ │ ├── RawTexture.java │ │ ├── ScreenNail.java │ │ ├── StringTexture.java │ │ ├── Texture.java │ │ ├── UploadedTexture.java │ │ └── animations │ │ │ ├── AlphaAnim.java │ │ │ ├── Animation.java │ │ │ ├── AnimationTime.java │ │ │ ├── CanvasAnim.java │ │ │ ├── CaptureAnim.java │ │ │ ├── FloatAnim.java │ │ │ └── IntegerAnim.java │ │ ├── record │ │ ├── AudioRecordThread.java │ │ ├── GLMovieRecorder.java │ │ ├── PcmToWavUtil.java │ │ └── gles │ │ │ ├── Drawable2d.java │ │ │ ├── EglCore.java │ │ │ ├── EglSurfaceBase.java │ │ │ ├── FlatShadedProgram.java │ │ │ ├── FullFrameRect.java │ │ │ ├── GeneratedTexture.java │ │ │ ├── GlUtil.java │ │ │ ├── OffscreenSurface.java │ │ │ ├── Sprite2d.java │ │ │ ├── Texture2dProgram.java │ │ │ └── WindowSurface.java │ │ ├── render │ │ ├── GLMovieRenderer.java │ │ ├── GLSurfaceMovieRenderer.java │ │ ├── GLTextureMovieRender.java │ │ ├── GLTextureView.java │ │ └── MovieRenderer.java │ │ ├── segment │ │ ├── AbsLayerSegment.java │ │ ├── BitmapInfo.java │ │ ├── EndGaussianBlurSegment.java │ │ ├── FitCenterScaleSegment.java │ │ ├── FitCenterSegment.java │ │ ├── GLMovieSegment.java │ │ ├── GradientSegment.java │ │ ├── GradientTransferSegment.java │ │ ├── LayerSegment.java │ │ ├── MoveTransitionSegment.java │ │ ├── MovieSegment.java │ │ ├── MulitBitmapSegment.java │ │ ├── ScaleSegment.java │ │ ├── ScaleTransSegment.java │ │ ├── SingleBitmapSegment.java │ │ ├── TestLayerSegment.java │ │ ├── TestMovieSegment.java │ │ ├── ThawSegment.java │ │ ├── TransitionSegment.java │ │ ├── WaterMarkSegment.java │ │ ├── WindowSegment.java │ │ ├── animation │ │ │ ├── DstAnimation.java │ │ │ ├── DstScaleAnimation.java │ │ │ ├── DstTransAnimation.java │ │ │ ├── SegmentAnimation.java │ │ │ ├── SrcAnimation.java │ │ │ ├── SrcLeftRightAnimation.java │ │ │ ├── SrcScaleAnimation.java │ │ │ └── SrcTransAnimation.java │ │ ├── layer │ │ │ ├── AvailableRect.java │ │ │ ├── GaussianBlurLayer.java │ │ │ ├── MovieLayer.java │ │ │ ├── MovieTextLayer.java │ │ │ ├── ScaleTransLayer.java │ │ │ ├── SubtitleLayer.java │ │ │ ├── TestBaseLayer.java │ │ │ └── TestMuiltBitmapLayer.java │ │ └── strategy │ │ │ ├── NotRetryStrategy.java │ │ │ ├── ReallocStrategy.java │ │ │ └── RetryStrategy.java │ │ ├── timer │ │ ├── IMovieTimer.java │ │ └── MovieTimer.java │ │ └── util │ │ ├── AppResources.java │ │ ├── BitmapUtil.java │ │ ├── GLUtil.java │ │ ├── IntArray.java │ │ ├── MLog.java │ │ ├── PhotoUtil.java │ │ ├── ScaleType.java │ │ ├── SystemPropertiesUtil.java │ │ ├── Utils.java │ │ └── stackblur │ │ ├── BlurProcess.java │ │ ├── JavaBlurProcess.java │ │ └── StackBlurManager.java │ └── res │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── readme ├── PhotoMovie.png ├── filter.gif ├── gradient.gif ├── gradient_timeline.png └── transfer.gif └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /local.properties 3 | /.idea/workspace.xml 4 | /.idea/libraries 5 | /.idea 6 | .DS_Store 7 | /build 8 | *.iml 9 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /local.properties 3 | /.idea/workspace.xml 4 | /.idea/libraries 5 | /.idea 6 | .DS_Store 7 | /build 8 | *.iml 9 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | jcenter() 4 | google() 5 | } 6 | dependencies { 7 | classpath 'com.android.tools.build:gradle:3.2.1' 8 | } 9 | } 10 | apply plugin: 'com.android.application' 11 | 12 | repositories { 13 | jcenter() 14 | } 15 | 16 | android { 17 | compileSdkVersion 27 18 | buildToolsVersion '27.0.3' 19 | 20 | defaultConfig { 21 | applicationId "com.hw.photomovie" 22 | minSdkVersion 14 23 | targetSdkVersion 19 24 | versionCode 1 25 | versionName "1.0" 26 | vectorDrawables.useSupportLibrary true 27 | } 28 | 29 | compileOptions { 30 | sourceCompatibility JavaVersion.VERSION_1_6 31 | targetCompatibility JavaVersion.VERSION_1_6 32 | } 33 | buildTypes { 34 | release { 35 | minifyEnabled false 36 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 37 | } 38 | } 39 | if (RunForEmulator) { 40 | splits { 41 | abi { 42 | enable true 43 | reset() 44 | include 'x86', 'arm64-v8a', 'armeabi-v7a', 'x86_64' 45 | universalApk true 46 | } 47 | } 48 | } 49 | } 50 | 51 | dependencies { 52 | compile fileTree(include: ['*.jar'], dir: 'libs') 53 | implementation project(':library') 54 | implementation 'com.android.support:appcompat-v7:27.1.1' 55 | implementation 'com.android.support.constraint:constraint-layout:1.0.2' 56 | implementation 'com.android.support:recyclerview-v7:27.1.1' 57 | implementation 'de.hdodenhof:circleimageview:2.1.0' 58 | implementation 'me.iwf.photopicker:PhotoPicker:0.9.12@aar' 59 | compile 'com.github.bumptech.glide:glide:4.1.1' 60 | implementation 'com.android.support:design:27.1.1' 61 | } 62 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:/ADT/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/hw/photomovie/app/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 16 | 18 | 19 | 20 | 21 | 22 | 23 | 27 | 28 | 29 | 32 | 33 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/hw/photomovie/sample/IDemoView.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.sample; 2 | 3 | import android.app.Activity; 4 | import com.hw.photomovie.render.GLTextureView; 5 | import com.hw.photomovie.sample.widget.FilterItem; 6 | import com.hw.photomovie.sample.widget.TransferItem; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * Created by huangwei on 2018/9/9. 12 | */ 13 | public interface IDemoView { 14 | public GLTextureView getGLView(); 15 | void setFilters(List filters); 16 | Activity getActivity(); 17 | 18 | void setTransfers(List items); 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/hw/photomovie/sample/activityAnim/ActivityAnimSegment.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.sample.activityAnim; 2 | 3 | import android.app.Activity; 4 | import android.widget.TextView; 5 | import com.hw.photomovie.segment.MovieSegment; 6 | 7 | /** 8 | * Created by huangwei on 2015/7/1. 9 | */ 10 | public class ActivityAnimSegment extends MovieSegment { 11 | 12 | private float mTransX, mTransY; 13 | private float mStepX, mStepY; 14 | 15 | @Override 16 | protected boolean checkPrepared() { 17 | return false; 18 | } 19 | 20 | @Override 21 | protected void onPrepare() { 22 | mTransX = mTransY = 0; 23 | mStepX = getRanStep(); 24 | mStepY = getRanStep(); 25 | if (mOnSegmentPrepareListener != null) { 26 | mOnSegmentPrepareListener.onSegmentPrepared(true); 27 | } 28 | onDataPrepared(); 29 | } 30 | 31 | @Override 32 | protected void onDataPrepared() { 33 | 34 | } 35 | 36 | @Override 37 | public void drawFrame(Activity painter, float segmentProgress) { 38 | TextView textView = (TextView) painter.findViewById(android.R.id.content).findViewWithTag("text"); 39 | textView.setRotation(segmentProgress * 7200); 40 | 41 | int maxX = (int) (mViewportRect.width() / 2); 42 | int maxY = (int) (mViewportRect.height() / 2); 43 | 44 | if (!(mTransX > -maxX && mTransX < maxX)) { 45 | mStepX = getRanStep(); 46 | mStepX = mTransX > 0 ? -mStepX : mStepX; 47 | } 48 | mTransX += mStepX; 49 | 50 | if (!(mTransY > -maxY && mTransY < maxY)) { 51 | mStepY = getRanStep(); 52 | mStepY = mTransY > 0 ? -mStepY : mStepY; 53 | } 54 | mTransY += mStepY; 55 | 56 | textView.setTranslationX(mTransX); 57 | textView.setTranslationY(mTransY); 58 | } 59 | 60 | private float getRanStep() { 61 | return (float) Math.abs(Math.random() * 40 - 20); 62 | } 63 | 64 | @Override 65 | public int getRequiredPhotoNum() { 66 | return 0; 67 | } 68 | 69 | @Override 70 | protected void onRelease() { 71 | 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /app/src/main/java/com/hw/photomovie/sample/activityAnim/ActivityMovieRenderer.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.sample.activityAnim; 2 | 3 | import android.app.Activity; 4 | import android.graphics.Bitmap; 5 | import android.graphics.Rect; 6 | import android.util.DisplayMetrics; 7 | import com.hw.photomovie.render.MovieRenderer; 8 | import com.hw.photomovie.segment.MovieSegment; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * Created by huangwei on 2015/7/1. 14 | */ 15 | public class ActivityMovieRenderer extends MovieRenderer { 16 | @Override 17 | public void drawFrame(int elapsedTime) { 18 | drawMovieFrame(elapsedTime); 19 | } 20 | 21 | @Override 22 | public MovieRenderer setPainter(Activity painter) { 23 | DisplayMetrics displayMetrics = painter.getResources().getDisplayMetrics(); 24 | setMovieViewport(0,0,displayMetrics.widthPixels,displayMetrics.heightPixels); 25 | return super.setPainter(painter); 26 | } 27 | 28 | @Override 29 | public void release() { 30 | 31 | } 32 | 33 | @Override 34 | public void release(List> movieSegments) { 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/hw/photomovie/sample/activityAnim/AnimActivity.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.sample.activityAnim; 2 | 3 | import android.app.Activity; 4 | import android.graphics.Color; 5 | import android.os.Bundle; 6 | import android.util.TypedValue; 7 | import android.view.Gravity; 8 | import android.widget.FrameLayout; 9 | import android.widget.TextView; 10 | import com.hw.photomovie.PhotoMovie; 11 | import com.hw.photomovie.PhotoMoviePlayer; 12 | import com.hw.photomovie.model.PhotoSource; 13 | import com.hw.photomovie.sample.R; 14 | import com.hw.photomovie.segment.MovieSegment; 15 | import com.hw.photomovie.util.MLog; 16 | 17 | import java.util.ArrayList; 18 | import java.util.List; 19 | 20 | /** 21 | * Created by huangwei on 2015/7/1. 22 | */ 23 | public class AnimActivity extends Activity{ 24 | 25 | private TextView mTextView; 26 | 27 | @Override 28 | protected void onCreate(Bundle savedInstanceState) { 29 | super.onCreate(savedInstanceState); 30 | FrameLayout layout = new FrameLayout(this); 31 | layout.setBackgroundColor(Color.WHITE); 32 | setContentView(layout); 33 | 34 | mTextView = new TextView(this); 35 | mTextView.setText("testtesttest"); 36 | mTextView.setTextColor(Color.BLUE); 37 | mTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 30); 38 | mTextView.setTag("text"); 39 | mTextView.setGravity(Gravity.CENTER); 40 | layout.addView(mTextView,FrameLayout.LayoutParams.MATCH_PARENT,FrameLayout.LayoutParams.MATCH_PARENT); 41 | 42 | List> segments = new ArrayList>(); 43 | segments.add(new ActivityAnimSegment().setDuration(15000)); 44 | PhotoMovie photoMovie = new PhotoMovie(new PhotoSource(null),segments); 45 | 46 | final PhotoMoviePlayer photoMoviePlayer = new PhotoMoviePlayer(getApplicationContext()); 47 | photoMoviePlayer.setMovieRenderer(new ActivityMovieRenderer().setPainter(this)); 48 | photoMoviePlayer.setMusic(getResources().openRawResourceFd(R.raw.bg).getFileDescriptor()); 49 | photoMoviePlayer.setDataSource(photoMovie); 50 | photoMoviePlayer.setOnPreparedListener(new PhotoMoviePlayer.OnPreparedListener() { 51 | @Override 52 | public void onPreparing(PhotoMoviePlayer moviePlayer, float progress) { 53 | MLog.i("onPrepare", "" + progress); 54 | } 55 | 56 | @Override 57 | public void onPrepared(PhotoMoviePlayer moviePlayer, int prepared, int total) { 58 | MLog.i("onPrepare", "prepared:" + prepared + " total:" + total); 59 | photoMoviePlayer.start(); 60 | } 61 | 62 | @Override 63 | public void onError(PhotoMoviePlayer moviePlayer) { 64 | MLog.i("onPrepare", "onPrepare error"); 65 | } 66 | }); 67 | photoMoviePlayer.prepare(); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /app/src/main/java/com/hw/photomovie/sample/widget/FilterHolder.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.sample.widget; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.view.View; 5 | 6 | /** 7 | * Created by huangwei on 2018/9/9. 8 | */ 9 | public class FilterHolder extends RecyclerView.ViewHolder { 10 | public FilterHolder(View itemView) { 11 | super(itemView); 12 | } 13 | 14 | 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/hw/photomovie/sample/widget/FilterItem.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.sample.widget; 2 | 3 | import com.hw.photomovie.filter.GrayFilter; 4 | import com.hw.photomovie.moviefilter.CameoMovieFilter; 5 | import com.hw.photomovie.moviefilter.GrayMovieFilter; 6 | import com.hw.photomovie.moviefilter.IMovieFilter; 7 | import com.hw.photomovie.moviefilter.KuwaharaMovieFilter; 8 | import com.hw.photomovie.moviefilter.LutMovieFilter; 9 | import com.hw.photomovie.moviefilter.SnowMovieFilter; 10 | 11 | /** 12 | * Created by huangwei on 2018/9/9. 13 | */ 14 | public class FilterItem { 15 | 16 | public FilterItem(int imgRes, String name, FilterType type) { 17 | this.imgRes = imgRes; 18 | this.name = name; 19 | this.type = type; 20 | } 21 | 22 | public int imgRes; 23 | public String name; 24 | public FilterType type; 25 | 26 | public IMovieFilter initFilter() { 27 | switch (type) { 28 | case GRAY: 29 | return new GrayMovieFilter(); 30 | case SNOW: 31 | return new SnowMovieFilter(); 32 | case CAMEO: 33 | return new CameoMovieFilter(); 34 | case KUWAHARA: 35 | return new KuwaharaMovieFilter(); 36 | case LUT1: 37 | return new LutMovieFilter(LutMovieFilter.LutType.A); 38 | case LUT2: 39 | return new LutMovieFilter(LutMovieFilter.LutType.B); 40 | case LUT3: 41 | return new LutMovieFilter(LutMovieFilter.LutType.C); 42 | case LUT4: 43 | return new LutMovieFilter(LutMovieFilter.LutType.D); 44 | case LUT5: 45 | return new LutMovieFilter(LutMovieFilter.LutType.E); 46 | case NONE: 47 | default: 48 | return null; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/java/com/hw/photomovie/sample/widget/FilterType.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.sample.widget; 2 | 3 | /** 4 | * Created by huangwei on 2018/9/9. 5 | */ 6 | public enum FilterType { 7 | NONE, 8 | CAMEO,//浮雕 9 | GRAY,//黑白 10 | KUWAHARA,//水彩 11 | SNOW,//飘雪 12 | LUT1, 13 | LUT2, 14 | LUT3, 15 | LUT4, 16 | LUT5, 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/hw/photomovie/sample/widget/MovieBottomView.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.sample.widget; 2 | 3 | import android.content.Context; 4 | import android.support.constraint.ConstraintLayout; 5 | import android.util.AttributeSet; 6 | import android.view.View; 7 | import com.hw.photomovie.sample.R; 8 | 9 | /** 10 | * Created by huangwei on 2018/9/9. 11 | */ 12 | public class MovieBottomView extends ConstraintLayout implements View.OnClickListener { 13 | 14 | private MovieBottomCallback mCallback; 15 | 16 | public MovieBottomView(Context context) { 17 | super(context); 18 | } 19 | 20 | public MovieBottomView(Context context, AttributeSet attrs) { 21 | super(context, attrs); 22 | } 23 | 24 | public MovieBottomView(Context context, AttributeSet attrs, int defStyleAttr) { 25 | super(context, attrs, defStyleAttr); 26 | } 27 | 28 | @Override 29 | protected void onFinishInflate() { 30 | super.onFinishInflate(); 31 | findViewById(R.id.movie_next).setOnClickListener(this); 32 | findViewById(R.id.movie_filter).setOnClickListener(this); 33 | findViewById(R.id.movie_filter_txt).setOnClickListener(this); 34 | findViewById(R.id.movie_transfer).setOnClickListener(this); 35 | findViewById(R.id.movie_transfer_txt).setOnClickListener(this); 36 | findViewById(R.id.movie_music).setOnClickListener(this); 37 | findViewById(R.id.movie_music_txt).setOnClickListener(this); 38 | } 39 | 40 | public void setCallback(MovieBottomCallback callback) { 41 | this.mCallback = callback; 42 | } 43 | 44 | @Override 45 | public void onClick(View v) { 46 | switch (v.getId()){ 47 | case R.id.movie_filter: 48 | case R.id.movie_filter_txt: 49 | if(mCallback!=null){ 50 | mCallback.onFilterClick(); 51 | } 52 | break; 53 | case R.id.movie_transfer: 54 | case R.id.movie_transfer_txt: 55 | if(mCallback!=null){ 56 | mCallback.onTransferClick(); 57 | } 58 | break; 59 | case R.id.movie_music: 60 | case R.id.movie_music_txt: 61 | if(mCallback!=null){ 62 | mCallback.onMusicClick(); 63 | } 64 | break; 65 | case R.id.movie_next: 66 | if(mCallback!=null){ 67 | mCallback.onNextClick(); 68 | } 69 | break; 70 | } 71 | } 72 | 73 | public static interface MovieBottomCallback{ 74 | void onNextClick(); 75 | void onMusicClick(); 76 | void onTransferClick(); 77 | void onFilterClick(); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /app/src/main/java/com/hw/photomovie/sample/widget/SpaceItemDecoration.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.sample.widget; 2 | 3 | import android.graphics.Canvas; 4 | import android.graphics.Rect; 5 | import android.support.v7.widget.RecyclerView; 6 | import android.view.View; 7 | import com.hw.photomovie.sample.R; 8 | import com.hw.photomovie.util.AppResources; 9 | 10 | /** 11 | * Created by huangwei on 2018/9/9. 12 | */ 13 | public class SpaceItemDecoration extends RecyclerView.ItemDecoration { 14 | 15 | private int mSpace; 16 | 17 | public SpaceItemDecoration(int space) { 18 | mSpace = space; 19 | } 20 | 21 | @Override 22 | public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { 23 | super.getItemOffsets(outRect, view, parent, state); 24 | int pos = ((RecyclerView.LayoutParams) view.getLayoutParams()).getViewAdapterPosition(); 25 | if (pos == 0) { 26 | outRect.left = mSpace; 27 | } 28 | outRect.right = mSpace; 29 | } 30 | 31 | @Override 32 | public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { 33 | super.onDraw(c, parent, state); 34 | 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/hw/photomovie/sample/widget/TransferItem.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.sample.widget; 2 | 3 | import com.hw.photomovie.PhotoMovieFactory; 4 | import com.hw.photomovie.moviefilter.CameoMovieFilter; 5 | import com.hw.photomovie.moviefilter.GrayMovieFilter; 6 | import com.hw.photomovie.moviefilter.IMovieFilter; 7 | import com.hw.photomovie.moviefilter.KuwaharaMovieFilter; 8 | import com.hw.photomovie.moviefilter.LutMovieFilter; 9 | import com.hw.photomovie.moviefilter.SnowMovieFilter; 10 | 11 | /** 12 | * Created by huangwei on 2018/9/9. 13 | */ 14 | public class TransferItem { 15 | 16 | public TransferItem(int imgRes, String name, PhotoMovieFactory.PhotoMovieType type) { 17 | this.imgRes = imgRes; 18 | this.name = name; 19 | this.type = type; 20 | } 21 | 22 | public int imgRes; 23 | public String name; 24 | public PhotoMovieFactory.PhotoMovieType type; 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/cameo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yellowcath/PhotoMovie/ed952bb6c9cbb556ae138d5c32bcc09b61bf8be6/app/src/main/res/drawable-nodpi/cameo.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/cancel_click.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yellowcath/PhotoMovie/ed952bb6c9cbb556ae138d5c32bcc09b61bf8be6/app/src/main/res/drawable-nodpi/cancel_click.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/filter_default.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yellowcath/PhotoMovie/ed952bb6c9cbb556ae138d5c32bcc09b61bf8be6/app/src/main/res/drawable-nodpi/filter_default.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/gray.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yellowcath/PhotoMovie/ed952bb6c9cbb556ae138d5c32bcc09b61bf8be6/app/src/main/res/drawable-nodpi/gray.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/kuwahara.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yellowcath/PhotoMovie/ed952bb6c9cbb556ae138d5c32bcc09b61bf8be6/app/src/main/res/drawable-nodpi/kuwahara.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/l1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yellowcath/PhotoMovie/ed952bb6c9cbb556ae138d5c32bcc09b61bf8be6/app/src/main/res/drawable-nodpi/l1.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/l2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yellowcath/PhotoMovie/ed952bb6c9cbb556ae138d5c32bcc09b61bf8be6/app/src/main/res/drawable-nodpi/l2.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/l3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yellowcath/PhotoMovie/ed952bb6c9cbb556ae138d5c32bcc09b61bf8be6/app/src/main/res/drawable-nodpi/l3.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/l4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yellowcath/PhotoMovie/ed952bb6c9cbb556ae138d5c32bcc09b61bf8be6/app/src/main/res/drawable-nodpi/l4.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/l5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yellowcath/PhotoMovie/ed952bb6c9cbb556ae138d5c32bcc09b61bf8be6/app/src/main/res/drawable-nodpi/l5.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/snow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yellowcath/PhotoMovie/ed952bb6c9cbb556ae138d5c32bcc09b61bf8be6/app/src/main/res/drawable-nodpi/snow.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/movie_next_shape.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/watermark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yellowcath/PhotoMovie/ed952bb6c9cbb556ae138d5c32bcc09b61bf8be6/app/src/main/res/drawable-xxhdpi/watermark.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_add.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_add_frame.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_check.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_filter_check_shape.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_movie_filter.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_movie_music.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_movie_transfer.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/movie_next_shape.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/movie_text_cover.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_demo.xml: -------------------------------------------------------------------------------- 1 | 5 | 9 | 10 | 18 | 22 | 28 | 29 | 30 | 37 | 44 | 51 | 52 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /app/src/main/res/layout/demo_bottom_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 18 | 27 | 28 | 37 | 46 | 47 | 56 | 65 | 66 | 80 | 81 | -------------------------------------------------------------------------------- /app/src/main/res/layout/demo_filter_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 13 | 21 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/res/layout/demo_filter_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/layout/demo_transfer_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 13 | 21 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/res/layout/demo_transfer_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yellowcath/PhotoMovie/ed952bb6c9cbb556ae138d5c32bcc09b61bf8be6/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yellowcath/PhotoMovie/ed952bb6c9cbb556ae138d5c32bcc09b61bf8be6/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yellowcath/PhotoMovie/ed952bb6c9cbb556ae138d5c32bcc09b61bf8be6/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yellowcath/PhotoMovie/ed952bb6c9cbb556ae138d5c32bcc09b61bf8be6/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/raw/bg.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yellowcath/PhotoMovie/ed952bb6c9cbb556ae138d5c32bcc09b61bf8be6/app/src/main/res/raw/bg.mid -------------------------------------------------------------------------------- /app/src/main/res/raw/dynamic_window_segment.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yellowcath/PhotoMovie/ed952bb6c9cbb556ae138d5c32bcc09b61bf8be6/app/src/main/res/raw/dynamic_window_segment.jar -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values-zh-rCN/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 滤镜 4 | 转场 5 | 音乐 6 | 下一步 7 | 选择图片 8 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #7F000000 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 130dp 6 | 120dp 7 | 10dp 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/values/stringarray.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Thaw 5 | Scale 6 | ScaleTrans_subtitle 7 | Window 8 | OldMpvie 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | PhotoMovie 3 | 4 | Hello world! 5 | Settings 6 | filter 7 | transfer 8 | music 9 | next 10 | select photos 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/uml/PhotoMovie.uml: -------------------------------------------------------------------------------- 1 | 2 | 3 | JAVA 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | All 12 | 13 | 14 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | ext { 3 | //在模拟器上运行需要强行打开x86开关 4 | RunForEmulator = false 5 | } 6 | 7 | 8 | buildscript { 9 | repositories { 10 | jcenter() 11 | google() 12 | maven { url 'https://www.jitpack.io' } 13 | } 14 | dependencies { 15 | classpath 'com.android.tools.build:gradle:3.2.1' 16 | classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0' 17 | // NOTE: Do not place your application dependencies here; they belong 18 | // in the individual module build.gradle files 19 | } 20 | } 21 | 22 | allprojects { 23 | repositories { 24 | jcenter() 25 | google() 26 | maven { url 'https://www.jitpack.io' } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /dynamicdemo/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /local.properties 3 | /.idea/workspace.xml 4 | /.idea/libraries 5 | /.idea 6 | .DS_Store 7 | /build 8 | *.iml -------------------------------------------------------------------------------- /dynamicdemo/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 27 5 | buildToolsVersion '27.0.3' 6 | 7 | defaultConfig { 8 | minSdkVersion 14 9 | targetSdkVersion 22 10 | versionCode 1 11 | versionName "1.0" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | compile fileTree(include: ['*.jar'], dir: 'libs') 23 | implementation project(':library') 24 | } 25 | 26 | task clearJar(type: Delete) { 27 | delete 'libs/dynamic.jar' 28 | } 29 | task makeJar(type:org.gradle.api.tasks.bundling.Jar) { 30 | //ָ�����ɵ�jar�� 31 | baseName 'dynamic' 32 | //��������class�ļ� 33 | from('build/intermediates/classes/release/com/hw/dynamicdemo/') 34 | //�����jar���Ŀ¼�ṹ 35 | into('com/hw/dynamicdemo/') 36 | //ȥ������Ҫ�����Ŀ¼���ļ� 37 | exclude('test/', 'BuildConfig.class', 'R.class') 38 | //ȥ��R$��ͷ���ļ� 39 | exclude{ it.name.startsWith('R$');} 40 | } 41 | -------------------------------------------------------------------------------- /dynamicdemo/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\ADT\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /dynamicdemo/src/androidTest/java/com/hw/dynamicdemo/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.hw.dynamicdemo; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /dynamicdemo/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yellowcath/PhotoMovie/ed952bb6c9cbb556ae138d5c32bcc09b61bf8be6/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Jan 05 19:12:12 CST 2019 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip 7 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /library/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /local.properties 3 | /.idea/workspace.xml 4 | /.idea/libraries 5 | /.idea 6 | .DS_Store 7 | /build 8 | *.iml 9 | -------------------------------------------------------------------------------- /library/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'com.github.dcendents.android-maven' 3 | group = 'yellowcath' 4 | android { 5 | compileSdkVersion 27 6 | buildToolsVersion '27.0.3' 7 | 8 | defaultConfig { 9 | minSdkVersion 14 10 | targetSdkVersion 22 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(include: ['*.jar'], dir: 'libs') 24 | } 25 | -------------------------------------------------------------------------------- /library/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\ADT\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /library/src/androidTest/java/com/hw/photomovie/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /library/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /library/src/main/assets/lut/lut_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yellowcath/PhotoMovie/ed952bb6c9cbb556ae138d5c32bcc09b61bf8be6/library/src/main/assets/lut/lut_1.jpg -------------------------------------------------------------------------------- /library/src/main/assets/lut/lut_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yellowcath/PhotoMovie/ed952bb6c9cbb556ae138d5c32bcc09b61bf8be6/library/src/main/assets/lut/lut_2.jpg -------------------------------------------------------------------------------- /library/src/main/assets/lut/lut_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yellowcath/PhotoMovie/ed952bb6c9cbb556ae138d5c32bcc09b61bf8be6/library/src/main/assets/lut/lut_3.jpg -------------------------------------------------------------------------------- /library/src/main/assets/lut/lut_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yellowcath/PhotoMovie/ed952bb6c9cbb556ae138d5c32bcc09b61bf8be6/library/src/main/assets/lut/lut_4.jpg -------------------------------------------------------------------------------- /library/src/main/assets/lut/lut_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yellowcath/PhotoMovie/ed952bb6c9cbb556ae138d5c32bcc09b61bf8be6/library/src/main/assets/lut/lut_5.jpg -------------------------------------------------------------------------------- /library/src/main/assets/lut/lut_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yellowcath/PhotoMovie/ed952bb6c9cbb556ae138d5c32bcc09b61bf8be6/library/src/main/assets/lut/lut_default.png -------------------------------------------------------------------------------- /library/src/main/assets/shader/base.glsl: -------------------------------------------------------------------------------- 1 | varying highp vec2 textureCoordinate; 2 | uniform sampler2D inputImageTexture; 3 | 4 | void main() { 5 | gl_FragColor = texture2D(inputImageTexture, textureCoordinate); 6 | } 7 | -------------------------------------------------------------------------------- /library/src/main/assets/shader/lut.glsl: -------------------------------------------------------------------------------- 1 | varying highp vec2 textureCoordinate; 2 | uniform sampler2D inputImageTexture; 3 | uniform sampler2D inputImageTexture2; 4 | 5 | void main() { 6 | 7 | highp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); 8 | highp float blueColor = textureColor.b * 63.0; 9 | 10 | highp vec2 quad1; 11 | quad1.y = floor(floor(blueColor) / 8.0); 12 | quad1.x = floor(blueColor) - (quad1.y * 8.0); 13 | 14 | highp vec2 quad2; 15 | quad2.y = floor(ceil(blueColor) / 8.0); 16 | quad2.x = ceil(blueColor) - (quad2.y * 8.0); 17 | 18 | highp vec2 texPos1; 19 | texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r); 20 | texPos1.y = (quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g); 21 | 22 | highp vec2 texPos2; 23 | texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r); 24 | texPos2.y = (quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g); 25 | 26 | lowp vec4 newColor1 = texture2D(inputImageTexture2, texPos1); 27 | lowp vec4 newColor2 = texture2D(inputImageTexture2, texPos2); 28 | 29 | lowp vec4 newColor = mix(newColor1, newColor2, fract(blueColor)); 30 | gl_FragColor = vec4(newColor.rgb, textureColor.w); 31 | 32 | } 33 | -------------------------------------------------------------------------------- /library/src/main/assets/shader/snow.glsl: -------------------------------------------------------------------------------- 1 | precision mediump float; 2 | varying highp vec2 textureCoordinate; 3 | uniform sampler2D inputImageTexture; 4 | 5 | const float PI = 3.14159265359; 6 | const float aoinParam1 = 0.7; 7 | 8 | uniform float time; 9 | uniform vec2 resolution; 10 | 11 | float snow(vec2 uv,float scale) 12 | { 13 | float w=smoothstep(9.,0.,-uv.y*(scale/10.)); 14 | if(w<.1)return 0.; 15 | uv+=(time*aoinParam1)/scale; 16 | uv.y+=time*0./scale; 17 | uv.x+=sin(uv.y+time*.05)/scale; 18 | uv*=scale; 19 | vec2 s=floor(uv),f=fract(uv),p; 20 | float k=3.,d; 21 | p=.5+.35*sin(11.*fract(sin((s+p+scale)*mat2(7,3,6,5))*5.))-f; 22 | d=length(p); 23 | k=min(d,k); 24 | k=smoothstep(0.,k,sin(f.x+f.y)*0.01); 25 | return k*w; 26 | } 27 | void main(void) 28 | { 29 | vec4 texColor = texture2D(inputImageTexture, textureCoordinate); 30 | 31 | float T = (time / .99); 32 | vec2 position = (( textureCoordinate.xy / resolution.xy ) - 0.5); 33 | position.x *= resolution.x / resolution.y; 34 | vec3 color = texColor.rgb; 35 | vec2 uv=(textureCoordinate.xy*2.-resolution.xy)/min(resolution.x,resolution.y); 36 | vec3 finalColor=vec3(0); 37 | float c=0.0; 38 | c+=snow(uv,30.)*.3; 39 | c+=snow(uv,8.); 40 | c+=snow(uv,6.); 41 | c+=snow(uv,5.); 42 | finalColor=(vec3(c)); 43 | 44 | gl_FragColor = (vec4( color, 1.0 ) + vec4(finalColor,1)); 45 | } -------------------------------------------------------------------------------- /library/src/main/assets/shader/two_fragment.glsl: -------------------------------------------------------------------------------- 1 | varying highp vec2 textureCoordinate; 2 | varying highp vec2 textureCoordinate2; 3 | uniform sampler2D inputImageTexture; 4 | uniform sampler2D inputImageTexture2; 5 | void main() 6 | { 7 | vec4 texColor = texture2D(inputImageTexture, textureCoordinate); 8 | vec4 texColor2 = texture2D(inputImageTexture2, textureCoordinate2); 9 | gl_FragColor = texColor*texColor2; 10 | } -------------------------------------------------------------------------------- /library/src/main/assets/shader/two_vertex.glsl: -------------------------------------------------------------------------------- 1 | attribute vec4 position; 2 | attribute vec4 inputTextureCoordinate; 3 | attribute vec4 inputTextureCoordinate2; 4 | 5 | varying vec2 textureCoordinate; 6 | varying vec2 textureCoordinate2; 7 | void main() 8 | { 9 | gl_Position = position; 10 | textureCoordinate = inputTextureCoordinate.xy; 11 | textureCoordinate2 = inputTextureCoordinate2.xy; 12 | } 13 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/dynamic/DynamicLoader.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.dynamic; 2 | 3 | import android.content.Context; 4 | import android.text.TextUtils; 5 | import com.hw.photomovie.opengl.GLESCanvas; 6 | import com.hw.photomovie.segment.MovieSegment; 7 | import dalvik.system.DexClassLoader; 8 | import dalvik.system.DexFile; 9 | 10 | import java.io.File; 11 | import java.lang.reflect.Constructor; 12 | import java.lang.reflect.Method; 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | import java.util.Objects; 16 | 17 | /** 18 | * Created by huangwei on 2015/6/1. 19 | * 从jar包里动态读取电影片段List 20 | * java jar包打包成android jar包命令 dx --dex --output=out.jar from.jar,dx在build-tools里 21 | */ 22 | public class DynamicLoader { 23 | public static List loadSegmentsFromFile(Context context, String path, String classFullName) { 24 | List segmentList = new ArrayList(); 25 | if (TextUtils.isEmpty(path) || TextUtils.isEmpty(classFullName)) { 26 | return segmentList; 27 | } 28 | final File jarFile = new File(path); 29 | final File dexOutputDir = context.getCacheDir(); 30 | // DexFile.loadDex(jarFile.getAbsolutePath(),dexOutputDir+File.separator+"dexfile",0); 31 | DexClassLoader mClassLoader = new DexClassLoader(jarFile.getAbsolutePath(), dexOutputDir.getAbsolutePath(), null, 32 | context.getClassLoader()); 33 | Class libProviderClazz = null; 34 | try { 35 | libProviderClazz = mClassLoader.loadClass(classFullName); 36 | Method[] methods = libProviderClazz.getMethods(); 37 | Method method = null; 38 | for(int i=0;methods!=null && i) method.invoke(null,new Object[0]); 48 | } catch (Exception exception) { 49 | // Handle exception gracefully here. 50 | exception.printStackTrace(); 51 | } 52 | return segmentList; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/filter/AlphaFilter.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.filter; 2 | 3 | import android.graphics.Rect; 4 | import android.graphics.RectF; 5 | import android.opengl.GLES20; 6 | 7 | /** 8 | * Created by huangwei on 2015/6/9. 9 | */ 10 | public class AlphaFilter extends MovieFilter { 11 | 12 | private static final String ALPHA_UNIFORM = "uAlpha"; 13 | 14 | protected static final String ALPHA_FRAGMENT_SHADER = "" + 15 | "precision mediump float;\n" + 16 | "varying highp vec2 textureCoordinate;\n" + 17 | " \n" + 18 | "uniform sampler2D inputImageTexture;\n" + 19 | " \n" + 20 | "uniform float " + ALPHA_UNIFORM + ";\n" + 21 | " \n" + 22 | "void main()\n" + 23 | "{\n" + 24 | " gl_FragColor = texture2D(inputImageTexture, textureCoordinate);\n" + 25 | " gl_FragColor *=" + ALPHA_UNIFORM + ";\n" + 26 | "}"; 27 | 28 | private int mAlphaLocation; 29 | 30 | public AlphaFilter() { 31 | super(VERTEX_SHADER, ALPHA_FRAGMENT_SHADER); 32 | } 33 | 34 | @Override 35 | public void init() { 36 | super.init(); 37 | mAlphaLocation = GLES20.glGetUniformLocation(mProgId, ALPHA_UNIFORM); 38 | } 39 | 40 | @Override 41 | public void drawFrame(float progress, int glTextureId, Rect textureRext, RectF srcRect, RectF dstRect) { 42 | GLES20.glUniform1f(mAlphaLocation, progress); 43 | super.drawFrame(progress, glTextureId, textureRext, srcRect, dstRect); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/filter/AlphaGradientFilter.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.filter; 2 | 3 | import android.graphics.Rect; 4 | import android.graphics.RectF; 5 | import android.opengl.GLES20; 6 | 7 | /** 8 | * Created by huangwei on 2015/6/9. 9 | * range[0~1],以top为0,bottom为1,从start到end,alpha值渐变[0~1] 10 | */ 11 | public class AlphaGradientFilter extends MovieFilter { 12 | 13 | protected static final String ALPHA_FRAGMENT_SHADER = "" + 14 | "precision mediump float;\n" + 15 | "varying highp vec2 textureCoordinate;\n" + 16 | "uniform sampler2D inputImageTexture;\n" + 17 | "uniform float uStart;\n" + 18 | "uniform float uEnd;\n" + 19 | "float uAlpha;\n" + 20 | "float y;\n" + 21 | " \n" + 22 | "void main()\n" + 23 | "{\n" + 24 | " gl_FragColor = texture2D(inputImageTexture, textureCoordinate);\n" + 25 | " y = textureCoordinate.y;" + 26 | " if(uStart=uEnd){\n" + 30 | " uAlpha = 1.0;\n" + 31 | " } else{\n" + 32 | " uAlpha = (y - uStart) / (uEnd - uStart);\n" + 33 | " }\n" + 34 | " } else if(uStart == uEnd){\n" + 35 | " uAlpha = 1.0;\n" + 36 | " } else{\n" + 37 | " if(y >= uStart){\n" + 38 | " uAlpha = 0.0;\n" + 39 | " } else if(y <=uEnd){\n" + 40 | " uAlpha = 1.0;\n" + 41 | " } else{\n" + 42 | " uAlpha = (y - uStart) / (uEnd - uStart);\n" + 43 | " } \n" + 44 | " }" + 45 | " gl_FragColor *=uAlpha;\n" + 46 | "}"; 47 | 48 | 49 | private int mStartLocation; 50 | private int mEndLocation; 51 | 52 | public AlphaGradientFilter() { 53 | super(VERTEX_SHADER, ALPHA_FRAGMENT_SHADER); 54 | } 55 | 56 | @Override 57 | public void init() { 58 | super.init(); 59 | mStartLocation = GLES20.glGetUniformLocation(mProgId, "uStart"); 60 | mEndLocation = GLES20.glGetUniformLocation(mProgId, "uEnd"); 61 | } 62 | 63 | @Override 64 | public void drawFrame(float progress, int glTextureId, Rect textureRext, RectF srcRect, RectF dstRect) { 65 | float baseY = (srcRect.top - textureRext.top) / textureRext.height(); 66 | float scaleY = srcRect.height() / textureRext.height(); 67 | mRangeStart = baseY + mRangeStart * scaleY; 68 | mRangeEnd = baseY + mRangeEnd * scaleY; 69 | GLES20.glUniform1f(mStartLocation, mRangeStart); 70 | GLES20.glUniform1f(mEndLocation, mRangeEnd); 71 | super.drawFrame(progress, glTextureId, textureRext, srcRect, dstRect); 72 | } 73 | 74 | @Override 75 | public void setRange(float start, float end) { 76 | super.setRange(start, end); 77 | } 78 | } 79 | 80 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/filter/GrayFilter.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.filter; 2 | 3 | /** 4 | * Created by huangwei on 2015/6/23. 5 | */ 6 | public class GrayFilter extends MovieFilter { 7 | 8 | protected static final String FRAGMENT_SHADER = "" + 9 | "varying highp vec2 textureCoordinate;\n" + 10 | " \n" + 11 | "uniform sampler2D inputImageTexture;\n" + 12 | " \n" + 13 | "void main()\n" + 14 | "{\n" + 15 | " mediump vec4 color = texture2D(inputImageTexture, textureCoordinate);\n" + 16 | " mediump float gray = color.r*0.3+color.g*0.59+color.b*0.11;\n"+ 17 | " gl_FragColor = vec4(gray,gray,gray,1.0);\n"+ 18 | "}"; 19 | 20 | public GrayFilter() { 21 | super(VERTEX_SHADER,FRAGMENT_SHADER); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/filter/OldMovieFilter.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.filter; 2 | 3 | import android.opengl.GLES20; 4 | 5 | /** 6 | * Created by huangwei on 2015/6/23. 7 | */ 8 | public class OldMovieFilter extends MovieFilter { 9 | protected static final String FRAGMENT_SHADER = "precision highp float;\n" + 10 | " varying vec2 textureCoordinate;\n" + 11 | " vec4 coefficient = vec4(0.0,0.5,1.0,0.4); \n" +/* inverted, radius, gradient, brightness. */ 12 | " vec4 color = vec4(1.0,1.0,1.0,1.0);\n" + 13 | " vec2 touchPoint = vec2(0.5,0.5);\n" + 14 | " uniform sampler2D inputImageTexture;\n" + 15 | " vec2 resolution = vec2(700.0,1000.0);\n" + 16 | " uniform float uRandom;\n" + 17 | " float dis = 50.0;\n" + 18 | " \n" + 19 | " float getMask(float radius, vec2 pos, vec2 centre)\n" + 20 | " {\n" + 21 | " float rDis = dis * uRandom;\n" + 22 | " float xDis = rDis/resolution.x;\n" + 23 | " float yDis = rDis/resolution.y;\n" + 24 | " float l = 0.0 + rDis;\n" + 25 | " float r = resolution.x - rDis;\n" + 26 | " float b = 0.0 + rDis;\n" + 27 | " float t = resolution.y - rDis;\n" + 28 | " if(pos.x < r && pos.x >l && pos.y < t && pos.y > b){\n" + 29 | " float dis1 = abs(pos.x - l) / resolution.x;\n" + 30 | " float dis2 = abs(pos.x - r) / resolution.x;\n" + 31 | " float dis3 = abs(pos.y - t) / resolution.y;\n" + 32 | " float dis4 = abs(pos.y - b) / resolution.y;\n" + 33 | " //return 1.0;\n" + 34 | " float minDis = min(dis1,min(dis2,min(dis3,dis4)));\n" + 35 | " return smoothstep(0.0, coefficient.z, pow(minDis, coefficient.w));\n" + 36 | " } else{\n" + 37 | " return 0.0;\n" + 38 | " }\n" + 39 | " }\n" + 40 | "\n" + 41 | " void main()\n" + 42 | " {\n" + 43 | " vec2 centre = touchPoint;\n" + 44 | " vec4 tc = texture2D(inputImageTexture,textureCoordinate);\n" + 45 | " float mask = getMask(coefficient.y, gl_FragCoord.xy, centre);\n" + 46 | " if (coefficient.x == 0.0)\n" + 47 | " gl_FragColor = vec4(tc*mask*color);\n" + 48 | " else\n" + 49 | " gl_FragColor = vec4(tc*(1.0-coefficient.x*mask*color));\n" + 50 | " }"; 51 | 52 | private int mRandomHandle; 53 | 54 | public OldMovieFilter() { 55 | super(VERTEX_SHADER, FRAGMENT_SHADER); 56 | } 57 | 58 | @Override 59 | public void initShader() { 60 | super.initShader(); 61 | GLHelper.checkGlError(); 62 | mRandomHandle = GLES20.glGetUniformLocation(mProgId, "uRandom"); 63 | GLHelper.checkGlError(); 64 | } 65 | 66 | @Override 67 | protected void preDraw(float progress) { 68 | super.preDraw(progress); 69 | float sinCount = 5f; 70 | float p = progress % (1/sinCount) / (1/sinCount); 71 | GLES20.glUniform1f(mRandomHandle, 1 + (float) Math.sin(p * Math.PI) * .2f); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/model/ErrorReason.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.model; 2 | 3 | 4 | /** 5 | * Created by yellowcat on 2015/6/2. 6 | */ 7 | public class ErrorReason { 8 | 9 | private Throwable mThrowable; 10 | private String mExtra; 11 | 12 | public ErrorReason(Throwable cause,String extra) { 13 | mThrowable = cause; 14 | mExtra = extra; 15 | } 16 | 17 | public Throwable getThrowable() { 18 | return mThrowable; 19 | } 20 | 21 | public String getExtra() { 22 | return mExtra; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/model/PhotoData.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.model; 2 | 3 | import android.graphics.Bitmap; 4 | 5 | /** 6 | * Created by huangwei on 2015/5/25. 7 | */ 8 | public abstract class PhotoData { 9 | 10 | public static final int STATE_ERROR = -1; 11 | public static final int STATE_REMOTE = 0; 12 | public static final int STATE_DOWNLOADING = 1; 13 | public static final int STATE_LOCAL = 2; 14 | public static final int STATE_LOADING = 3; 15 | public static final int STATE_BITMAP = 4; 16 | 17 | protected String mUri; 18 | protected String mLocalUri; 19 | protected volatile Bitmap mBitmap; 20 | 21 | protected int mState; 22 | protected int mTargetState; 23 | 24 | private PhotoInfo mPhotoInfo; 25 | 26 | public PhotoData(String uri, int state) { 27 | this(uri, state, null); 28 | } 29 | 30 | public PhotoData(String uri, int state, PhotoInfo photoInfo) { 31 | mUri = uri; 32 | mState = state; 33 | mPhotoInfo = photoInfo; 34 | } 35 | 36 | /** 37 | * 可能返回null,只有状态为{@link #STATE_BITMAP}才返回bitmap 38 | * 39 | * @return 40 | */ 41 | public Bitmap getBitmap() { 42 | return mBitmap; 43 | } 44 | 45 | /** 46 | * 可能返回null,只有状态为{@link #STATE_BITMAP}才返回bitmap 47 | * 48 | * @return 49 | */ 50 | public Bitmap getBitmapAndRelease() { 51 | Bitmap bitmap = mBitmap; 52 | mBitmap = null; 53 | return bitmap; 54 | } 55 | 56 | public void setBitmap(Bitmap bitmap) { 57 | if (bitmap != null) { 58 | mBitmap = bitmap; 59 | } 60 | } 61 | 62 | public String getUri() { 63 | return mUri; 64 | } 65 | 66 | public int getState() { 67 | return mState; 68 | } 69 | 70 | public int getTargetState() { 71 | return mTargetState; 72 | } 73 | 74 | public PhotoInfo getPhotoInfo() { 75 | return mPhotoInfo; 76 | } 77 | 78 | public void setPhotoInfo(PhotoInfo photoInfo) { 79 | mPhotoInfo = photoInfo; 80 | } 81 | 82 | /** 83 | * @param targetState must be {@link #STATE_LOCAL} OR {@link #STATE_BITMAP} 84 | * @param onDataLoadListener 85 | */ 86 | public abstract void prepareData(int targetState, OnDataLoadListener onDataLoadListener); 87 | 88 | public boolean isLocal() { 89 | return mState == STATE_LOCAL || mState == STATE_LOADING || mState == STATE_BITMAP; 90 | } 91 | 92 | public static class SimpleOnDataLoadListener implements OnDataLoadListener { 93 | 94 | @Override 95 | public void onDataLoaded(PhotoData photoData, Bitmap bitmap) { 96 | 97 | } 98 | 99 | @Override 100 | public void onDownloaded(PhotoData photoData) { 101 | 102 | } 103 | 104 | @Override 105 | public void onDownloadProgressUpdate(PhotoData photoData, int current, int total) { 106 | 107 | } 108 | 109 | @Override 110 | public void onError(PhotoData photoData, ErrorReason errorReason) { 111 | 112 | } 113 | } 114 | 115 | public interface OnDataLoadListener { 116 | void onDataLoaded(PhotoData photoData, Bitmap bitmap); 117 | 118 | void onDownloaded(PhotoData photoData); 119 | 120 | void onDownloadProgressUpdate(PhotoData photoData, int current, int total); 121 | 122 | void onError(PhotoData photoData, ErrorReason errorReason); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/model/PhotoInfo.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.model; 2 | 3 | /** 4 | * Created by huangwei on 2015/6/10. 5 | */ 6 | public class PhotoInfo { 7 | public Object extra; 8 | public String description; 9 | } 10 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/moviefilter/CameoMovieFilter.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.moviefilter; 2 | 3 | import android.graphics.Rect; 4 | import android.graphics.RectF; 5 | import android.opengl.GLES20; 6 | import com.hw.photomovie.PhotoMovie; 7 | import com.hw.photomovie.opengl.FboTexture; 8 | 9 | /** 10 | * Created by huangwei on 2018/9/8. 11 | */ 12 | public class CameoMovieFilter extends BaseMovieFilter { 13 | 14 | protected static final String FRAGMENT_SHADER = 15 | "precision mediump float;\n" + 16 | "varying vec2 textureCoordinate;\n" + 17 | "uniform sampler2D inputImageTexture;\n" + 18 | "const highp vec3 W = vec3(0.2125, 0.7154, 0.0721);\n" + 19 | "uniform vec2 TexSize;\n" + 20 | "const vec4 bkColor = vec4(0.5, 0.5, 0.5, 1.0);\n" + 21 | "\n" + 22 | "void main()\n" + 23 | "{\n" + 24 | " vec2 tex = textureCoordinate;\n" + 25 | " vec2 upLeftUV = vec2(tex.x-1.0/TexSize.x, tex.y-1.0/TexSize.y);\n" + 26 | " vec4 curColor = texture2D(inputImageTexture, textureCoordinate);\n" + 27 | " vec4 upLeftColor = texture2D(inputImageTexture, upLeftUV);\n" + 28 | " vec4 delColor = curColor - upLeftColor;\n" + 29 | " float luminance = dot(delColor.rgb, W);\n" + 30 | " gl_FragColor = vec4(vec3(luminance), 0.0) + bkColor;\n" + 31 | "}"; 32 | 33 | private int mTexSizeHandle; 34 | public CameoMovieFilter(){ 35 | super(VERTEX_SHADER,FRAGMENT_SHADER); 36 | } 37 | 38 | @Override 39 | public void initShader() { 40 | super.initShader(); 41 | mTexSizeHandle = GLES20.glGetUniformLocation(mProgId,"TexSize"); 42 | } 43 | 44 | @Override 45 | protected void onPreDraw(PhotoMovie photoMovie, int elapsedTime, FboTexture inputTexture) { 46 | super.onPreDraw(photoMovie, elapsedTime,inputTexture); 47 | GLES20.glUniform2fv(mTexSizeHandle,1,new float[]{inputTexture.getTextureWidth(),inputTexture.getTextureHeight()},0); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/moviefilter/GrayMovieFilter.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.moviefilter; 2 | 3 | /** 4 | * Created by huangwei on 2018/9/8. 5 | */ 6 | public class GrayMovieFilter extends BaseMovieFilter { 7 | protected static final String FRAGMENT_SHADER = "" + 8 | "varying highp vec2 textureCoordinate;\n" + 9 | " \n" + 10 | "uniform sampler2D inputImageTexture;\n" + 11 | " \n" + 12 | "void main()\n" + 13 | "{\n" + 14 | " mediump vec4 color = texture2D(inputImageTexture, textureCoordinate);\n" + 15 | " mediump float gray = color.r*0.3+color.g*0.59+color.b*0.11;\n"+ 16 | " gl_FragColor = vec4(gray,gray,gray,1.0);\n"+ 17 | "}"; 18 | public GrayMovieFilter(){ 19 | super(VERTEX_SHADER,FRAGMENT_SHADER); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/moviefilter/IMovieFilter.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.moviefilter; 2 | 3 | import com.hw.photomovie.PhotoMovie; 4 | import com.hw.photomovie.opengl.FboTexture; 5 | 6 | /** 7 | * Created by huangwei on 2018/9/5 0005. 8 | */ 9 | public interface IMovieFilter { 10 | void doFilter(PhotoMovie photoMovie,int elapsedTime, FboTexture inputTexture, FboTexture outputTexture); 11 | void release(); 12 | } 13 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/moviefilter/LutMovieFilter.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.moviefilter; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.BitmapFactory; 5 | import android.opengl.GLES20; 6 | import android.util.Log; 7 | import com.hw.photomovie.PhotoMovie; 8 | import com.hw.photomovie.opengl.FboTexture; 9 | import com.hw.photomovie.util.AppResources; 10 | 11 | import static com.hw.photomovie.util.AppResources.loadShaderFromAssets; 12 | 13 | /** 14 | * Created by huangwei on 2018/9/8. 15 | */ 16 | public class LutMovieFilter extends TwoTextureMovieFilter { 17 | 18 | public LutMovieFilter(Bitmap lutBitmap){ 19 | super(loadShaderFromAssets("shader/two_vertex.glsl"),loadShaderFromAssets("shader/lut.glsl")); 20 | setBitmap(lutBitmap); 21 | } 22 | 23 | public LutMovieFilter(LutType type){ 24 | super(loadShaderFromAssets("shader/two_vertex.glsl"),loadShaderFromAssets("shader/lut.glsl")); 25 | setBitmap(typeToBitmap(type)); 26 | } 27 | 28 | 29 | 30 | public enum LutType{ 31 | A,B,C,D,E 32 | 33 | } 34 | public static Bitmap typeToBitmap(LutType type){ 35 | switch (type){ 36 | case A: 37 | return AppResources.loadBitmapFromAssets("lut/lut_1.jpg"); 38 | case B: 39 | return AppResources.loadBitmapFromAssets("lut/lut_2.jpg"); 40 | case C: 41 | return AppResources.loadBitmapFromAssets("lut/lut_3.jpg"); 42 | case D: 43 | return AppResources.loadBitmapFromAssets("lut/lut_4.jpg"); 44 | case E: 45 | return AppResources.loadBitmapFromAssets("lut/lut_5.jpg"); 46 | } 47 | return null; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/moviefilter/SnowMovieFilter.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.moviefilter; 2 | 3 | import android.graphics.Rect; 4 | import android.graphics.RectF; 5 | import android.opengl.GLES20; 6 | import android.util.Log; 7 | import com.hw.photomovie.PhotoMovie; 8 | import com.hw.photomovie.opengl.FboTexture; 9 | 10 | import static com.hw.photomovie.util.AppResources.loadShaderFromAssets; 11 | 12 | /** 13 | * Created by huangwei on 2018/9/8. 14 | */ 15 | public class SnowMovieFilter extends BaseMovieFilter { 16 | 17 | private int mTimeHandler; 18 | private int mSizeHandler; 19 | private int mSnowSize = 3; 20 | private int mSpeed = 5; 21 | public SnowMovieFilter() { 22 | super(VERTEX_SHADER, loadShaderFromAssets("shader/snow.glsl")); 23 | } 24 | 25 | @Override 26 | public void initShader() { 27 | super.initShader(); 28 | mTimeHandler = GLES20.glGetUniformLocation(getProgram(),"time"); 29 | mSizeHandler = GLES20.glGetUniformLocation(getProgram(),"resolution"); 30 | } 31 | 32 | @Override 33 | protected void onPreDraw(PhotoMovie photoMovie, int elapsedTime, FboTexture inputTexture) { 34 | super.onPreDraw(photoMovie, elapsedTime, inputTexture); 35 | float time = photoMovie==null?0f:elapsedTime/(float)photoMovie.getDuration(); 36 | GLES20.glUniform1f(mTimeHandler,time*mSpeed); 37 | GLES20.glUniform2fv(mSizeHandler,1,new float[]{inputTexture.getWidth()/(float)inputTexture.getHeight()*mSnowSize,1f*mSnowSize},0); 38 | 39 | } 40 | 41 | public void setSnowSize(int mSnowSize) { 42 | this.mSnowSize = mSnowSize; 43 | } 44 | 45 | public void setSpeed(int mSpeed) { 46 | this.mSpeed = mSpeed; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/music/IMusicPlayer.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.music; 2 | 3 | import android.content.Context; 4 | import android.content.res.AssetFileDescriptor; 5 | import android.media.MediaPlayer; 6 | import android.net.Uri; 7 | 8 | import java.io.FileDescriptor; 9 | 10 | /** 11 | * Created by huangwei on 2018/9/13 0013. 12 | */ 13 | public interface IMusicPlayer { 14 | public void start(); 15 | public void stop(); 16 | public void pause(); 17 | public void release(); 18 | 19 | public void setDataSource(String path); 20 | public void setDataSource(FileDescriptor fileDescriptor); 21 | public void setDataSource(AssetFileDescriptor assetFileDescriptor); 22 | public void setDataSource(Context ctx, Uri uri); 23 | 24 | public void setErrorListener(MediaPlayer.OnErrorListener onErrorListener); 25 | public void setLooping(boolean loop); 26 | public boolean isPlaying(); 27 | public void seekTo(int msec); 28 | } 29 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/opengl/BitmapTexture.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.opengl; 2 | 3 | import android.graphics.Bitmap; 4 | import android.opengl.GLES20; 5 | import junit.framework.Assert; 6 | 7 | import static com.hw.photomovie.util.GLUtil.NO_TEXTURE; 8 | 9 | // BitmapTexture is a texture whose content is specified by a fixed Bitmap. 10 | // 11 | // The texture does not own the Bitmap. The user should make sure the Bitmap 12 | // is valid during the texture's lifetime. When the texture is recycled, it 13 | // does not free the Bitmap. 14 | public class BitmapTexture extends UploadedTexture { 15 | protected Bitmap mContentBitmap; 16 | protected boolean mIsRecycled; 17 | /** 18 | * 默认情况是统一由GLESCanvas销毁,但是PhotoMovie循环播放时会导致纹理越来越多. 19 | * 因此这里改变默认行为 20 | */ 21 | protected boolean mRecycleDirectly = true; 22 | 23 | public BitmapTexture(Bitmap bitmap) { 24 | this(bitmap, false); 25 | } 26 | 27 | public BitmapTexture(Bitmap bitmap, boolean hasBorder) { 28 | super(hasBorder); 29 | Assert.assertTrue(bitmap != null && !bitmap.isRecycled()); 30 | mContentBitmap = bitmap; 31 | mIsRecycled = false; 32 | } 33 | 34 | @Override 35 | public void recycle() { 36 | mIsRecycled = true; 37 | if(mRecycleDirectly) { 38 | if (mId != NO_TEXTURE && GLES20.glIsTexture(mId)) { 39 | GLES20.glDeleteTextures(1, new int[]{mId}, 0); 40 | mId = NO_TEXTURE; 41 | } 42 | } 43 | super.recycle(); 44 | } 45 | 46 | public void setRecycleDirectly(boolean recycleDirectly) { 47 | this.mRecycleDirectly = recycleDirectly; 48 | } 49 | 50 | @Override 51 | public void updateContent(GLESCanvas canvas) { 52 | // 当bitmap已经被释放,onGLIdle时还在上传队列中的该对象,崩溃 53 | if (mIsRecycled) { 54 | return; 55 | } 56 | super.updateContent(canvas); 57 | } 58 | 59 | @Override 60 | protected void onFreeBitmap(Bitmap bitmap) { 61 | // Do nothing. 62 | } 63 | 64 | @Override 65 | protected Bitmap onGetBitmap() { 66 | return mContentBitmap; 67 | } 68 | 69 | public Bitmap getBitmap() { 70 | return mContentBitmap; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/opengl/CanvasTexture.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.opengl; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.Bitmap.Config; 5 | import android.graphics.Canvas; 6 | 7 | // CanvasTexture is a texture whose content is the drawing on a Canvas. 8 | // The subclasses should override onDraw() to draw on the bitmap. 9 | // By default CanvasTexture is not opaque. 10 | abstract class CanvasTexture extends UploadedTexture { 11 | protected Canvas mCanvas; 12 | private final Config mConfig; 13 | 14 | public CanvasTexture(int width, int height) { 15 | mConfig = Config.ARGB_8888; 16 | setSize(width, height); 17 | setOpaque(false); 18 | } 19 | 20 | @Override 21 | protected Bitmap onGetBitmap() { 22 | Bitmap bitmap = Bitmap.createBitmap(mWidth, mHeight, mConfig); 23 | mCanvas = new Canvas(bitmap); 24 | onDraw(mCanvas, bitmap); 25 | return bitmap; 26 | } 27 | 28 | @Override 29 | protected void onFreeBitmap(Bitmap bitmap) { 30 | if (!inFinalizer()) { 31 | bitmap.recycle(); 32 | } 33 | } 34 | 35 | protected abstract void onDraw(Canvas canvas, Bitmap backing); 36 | } 37 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/opengl/ColorTexture.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.opengl; 2 | 3 | import com.hw.photomovie.util.Utils; 4 | 5 | // ColorTexture is a texture which fills the rectangle with the specified color. 6 | public class ColorTexture implements Texture { 7 | 8 | private final int mColor; 9 | private int mWidth; 10 | private int mHeight; 11 | 12 | public ColorTexture(int color) { 13 | mColor = color; 14 | mWidth = 1; 15 | mHeight = 1; 16 | } 17 | 18 | @Override 19 | public void draw(GLESCanvas canvas, int x, int y) { 20 | draw(canvas, x, y, mWidth, mHeight); 21 | } 22 | 23 | @Override 24 | public void draw(GLESCanvas canvas, int x, int y, int w, int h) { 25 | canvas.fillRect(x, y, w, h, mColor); 26 | } 27 | 28 | @Override 29 | public boolean isOpaque() { 30 | return Utils.isOpaque(mColor); 31 | } 32 | 33 | public void setSize(int width, int height) { 34 | mWidth = width; 35 | mHeight = height; 36 | } 37 | 38 | @Override 39 | public int getWidth() { 40 | return mWidth; 41 | } 42 | 43 | @Override 44 | public int getHeight() { 45 | return mHeight; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/opengl/ExtTexture.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.opengl; 2 | 3 | // ExtTexture is a texture whose content comes from a external texture. 4 | // Before drawing, setSize() should be called. 5 | public class ExtTexture extends BasicTexture { 6 | 7 | private int mTarget; 8 | 9 | public ExtTexture(GLESCanvas canvas, int target) { 10 | GLId glId = canvas.getGLId(); 11 | mId = glId.generateTexture(); 12 | mTarget = target; 13 | } 14 | 15 | private void uploadToCanvas(GLESCanvas canvas) { 16 | canvas.setTextureParameters(this); 17 | setAssociatedCanvas(canvas); 18 | mState = STATE_LOADED; 19 | } 20 | 21 | @Override 22 | protected boolean onBind(GLESCanvas canvas) { 23 | if (!isLoaded()) { 24 | uploadToCanvas(canvas); 25 | } 26 | 27 | return true; 28 | } 29 | 30 | @Override 31 | public int getTarget() { 32 | return mTarget; 33 | } 34 | 35 | @Override 36 | public boolean isOpaque() { 37 | return true; 38 | } 39 | 40 | @Override 41 | public void yield() { 42 | // we cannot free the texture because we have no backup. 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/opengl/FadeInTexture.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.opengl; 2 | 3 | // FadeInTexture is a texture which begins with a color, then gradually animates 4 | // into a given texture. 5 | public class FadeInTexture extends FadeTexture implements Texture { 6 | private final int mColor; 7 | 8 | public FadeInTexture(int color, BasicTexture texture) { 9 | super(texture); 10 | mColor = color; 11 | } 12 | 13 | @Override 14 | public void draw(GLESCanvas canvas, int x, int y, int w, int h) { 15 | if (isAnimating()) { 16 | canvas.drawMixed(mTexture, mColor, getRatio(), x, y, w, h); 17 | } else { 18 | mTexture.draw(canvas, x, y, w, h); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/opengl/FadeOutTexture.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.opengl; 2 | 3 | // FadeOutTexture is a texture which begins with a given texture, then gradually animates 4 | // into fading out totally. 5 | public class FadeOutTexture extends FadeTexture { 6 | public FadeOutTexture(BasicTexture texture) { 7 | super(texture); 8 | } 9 | 10 | @Override 11 | public void draw(GLESCanvas canvas, int x, int y, int w, int h) { 12 | if (isAnimating()) { 13 | canvas.save(GLESCanvas.SAVE_FLAG_ALPHA); 14 | canvas.setAlpha(getRatio()); 15 | mTexture.draw(canvas, x, y, w, h); 16 | canvas.restore(); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/opengl/FadeTexture.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.opengl; 2 | 3 | import com.hw.photomovie.opengl.animations.AnimationTime; 4 | import com.hw.photomovie.util.Utils; 5 | 6 | // FadeTexture is a texture which fades the given texture along the time. 7 | public abstract class FadeTexture implements Texture { 8 | // The duration of the fading animation in milliseconds 9 | public static final int DURATION = 180; 10 | protected final BasicTexture mTexture; 11 | private final long mStartTime; 12 | private final int mWidth; 13 | private final int mHeight; 14 | private final boolean mIsOpaque; 15 | private boolean mIsAnimating; 16 | 17 | public FadeTexture(BasicTexture texture) { 18 | mTexture = texture; 19 | mWidth = mTexture.getWidth(); 20 | mHeight = mTexture.getHeight(); 21 | mIsOpaque = mTexture.isOpaque(); 22 | mStartTime = now(); 23 | mIsAnimating = true; 24 | } 25 | 26 | @Override 27 | public void draw(GLESCanvas canvas, int x, int y) { 28 | draw(canvas, x, y, mWidth, mHeight); 29 | } 30 | 31 | @Override 32 | public boolean isOpaque() { 33 | return mIsOpaque; 34 | } 35 | 36 | @Override 37 | public int getWidth() { 38 | return mWidth; 39 | } 40 | 41 | @Override 42 | public int getHeight() { 43 | return mHeight; 44 | } 45 | 46 | public boolean isAnimating() { 47 | if (mIsAnimating) { 48 | if (now() - mStartTime >= DURATION) { 49 | mIsAnimating = false; 50 | } 51 | } 52 | return mIsAnimating; 53 | } 54 | 55 | protected float getRatio() { 56 | float r = (float) (now() - mStartTime) / DURATION; 57 | return Utils.clamp(1.0f - r, 0.0f, 1.0f); 58 | } 59 | 60 | private long now() { 61 | return AnimationTime.get(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/opengl/GLES11IdImpl.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.opengl; 2 | 3 | import javax.microedition.khronos.opengles.GL11; 4 | import javax.microedition.khronos.opengles.GL11ExtensionPack; 5 | 6 | /** 7 | * Open GL ES 1.1 implementation for generating and destroying texture IDs and 8 | * buffer IDs 9 | */ 10 | public class GLES11IdImpl implements GLId { 11 | private static int sNextId = 1; 12 | // Mutex for sNextId 13 | private static Object sLock = new Object(); 14 | 15 | @Override 16 | public int generateTexture() { 17 | synchronized (sLock) { 18 | return sNextId++; 19 | } 20 | } 21 | 22 | @Override 23 | public void glGenBuffers(int n, int[] buffers, int offset) { 24 | synchronized (sLock) { 25 | while (n-- > 0) { 26 | buffers[offset + n] = sNextId++; 27 | } 28 | } 29 | } 30 | 31 | @Override 32 | public void glDeleteTextures(GL11 gl, int n, int[] textures, int offset) { 33 | synchronized (sLock) { 34 | gl.glDeleteTextures(n, textures, offset); 35 | } 36 | } 37 | 38 | @Override 39 | public void glDeleteBuffers(GL11 gl, int n, int[] buffers, int offset) { 40 | synchronized (sLock) { 41 | gl.glDeleteBuffers(n, buffers, offset); 42 | } 43 | } 44 | 45 | @Override 46 | public void glDeleteFramebuffers(GL11ExtensionPack gl11ep, int n, int[] buffers, int offset) { 47 | synchronized (sLock) { 48 | gl11ep.glDeleteFramebuffersOES(n, buffers, offset); 49 | } 50 | } 51 | 52 | 53 | } 54 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/opengl/GLES20IdImpl.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.opengl; 2 | 3 | import android.opengl.GLES20; 4 | 5 | import javax.microedition.khronos.opengles.GL11; 6 | import javax.microedition.khronos.opengles.GL11ExtensionPack; 7 | 8 | public class GLES20IdImpl implements GLId { 9 | private final int[] mTempIntArray = new int[1]; 10 | 11 | @Override 12 | public int generateTexture() { 13 | GLES20.glGenTextures(1, mTempIntArray, 0); 14 | GLES20Canvas.checkError(); 15 | return mTempIntArray[0]; 16 | } 17 | 18 | @Override 19 | public void glGenBuffers(int n, int[] buffers, int offset) { 20 | GLES20.glGenBuffers(n, buffers, offset); 21 | GLES20Canvas.checkError(); 22 | } 23 | 24 | @Override 25 | public void glDeleteTextures(GL11 gl, int n, int[] textures, int offset) { 26 | GLES20.glDeleteTextures(n, textures, offset); 27 | GLES20Canvas.checkError(); 28 | } 29 | 30 | 31 | @Override 32 | public void glDeleteBuffers(GL11 gl, int n, int[] buffers, int offset) { 33 | GLES20.glDeleteBuffers(n, buffers, offset); 34 | GLES20Canvas.checkError(); 35 | } 36 | 37 | @Override 38 | public void glDeleteFramebuffers(GL11ExtensionPack gl11ep, int n, int[] buffers, int offset) { 39 | GLES20.glDeleteFramebuffers(n, buffers, offset); 40 | GLES20Canvas.checkError(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/opengl/GLId.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.opengl; 2 | 3 | import javax.microedition.khronos.opengles.GL11; 4 | import javax.microedition.khronos.opengles.GL11ExtensionPack; 5 | 6 | /** 7 | * @Author Jituo.Xuan 8 | * @Date 11:40:51 AM Mar 20, 2014 9 | * @Comments:This mimics corresponding GL functions. 10 | */ 11 | public interface GLId { 12 | public int generateTexture(); 13 | 14 | public void glGenBuffers(int n, int[] buffers, int offset); 15 | 16 | public void glDeleteTextures(GL11 gl, int n, int[] textures, int offset); 17 | 18 | public void glDeleteBuffers(GL11 gl, int n, int[] buffers, int offset); 19 | 20 | public void glDeleteFramebuffers(GL11ExtensionPack gl11ep, int n, int[] buffers, int offset); 21 | } 22 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/opengl/GLPaint.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.opengl; 2 | 3 | public class GLPaint { 4 | private float mLineWidth = 1f; 5 | private int mColor = 0; 6 | 7 | public void setColor(int color) { 8 | mColor = color; 9 | } 10 | 11 | public int getColor() { 12 | return mColor; 13 | } 14 | 15 | public void setLineWidth(float width) { 16 | mLineWidth = width; 17 | } 18 | 19 | public float getLineWidth() { 20 | return mLineWidth; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/opengl/MGLES20Canvas.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.opengl; 2 | 3 | /** 4 | * Created by huangwei on 2015/5/29. 5 | */ 6 | public class MGLES20Canvas extends GLES20Canvas{ 7 | 8 | private int mSavedHashcode; 9 | private ShaderParameter[] parameters; 10 | @Override 11 | protected ShaderParameter[] prepareTexture(BasicTexture texture) { 12 | if(texture.hashCode() == mSavedHashcode){ 13 | return parameters; 14 | } 15 | parameters = super.prepareTexture(texture); 16 | mSavedHashcode = texture.hashCode(); 17 | return parameters; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/opengl/MultiLineTexture.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.opengl; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.Canvas; 5 | import android.text.Layout; 6 | import android.text.StaticLayout; 7 | import android.text.TextPaint; 8 | 9 | 10 | // MultiLineTexture is a texture shows the content of a specified String. 11 | // 12 | // To create a MultiLineTexture, use the newInstance() method and specify 13 | // the String, the font size, and the color. 14 | class MultiLineTexture extends CanvasTexture { 15 | private final Layout mLayout; 16 | 17 | private MultiLineTexture(Layout layout) { 18 | super(layout.getWidth(), layout.getHeight()); 19 | mLayout = layout; 20 | } 21 | 22 | public static MultiLineTexture newInstance( 23 | String text, int maxWidth, float textSize, int color, 24 | Layout.Alignment alignment) { 25 | TextPaint paint = StringTexture.getDefaultPaint(textSize, color, true); 26 | Layout layout = new StaticLayout(text, 0, text.length(), paint, 27 | maxWidth, alignment, 1, 0, true, null, 0); 28 | 29 | return new MultiLineTexture(layout); 30 | } 31 | 32 | @Override 33 | protected void onDraw(Canvas canvas, Bitmap backing) { 34 | mLayout.draw(canvas); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/opengl/NinePatchChunk.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.opengl; 2 | 3 | import android.graphics.Rect; 4 | 5 | import java.nio.ByteBuffer; 6 | import java.nio.ByteOrder; 7 | 8 | // See "frameworks/base/include/utils/ResourceTypes.h" for the format of 9 | // NinePatch chunk. 10 | class NinePatchChunk { 11 | 12 | public static final int NO_COLOR = 0x00000001; 13 | public static final int TRANSPARENT_COLOR = 0x00000000; 14 | 15 | public Rect mPaddings = new Rect(); 16 | 17 | public int mDivX[]; 18 | public int mDivY[]; 19 | public int mColor[]; 20 | 21 | private static void readIntArray(int[] data, ByteBuffer buffer) { 22 | for (int i = 0, n = data.length; i < n; ++i) { 23 | data[i] = buffer.getInt(); 24 | } 25 | } 26 | 27 | private static void checkDivCount(int length) { 28 | if (length == 0 || (length & 0x01) != 0) { 29 | throw new RuntimeException("invalid nine-patch: " + length); 30 | } 31 | } 32 | 33 | public static NinePatchChunk deserialize(byte[] data) { 34 | ByteBuffer byteBuffer = 35 | ByteBuffer.wrap(data).order(ByteOrder.nativeOrder()); 36 | 37 | byte wasSerialized = byteBuffer.get(); 38 | if (wasSerialized == 0) { 39 | return null; 40 | } 41 | 42 | NinePatchChunk chunk = new NinePatchChunk(); 43 | chunk.mDivX = new int[byteBuffer.get()]; 44 | chunk.mDivY = new int[byteBuffer.get()]; 45 | chunk.mColor = new int[byteBuffer.get()]; 46 | 47 | checkDivCount(chunk.mDivX.length); 48 | checkDivCount(chunk.mDivY.length); 49 | 50 | // skip 8 bytes 51 | byteBuffer.getInt(); 52 | byteBuffer.getInt(); 53 | 54 | chunk.mPaddings.left = byteBuffer.getInt(); 55 | chunk.mPaddings.right = byteBuffer.getInt(); 56 | chunk.mPaddings.top = byteBuffer.getInt(); 57 | chunk.mPaddings.bottom = byteBuffer.getInt(); 58 | 59 | // skip 4 bytes 60 | byteBuffer.getInt(); 61 | 62 | readIntArray(chunk.mDivX, byteBuffer); 63 | readIntArray(chunk.mDivY, byteBuffer); 64 | readIntArray(chunk.mColor, byteBuffer); 65 | 66 | return chunk; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/opengl/RawTexture.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.opengl; 2 | 3 | import com.hw.photomovie.util.MLog; 4 | 5 | import javax.microedition.khronos.opengles.GL11; 6 | 7 | public class RawTexture extends BasicTexture { 8 | private static final String TAG = "RawTexture"; 9 | 10 | private final boolean mOpaque; 11 | private boolean mIsFlipped; 12 | 13 | public RawTexture(int width, int height, boolean opaque) { 14 | mOpaque = opaque; 15 | setSize(width, height); 16 | } 17 | 18 | @Override 19 | public boolean isOpaque() { 20 | return mOpaque; 21 | } 22 | 23 | @Override 24 | public boolean isFlippedVertically() { 25 | return mIsFlipped; 26 | } 27 | 28 | public void setIsFlippedVertically(boolean isFlipped) { 29 | mIsFlipped = isFlipped; 30 | } 31 | 32 | public void prepare(GLESCanvas canvas) { 33 | GLId glId = canvas.getGLId(); 34 | mId = glId.generateTexture(); 35 | canvas.initializeTextureSize(this, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE); 36 | canvas.setTextureParameters(this); 37 | mState = STATE_LOADED; 38 | setAssociatedCanvas(canvas); 39 | } 40 | 41 | @Override 42 | protected boolean onBind(GLESCanvas canvas) { 43 | if (isLoaded()) { 44 | return true; 45 | } 46 | MLog.w(TAG, "lost the content due to context change"); 47 | return false; 48 | } 49 | 50 | @Override 51 | public void yield() { 52 | // we cannot free the texture because we have no backup. 53 | } 54 | 55 | @Override 56 | protected int getTarget() { 57 | return GL11.GL_TEXTURE_2D; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/opengl/ScreenNail.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.opengl; 2 | 3 | import android.graphics.RectF; 4 | 5 | public interface ScreenNail { 6 | public int getWidth(); 7 | 8 | public int getHeight(); 9 | 10 | public boolean isReady(); 11 | 12 | public void setLoadingTexture(StringTexture loadingTexture); 13 | 14 | public void draw(GLESCanvas canvas, int x, int y, int width, int height); 15 | 16 | // We do not need to draw this ScreenNail in this frame. 17 | public void noDraw(); 18 | 19 | // This ScreenNail will not be used anymore. Release related resources. 20 | public void recycle(); 21 | 22 | // This is only used by TileImageView to back up the tiles not yet loaded. 23 | public void draw(GLESCanvas canvas, RectF source, RectF dest); 24 | } 25 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/opengl/Texture.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.opengl; 2 | 3 | /** 4 | * @Author Jituo.Xuan 5 | * @Date 11:38:11 AM Mar 20, 2014 6 | * @Comments:Texture is a rectangular image which can be drawn on GLCanvas. 7 | */ 8 | public interface Texture { 9 | public int getWidth(); 10 | 11 | public int getHeight(); 12 | 13 | public void draw(GLESCanvas canvas, int x, int y); 14 | 15 | public void draw(GLESCanvas canvas, int x, int y, int w, int h); 16 | 17 | public boolean isOpaque(); 18 | } 19 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/opengl/animations/AlphaAnim.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.opengl.animations; 2 | 3 | 4 | import com.hw.photomovie.opengl.GLESCanvas; 5 | import com.hw.photomovie.util.Utils; 6 | 7 | public class AlphaAnim extends CanvasAnim { 8 | private final float mStartAlpha; 9 | private final float mEndAlpha; 10 | private float mCurrentAlpha; 11 | 12 | public AlphaAnim(float from, float to) { 13 | mStartAlpha = from; 14 | mEndAlpha = to; 15 | mCurrentAlpha = from; 16 | } 17 | 18 | @Override 19 | public void apply(GLESCanvas canvas) { 20 | canvas.multiplyAlpha(mCurrentAlpha); 21 | } 22 | 23 | @Override 24 | public int getCanvasSaveFlags() { 25 | return GLESCanvas.SAVE_FLAG_ALPHA; 26 | } 27 | 28 | @Override 29 | protected void onCalculate(float progress) { 30 | mCurrentAlpha = Utils.clamp(mStartAlpha + (mEndAlpha - mStartAlpha) * progress, 0f, 1f); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/opengl/animations/Animation.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.opengl.animations; 2 | 3 | import android.view.animation.Interpolator; 4 | import com.hw.photomovie.util.Utils; 5 | 6 | // Animation calculates a value according to the current input time. 7 | // 8 | // 1. First we need to use setDuration(int) to set the duration of the 9 | // animation. The duration is in milliseconds. 10 | // 2. Then we should call start(). The actual start time is the first value 11 | // passed to calculate(long). 12 | // 3. Each time we want to get an animation value, we call 13 | // calculate(long currentTimeMillis) to ask the Animation to calculate it. 14 | // The parameter passed to calculate(long) should be nonnegative. 15 | // 4. Use get() to get that value. 16 | // 17 | // In step 3, onCalculate(float progress) is called so subclasses can calculate 18 | // the value according to progress (progress is a value in [0,1]). 19 | // 20 | // Before onCalculate(float) is called, There is an optional interpolator which 21 | // can change the progress value. The interpolator can be set by 22 | // setInterpolator(Interpolator). If the interpolator is used, the value passed 23 | // to onCalculate may be (for example, the overshoot effect). 24 | // 25 | // The isActive() method returns true after the animation start() is called and 26 | // before calculate is passed a value which reaches the duration of the 27 | // animation. 28 | // 29 | // The start() method can be called again to restart the Animation. 30 | // 31 | public abstract class Animation { 32 | 33 | private static final String TAG = "Animation"; 34 | 35 | private static final long ANIMATION_START = -1; 36 | private static final long NO_ANIMATION = -2; 37 | 38 | private long mStartTime = NO_ANIMATION; 39 | private int mDuration; 40 | private Interpolator mInterpolator; 41 | 42 | public void setInterpolator(Interpolator interpolator) { 43 | mInterpolator = interpolator; 44 | } 45 | 46 | public void setDuration(int duration) { 47 | mDuration = duration; 48 | } 49 | 50 | public void start() { 51 | mStartTime = ANIMATION_START; 52 | } 53 | 54 | public void setStartTime(long time) { 55 | mStartTime = time; 56 | } 57 | 58 | public boolean isActive() { 59 | return mStartTime != NO_ANIMATION; 60 | } 61 | 62 | public void forceStop() { 63 | mStartTime = NO_ANIMATION; 64 | } 65 | 66 | public boolean calculate(long currentTimeMillis) { 67 | if (mStartTime == NO_ANIMATION) { 68 | return false; 69 | } 70 | if (mStartTime == ANIMATION_START) { 71 | mStartTime = currentTimeMillis; 72 | } 73 | int elapse = (int) (currentTimeMillis - mStartTime); 74 | float x = Utils.clamp((float) elapse / mDuration, 0f, 1f); 75 | Interpolator i = mInterpolator; 76 | onCalculate(i != null ? i.getInterpolation(x) : x); 77 | if (elapse >= mDuration) { 78 | mStartTime = NO_ANIMATION; 79 | } 80 | return mStartTime != NO_ANIMATION; 81 | } 82 | 83 | protected abstract void onCalculate(float progress); 84 | } 85 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/opengl/animations/AnimationTime.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.opengl.animations; 2 | 3 | import android.os.SystemClock; 4 | 5 | // 6 | // The animation time should ideally be the vsync time the frame will be 7 | // displayed, but that is an unknown time in the future. So we use the system 8 | // time just after eglSwapBuffers (when GLSurfaceView.onDrawFrame is called) 9 | // as a approximation. 10 | // 11 | public class AnimationTime { 12 | private static final String TAG = "AnimationTime"; 13 | 14 | private static volatile long sTime; 15 | 16 | // Sets current time as the animation time. 17 | public static void update() { 18 | 19 | sTime = SystemClock.uptimeMillis(); 20 | } 21 | 22 | // Returns the animation time. 23 | public static long get() { 24 | return sTime; 25 | } 26 | 27 | public static long startTime() { 28 | sTime = SystemClock.uptimeMillis(); 29 | return sTime; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/opengl/animations/CanvasAnim.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.opengl.animations; 2 | 3 | 4 | import com.hw.photomovie.opengl.GLESCanvas; 5 | 6 | public abstract class CanvasAnim extends Animation { 7 | 8 | public abstract int getCanvasSaveFlags(); 9 | 10 | public abstract void apply(GLESCanvas canvas); 11 | } 12 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/opengl/animations/CaptureAnim.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 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 | 17 | package com.hw.photomovie.opengl.animations; 18 | 19 | import android.view.animation.AccelerateDecelerateInterpolator; 20 | import android.view.animation.AccelerateInterpolator; 21 | import android.view.animation.DecelerateInterpolator; 22 | import android.view.animation.Interpolator; 23 | 24 | @SuppressWarnings("checkstyle:constantname") 25 | 26 | public class CaptureAnim { 27 | // The amount of change for zooming out. 28 | private static final float ZOOM_DELTA = 0.2f; 29 | // Pre-calculated value for convenience. 30 | private static final float ZOOM_IN_BEGIN = 1f - ZOOM_DELTA; 31 | 32 | private static final Interpolator sZoomOutInterpolator = 33 | new DecelerateInterpolator(); 34 | private static final Interpolator sZoomInInterpolator = 35 | new AccelerateInterpolator(); 36 | private static final Interpolator sSlideInterpolator = 37 | new AccelerateDecelerateInterpolator(); 38 | 39 | // Calculate the slide factor based on the give time fraction. 40 | public static float calculateSlide(float fraction) { 41 | return sSlideInterpolator.getInterpolation(fraction); 42 | } 43 | 44 | // Calculate the scale factor based on the given time fraction. 45 | public static float calculateScale(float fraction) { 46 | float value; 47 | if (fraction <= 0.5f) { 48 | // Zoom in for the beginning. 49 | value = 1f - ZOOM_DELTA * 50 | sZoomOutInterpolator.getInterpolation(fraction * 2); 51 | } else { 52 | // Zoom out for the ending. 53 | value = ZOOM_IN_BEGIN + ZOOM_DELTA * 54 | sZoomInInterpolator.getInterpolation((fraction - 0.5f) * 2f); 55 | } 56 | return value; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/opengl/animations/FloatAnim.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.opengl.animations; 2 | 3 | public class FloatAnim extends Animation { 4 | 5 | private final float mFrom; 6 | private final float mTo; 7 | private float mCurrent; 8 | 9 | public FloatAnim(float from, float to, int duration) { 10 | mFrom = from; 11 | mTo = to; 12 | mCurrent = from; 13 | setDuration(duration); 14 | } 15 | 16 | @Override 17 | protected void onCalculate(float progress) { 18 | mCurrent = mFrom + (mTo - mFrom) * progress; 19 | } 20 | 21 | public float get() { 22 | return mCurrent; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/opengl/animations/IntegerAnim.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.opengl.animations; 2 | 3 | 4 | import com.hw.photomovie.util.MLog; 5 | 6 | public class IntegerAnim extends Animation { 7 | 8 | private static final String TAG = "IntegerAnim"; 9 | 10 | private int mTarget; 11 | private int mCurrent = 0; 12 | private int mFrom = 0; 13 | private boolean mEnabled = false; 14 | 15 | public void setEnabled(boolean enabled) { 16 | mEnabled = enabled; 17 | } 18 | 19 | public boolean isEnabled() { 20 | return mEnabled; 21 | } 22 | 23 | public void startAnimateTo(int target) { 24 | 25 | if (!mEnabled) { 26 | mTarget = mCurrent = target; 27 | return; 28 | } 29 | MLog.i(TAG, " target:" + target + " mTarget:" + mTarget); 30 | if (target == mTarget) { 31 | return; 32 | } 33 | 34 | mFrom = mCurrent; 35 | mTarget = target; 36 | setDuration(300); 37 | start(); 38 | } 39 | 40 | public int get() { 41 | return mCurrent; 42 | } 43 | 44 | public int getTarget() { 45 | return mTarget; 46 | } 47 | 48 | @Override 49 | protected void onCalculate(float progress) { 50 | mCurrent = Math.round(mFrom + (1 - progress) * (mTarget - mFrom)); 51 | if (progress == 0f) { 52 | mEnabled = false; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/record/gles/FullFrameRect.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Google Inc. All rights reserved. 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 | 17 | package com.hw.photomovie.record.gles; 18 | 19 | /** 20 | * This class essentially represents a viewport-sized sprite that will be rendered with 21 | * a texture, usually from an external source like the camera or video decoder. 22 | */ 23 | public class FullFrameRect { 24 | private final Drawable2d mRectDrawable = new Drawable2d(Drawable2d.Prefab.FULL_RECTANGLE); 25 | private Texture2dProgram mProgram; 26 | 27 | /** 28 | * Prepares the object. 29 | * 30 | * @param program The program to use. FullFrameRect takes ownership, and will release 31 | * the program when no longer needed. 32 | */ 33 | public FullFrameRect(Texture2dProgram program) { 34 | mProgram = program; 35 | } 36 | 37 | /** 38 | * Releases resources. 39 | *

40 | * This must be called with the appropriate EGL context current (i.e. the one that was 41 | * current when the constructor was called). If we're about to destroy the EGL context, 42 | * there's no value in having the caller make it current just to do this cleanup, so you 43 | * can pass a flag that will tell this function to skip any EGL-context-specific cleanup. 44 | */ 45 | public void release(boolean doEglCleanup) { 46 | if (mProgram != null) { 47 | if (doEglCleanup) { 48 | mProgram.release(); 49 | } 50 | mProgram = null; 51 | } 52 | } 53 | 54 | /** 55 | * Returns the program currently in use. 56 | */ 57 | public Texture2dProgram getProgram() { 58 | return mProgram; 59 | } 60 | 61 | /** 62 | * Changes the program. The previous program will be released. 63 | *

64 | * The appropriate EGL context must be current. 65 | */ 66 | public void changeProgram(Texture2dProgram program) { 67 | mProgram.release(); 68 | mProgram = program; 69 | } 70 | 71 | /** 72 | * Creates a texture object suitable for use with drawFrame(). 73 | */ 74 | public int createTextureObject() { 75 | return mProgram.createTextureObject(); 76 | } 77 | 78 | /** 79 | * Draws a viewport-filling rect, texturing it with the specified texture object. 80 | */ 81 | public void drawFrame(int textureId, float[] texMatrix) { 82 | // Use the identity matrix for MVP so our 2x2 FULL_RECTANGLE covers the viewport. 83 | mProgram.draw(GlUtil.IDENTITY_MATRIX, mRectDrawable.getVertexArray(), 0, 84 | mRectDrawable.getVertexCount(), mRectDrawable.getCoordsPerVertex(), 85 | mRectDrawable.getVertexStride(), 86 | texMatrix, mRectDrawable.getTexCoordArray(), textureId, 87 | mRectDrawable.getTexCoordStride()); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/record/gles/OffscreenSurface.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 Google Inc. All rights reserved. 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 | 17 | package com.hw.photomovie.record.gles; 18 | 19 | /** 20 | * Off-screen EGL surface (pbuffer). 21 | *

22 | * It's good practice to explicitly release() the surface, preferably from a "finally" block. 23 | */ 24 | public class OffscreenSurface extends EglSurfaceBase { 25 | /** 26 | * Creates an off-screen surface with the specified width and height. 27 | */ 28 | public OffscreenSurface(EglCore eglCore, int width, int height) { 29 | super(eglCore); 30 | createOffscreenSurface(width, height); 31 | } 32 | 33 | /** 34 | * Releases any resources associated with the surface. 35 | */ 36 | public void release() { 37 | releaseEglSurface(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/record/gles/WindowSurface.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 Google Inc. All rights reserved. 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 | 17 | package com.hw.photomovie.record.gles; 18 | 19 | import android.graphics.SurfaceTexture; 20 | import android.view.Surface; 21 | 22 | /** 23 | * Recordable EGL window surface. 24 | *

25 | * It's good practice to explicitly release() the surface, preferably from a "finally" block. 26 | */ 27 | public class WindowSurface extends EglSurfaceBase { 28 | private Surface mSurface; 29 | private boolean mReleaseSurface; 30 | 31 | /** 32 | * Associates an EGL surface with the native window surface. 33 | *

34 | * Set releaseSurface to true if you want the Surface to be released when release() is 35 | * called. This is convenient, but can interfere with framework classes that expect to 36 | * manage the Surface themselves (e.g. if you release a SurfaceView's Surface, the 37 | * surfaceDestroyed() callback won't fire). 38 | */ 39 | public WindowSurface(EglCore eglCore, Surface surface, boolean releaseSurface) { 40 | super(eglCore); 41 | createWindowSurface(surface); 42 | mSurface = surface; 43 | mReleaseSurface = releaseSurface; 44 | } 45 | 46 | /** 47 | * Associates an EGL surface with the SurfaceTexture. 48 | */ 49 | public WindowSurface(EglCore eglCore, SurfaceTexture surfaceTexture) { 50 | super(eglCore); 51 | createWindowSurface(surfaceTexture); 52 | } 53 | 54 | /** 55 | * Releases any resources associated with the EGL surface (and, if configured to do so, 56 | * with the Surface as well). 57 | *

58 | * Does not require that the surface's EGL context be current. 59 | */ 60 | public void release() { 61 | releaseEglSurface(); 62 | if (mSurface != null) { 63 | if (mReleaseSurface) { 64 | mSurface.release(); 65 | } 66 | mSurface = null; 67 | } 68 | } 69 | 70 | /** 71 | * Recreate the EGLSurface, using the new EglBase. The caller should have already 72 | * freed the old EGLSurface with releaseEglSurface(). 73 | *

74 | * This is useful when we want to update the EGLSurface associated with a Surface. 75 | * For example, if we want to share with a different EGLContext, which can only 76 | * be done by tearing down and recreating the context. (That's handled by the caller; 77 | * this just creates a new EGLSurface for the Surface we were handed earlier.) 78 | *

79 | * If the previous EGLSurface isn't fully destroyed, e.g. it's still current on a 80 | * context somewhere, the create call will fail with complaints from the Surface 81 | * about already being connected. 82 | */ 83 | public void recreate(EglCore newEglCore) { 84 | if (mSurface == null) { 85 | throw new RuntimeException("not yet implemented for SurfaceTexture"); 86 | } 87 | mEglCore = newEglCore; // switch to new context 88 | createWindowSurface(mSurface); // create new surface 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/render/GLTextureMovieRender.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.render; 2 | 3 | import android.opengl.GLES20; 4 | import com.hw.photomovie.util.MLog; 5 | 6 | import javax.microedition.khronos.egl.EGLConfig; 7 | import javax.microedition.khronos.opengles.GL10; 8 | 9 | /** 10 | * Created by huangwei on 2018/9/6 0006. 11 | */ 12 | public class GLTextureMovieRender extends GLSurfaceMovieRenderer { 13 | 14 | private static final String TAG = "GLTextureMovieRender"; 15 | protected GLTextureView mGLTextureView; 16 | 17 | public GLTextureMovieRender(GLTextureView glTextureView) { 18 | mGLTextureView = glTextureView; 19 | mGLTextureView.setEGLContextClientVersion(2); 20 | mGLTextureView.setRenderer(new GLTextureView.Renderer() { 21 | @Override 22 | public void onSurfaceCreated(GL10 gl, EGLConfig config) { 23 | //资源起其实已经销毁了,这里只是告知其保存的纹理已经不可用,需要重建 24 | if (mMovieFilter != null) { 25 | mMovieFilter.release(); 26 | } 27 | if(mCoverSegment!=null){ 28 | mCoverSegment.release(); 29 | } 30 | releaseTextures(); 31 | mNeedRelease.set(false); 32 | mSurfaceCreated = true; 33 | prepare(); 34 | } 35 | 36 | @Override 37 | public void onSurfaceChanged(GL10 gl, int width, int height) { 38 | setViewport(width, height); 39 | } 40 | 41 | @Override 42 | public boolean onDrawFrame(GL10 gl) { 43 | if (mNeedRelease.get()) { 44 | mNeedRelease.set(false); 45 | releaseGLResources(); 46 | return false; 47 | } 48 | GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); 49 | drawMovieFrame(mElapsedTime); 50 | return true; 51 | } 52 | 53 | @Override 54 | public void onSurfaceDestroyed() { 55 | mSurfaceCreated = false; 56 | mNeedRelease.set(false); 57 | } 58 | }); 59 | mGLTextureView.setRenderMode(GLTextureView.RENDERMODE_WHEN_DIRTY); 60 | } 61 | 62 | @Override 63 | public void drawFrame(int elapsedTime) { 64 | mElapsedTime = elapsedTime; 65 | if (mRenderToRecorder) { 66 | onDrawFrame(null); 67 | return; 68 | } 69 | if (mSurfaceCreated) { 70 | mGLTextureView.requestRender(); 71 | } else { 72 | MLog.e(TAG, "Surface not created!"); 73 | } 74 | } 75 | 76 | @Override 77 | public void release() { 78 | mNeedRelease.set(true); 79 | if (mSurfaceCreated) { 80 | mGLTextureView.requestRender(); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/render/MovieRenderer.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.render; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.Rect; 5 | import android.graphics.RectF; 6 | import com.hw.photomovie.PhotoMovie; 7 | import com.hw.photomovie.opengl.GLESCanvas; 8 | import com.hw.photomovie.segment.MovieSegment; 9 | import com.hw.photomovie.segment.SingleBitmapSegment; 10 | import com.hw.photomovie.segment.WaterMarkSegment; 11 | 12 | import java.util.List; 13 | 14 | /** 15 | * Created by huangwei on 2015/5/26. 16 | */ 17 | public abstract class MovieRenderer { 18 | protected PhotoMovie mPhotoMovie; 19 | protected volatile int mElapsedTime; 20 | protected Rect mViewportRect = new Rect(); 21 | protected T mPainter; 22 | protected boolean mEnableDraw = true; 23 | protected OnReleaseListener mOnReleaseListener; 24 | protected MovieSegment mCurrentSegment; 25 | /** 26 | * 用于展示水印 27 | */ 28 | protected MovieSegment mCoverSegment; 29 | 30 | public MovieRenderer() { 31 | } 32 | 33 | public abstract void drawFrame(int elapsedTime); 34 | 35 | public MovieRenderer setPainter(T painter) { 36 | mPainter = painter; 37 | return this; 38 | } 39 | 40 | public void drawMovieFrame(int elapsedTime) { 41 | if (mPhotoMovie == null || !mEnableDraw) { 42 | return; 43 | } 44 | PhotoMovie.SegmentPicker segmentPicker = mPhotoMovie.getSegmentPicker(); 45 | MovieSegment movieSegment = segmentPicker.pickCurrentSegment(elapsedTime); 46 | if (movieSegment != null) { 47 | float segmentProgress = segmentPicker.getSegmentProgress(movieSegment, elapsedTime); 48 | if (movieSegment.showNextAsBackground()) { 49 | MovieSegment nextSegment = segmentPicker.getNextSegment(elapsedTime); 50 | if (nextSegment != null && nextSegment != movieSegment) { 51 | nextSegment.drawFrame(mPainter, 0); 52 | } 53 | } 54 | movieSegment.drawFrame(mPainter, segmentProgress); 55 | mCurrentSegment = movieSegment; 56 | } 57 | if(mCoverSegment!=null && mPainter instanceof GLESCanvas){ 58 | mCoverSegment.drawFrame(mPainter,0); 59 | } 60 | } 61 | 62 | public void releaseCoverSegment() { 63 | if(mCoverSegment!=null){ 64 | mCoverSegment.release(); 65 | } 66 | } 67 | 68 | public void setMovieViewport(int l, int t, int r, int b) { 69 | if (mPhotoMovie != null) { 70 | for (MovieSegment segment : mPhotoMovie.getMovieSegments()) { 71 | segment.setViewport(l, t, r, b); 72 | } 73 | } 74 | if(mCoverSegment!=null){ 75 | mCoverSegment.setViewport(l, t, r, b); 76 | } 77 | mViewportRect.set(l, t, r, b); 78 | } 79 | 80 | public void setPhotoMovie(PhotoMovie photoMovie) { 81 | mPhotoMovie = photoMovie; 82 | if (mViewportRect.width() > 0 && mViewportRect.height() > 0) { 83 | setMovieViewport(mViewportRect.left, mViewportRect.top, mViewportRect.right, mViewportRect.bottom); 84 | } 85 | } 86 | 87 | public PhotoMovie getPhotoMovie() { 88 | return mPhotoMovie; 89 | } 90 | 91 | public void enableDraw(boolean enableDraw) { 92 | mEnableDraw = enableDraw; 93 | } 94 | 95 | public abstract void release(); 96 | public abstract void release(List> segments); 97 | 98 | public void setOnReleaseListener(OnReleaseListener listener) { 99 | mOnReleaseListener = listener; 100 | } 101 | 102 | public void setCoverSegment(MovieSegment coverSegment){ 103 | mCoverSegment = coverSegment; 104 | } 105 | 106 | public interface OnReleaseListener { 107 | void onRelease(); 108 | } 109 | } -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/segment/AbsLayerSegment.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.segment; 2 | 3 | import com.hw.photomovie.opengl.GLESCanvas; 4 | import com.hw.photomovie.segment.layer.MovieLayer; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | /** 10 | * Created by huangwei on 2015/6/3. 11 | */ 12 | public abstract class AbsLayerSegment extends MulitBitmapSegment { 13 | 14 | protected MovieLayer[] mLayers; 15 | 16 | public AbsLayerSegment() { 17 | super(); 18 | mLayers = initLayers(); 19 | } 20 | 21 | public AbsLayerSegment(int duration) { 22 | super(duration); 23 | mLayers = initLayers(); 24 | } 25 | 26 | protected abstract MovieLayer[] initLayers(); 27 | 28 | @Override 29 | public void drawFrame(GLESCanvas canvas, float segmentProgress) { 30 | if (mLayers == null || mLayers.length == 0) { 31 | return; 32 | } 33 | 34 | for (int i = 0; i < mLayers.length; i++) { 35 | mLayers[i].drawFrame(canvas, segmentProgress); 36 | } 37 | } 38 | 39 | @Override 40 | public void setViewport(int l, int t, int r, int b) { 41 | super.setViewport(l, t, r, b); 42 | for (int i = 0; mLayers != null && i < mLayers.length; i++) { 43 | mLayers[i].setViewprot(l, t, r, b); 44 | } 45 | } 46 | 47 | @Override 48 | public int getRequiredPhotoNum() { 49 | int num = 0; 50 | for (int i = 0; mLayers != null && i < mLayers.length; i++) { 51 | num += mLayers[i].getRequiredPhotoNum(); 52 | } 53 | return num; 54 | } 55 | 56 | @Override 57 | protected void onDataPrepared() { 58 | allocPhotoToLayers(); 59 | for(int i=0;mLayers!=null && i photoDatas = new ArrayList(); 70 | for (MovieLayer layer : mLayers) { 71 | photoDatas.clear(); 72 | int required = layer.getRequiredPhotoNum(); 73 | while (required > 0) { 74 | if (index >= mPhotos.size()) { 75 | index = 0; 76 | } 77 | photoDatas.add(mPhotoDataMap.get(mPhotos.get(index))); 78 | --required; 79 | ++index; 80 | } 81 | layer.allocPhotos(photoDatas); 82 | } 83 | } 84 | 85 | @Override 86 | public void onRelease() { 87 | super.onRelease(); 88 | for(int i=0;mLayers!=null && i { 9 | } 10 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/segment/GradientSegment.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.segment; 2 | 3 | import com.hw.photomovie.opengl.GLESCanvas; 4 | 5 | /** 6 | * Created by huangwei on 2018/9/12 0012. 7 | */ 8 | public class GradientSegment extends FitCenterSegment { 9 | /** 10 | * 缩放动画范围 11 | */ 12 | private float mScaleFrom; 13 | private float mScaleTo; 14 | /** 15 | * 开始做alpha动画的进度 16 | */ 17 | private float mAlphaStartProgress; 18 | private float mProgress; 19 | 20 | /** 21 | * @param duration 片段时长 22 | * @param alphaDuration 后半段的alpha动画时长 23 | * @param scaleFrom 缩放范围 24 | * @param scaleTo 缩放范围 25 | */ 26 | public GradientSegment(int duration, int alphaDuration,float scaleFrom,float scaleTo) { 27 | super(duration); 28 | mScaleFrom = scaleFrom; 29 | mScaleTo = scaleTo; 30 | mAlphaStartProgress = (duration-alphaDuration) / (float) duration; 31 | } 32 | 33 | @Override 34 | protected void onDataPrepared() { 35 | super.onDataPrepared(); 36 | } 37 | 38 | @Override 39 | public void drawFrame(GLESCanvas canvas, float segmentProgress) { 40 | mProgress = segmentProgress; 41 | super.drawFrame(canvas, segmentProgress); 42 | } 43 | 44 | @Override 45 | protected void drawContent(GLESCanvas canvas, float scale) { 46 | //FitCenterSegment已提供了缩放功能,这里我们只要提供自己需要的放大倍率即可 47 | scale = mScaleFrom + (mScaleTo - mScaleFrom) * mProgress; 48 | 49 | if (mProgress < mAlphaStartProgress) { 50 | //只展示放大动画 51 | super.drawContent(canvas, scale); 52 | } else { 53 | float alpha = 1 - (mProgress - mAlphaStartProgress) / (1 - mAlphaStartProgress); 54 | //加上alpha效果 55 | canvas.save(); 56 | canvas.setAlpha(alpha); 57 | super.drawContent(canvas, scale); 58 | canvas.restore(); 59 | } 60 | } 61 | 62 | @Override 63 | public boolean showNextAsBackground() { 64 | return true; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/segment/GradientTransferSegment.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.segment; 2 | 3 | import android.opengl.GLES20; 4 | import com.hw.photomovie.opengl.GLESCanvas; 5 | 6 | /** 7 | * Created by huangwei on 2018/9/12 0012. 8 | */ 9 | public class GradientTransferSegment extends TransitionSegment { 10 | /** 11 | * 缩放动画范围 12 | */ 13 | private float mPreScaleFrom; 14 | private float mPreScaleTo; 15 | private float mNextScaleFrom; 16 | private float mNextScaleTo; 17 | 18 | public GradientTransferSegment(int duration, 19 | float preScaleFrom, float preScaleTo, 20 | float nextScaleFrom, float nextScaleTo) { 21 | mPreScaleFrom = preScaleFrom; 22 | mPreScaleTo = preScaleTo; 23 | mNextScaleFrom = nextScaleFrom; 24 | mNextScaleTo = nextScaleTo; 25 | setDuration(duration); 26 | } 27 | 28 | @Override 29 | protected void onDataPrepared() { 30 | 31 | } 32 | 33 | @Override 34 | public void drawFrame(GLESCanvas canvas, float segmentProgress) { 35 | GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); 36 | //下一个片段开始放大 37 | float nextScale = mNextScaleFrom + (mNextScaleTo - mNextScaleFrom) * segmentProgress; 38 | mNextSegment.drawContent(canvas, nextScale); 39 | 40 | //上一个片段继续放大同时变透明 41 | float preScale = mPreScaleFrom + (mPreScaleTo - mPreScaleFrom) * segmentProgress; 42 | float alpha = 1 - segmentProgress; 43 | mPreSegment.drawBackground(canvas); 44 | canvas.save(); 45 | canvas.setAlpha(alpha); 46 | mPreSegment.drawContent(canvas, preScale); 47 | canvas.restore(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/segment/LayerSegment.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.segment; 2 | 3 | import com.hw.photomovie.segment.layer.MovieLayer; 4 | 5 | /** 6 | * Created by huangwei on 2015/6/10. 7 | */ 8 | public class LayerSegment extends AbsLayerSegment { 9 | 10 | public LayerSegment(MovieLayer[] layers, int duration) { 11 | super(duration); 12 | mLayers = layers; 13 | } 14 | 15 | @Override 16 | protected MovieLayer[] initLayers() { 17 | return mLayers; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/segment/MoveTransitionSegment.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.segment; 2 | 3 | import android.animation.TimeInterpolator; 4 | import android.view.animation.DecelerateInterpolator; 5 | import com.hw.photomovie.opengl.GLESCanvas; 6 | 7 | /** 8 | * Created by huangwei on 2018/9/4 0004. 9 | */ 10 | public class MoveTransitionSegment extends TransitionSegment { 11 | 12 | public static int DIRECTION_HORIZON = 0; 13 | public static int DIRECTION_VERTICAL = 1; 14 | 15 | private float mScaleFrom = 1f; 16 | private float mScaleTo = 0.7f; 17 | private int mDirection; 18 | private TimeInterpolator mInterpolator = new DecelerateInterpolator(1); 19 | 20 | public MoveTransitionSegment(int direction, int duration) { 21 | mDirection = direction; 22 | setDuration(duration); 23 | } 24 | 25 | @Override 26 | protected void onDataPrepared() { 27 | mNextSegment.onDataPrepared(); 28 | } 29 | 30 | @Override 31 | public void drawFrame(GLESCanvas canvas, float segmentProgress) { 32 | segmentProgress = mInterpolator.getInterpolation(segmentProgress); 33 | 34 | canvas.fillRect(0, 0, mViewportRect.width(), mViewportRect.height(), mPreSegment.getBackgroundColor()); 35 | 36 | canvas.save(); 37 | canvas.setAlpha(1 - segmentProgress); 38 | float scale = mScaleFrom + (mScaleTo - mScaleFrom) * segmentProgress; 39 | mPreSegment.drawContent(canvas, scale); 40 | canvas.restore(); 41 | 42 | if (mDirection == DIRECTION_VERTICAL) { 43 | canvas.save(); 44 | canvas.translate(0, (1 - segmentProgress) * mViewportRect.height()); 45 | mNextSegment.drawContent(canvas, 1f); 46 | canvas.restore(); 47 | } else { 48 | canvas.save(); 49 | canvas.translate((1 - segmentProgress) * mViewportRect.width(), 0); 50 | mNextSegment.drawContent(canvas, 1f); 51 | canvas.restore(); 52 | } 53 | } 54 | 55 | @Override 56 | public void onPrepare() { 57 | super.onPrepare(); 58 | } 59 | 60 | @Override 61 | public void setViewport(int l, int t, int r, int b) { 62 | super.setViewport(l, t, r, b); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/segment/ScaleSegment.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.segment; 2 | 3 | import android.graphics.Bitmap; 4 | import com.hw.photomovie.model.PhotoData; 5 | import com.hw.photomovie.opengl.BitmapTexture; 6 | import com.hw.photomovie.opengl.GLESCanvas; 7 | import com.hw.photomovie.segment.animation.SrcAnimation; 8 | import com.hw.photomovie.segment.animation.SrcScaleAnimation; 9 | import com.hw.photomovie.util.Utils; 10 | 11 | /** 12 | * Created by huangwei on 2015/5/30. 13 | */ 14 | public class ScaleSegment extends SingleBitmapSegment { 15 | 16 | private SrcAnimation mSrcAnimation; 17 | private float mFrom = 1f; 18 | private float mTo = 1f; 19 | 20 | public ScaleSegment(int duration, float from, float to) { 21 | this.mDuration = duration; 22 | mFrom = from; 23 | mTo = to; 24 | } 25 | 26 | public void onPrepare() { 27 | PhotoData photoData = this.getPhoto(0); 28 | if (photoData != null) { 29 | photoData.prepareData(4, new PluginListener(this)); 30 | } else { 31 | throw new NullPointerException("PhotoData is null"); 32 | } 33 | } 34 | 35 | protected void onDataPrepared() { 36 | mBitmapInfo.applyScaleType(mViewportRect); 37 | mSrcAnimation = new SrcScaleAnimation(mBitmapInfo.srcRect, mBitmapInfo.srcShowRect, mViewportRect, mFrom, mTo); 38 | mDataPrepared = true; 39 | } 40 | 41 | public void drawFrame(float segmentProgress) { 42 | } 43 | 44 | public void drawFrame(GLESCanvas canvas, float segmentRate) { 45 | if (!mDataPrepared) { 46 | return; 47 | } 48 | mSrcAnimation.update(segmentRate); 49 | if (this.mBitmapInfo != null && mBitmapInfo.bitmapTexture != null) { 50 | canvas.drawTexture(this.mBitmapInfo.bitmapTexture, this.mBitmapInfo.srcShowRect, this.mViewportRect); 51 | } 52 | 53 | } 54 | 55 | public int getRequiredPhotoNum() { 56 | return 1; 57 | } 58 | 59 | private class PluginListener extends PhotoData.SimpleOnDataLoadListener { 60 | private ScaleSegment segment; 61 | 62 | public PluginListener(ScaleSegment segment) { 63 | this.segment = segment; 64 | } 65 | 66 | @Override 67 | public void onDataLoaded(PhotoData photoData, Bitmap bitmap) { 68 | boolean success = false; 69 | if (Utils.isBitmapAvailable(bitmap)) { 70 | segment.mBitmapInfo = new BitmapInfo(); 71 | segment.mBitmapInfo.bitmapTexture = new BitmapTexture(bitmap); 72 | segment.mBitmapInfo.srcRect.set(0, 0, bitmap.getWidth(), bitmap.getHeight()); 73 | segment.mBitmapInfo.srcShowRect.set(0, 0, bitmap.getWidth(), bitmap.getHeight()); 74 | segment.onDataPrepared(); 75 | success = true; 76 | } 77 | 78 | if (segment.mOnSegmentPrepareListener != null) { 79 | segment.mOnSegmentPrepareListener.onSegmentPrepared(success); 80 | } 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/segment/ScaleTransSegment.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.segment; 2 | 3 | import android.text.TextUtils; 4 | import com.hw.photomovie.model.PhotoData; 5 | import com.hw.photomovie.model.PhotoInfo; 6 | import com.hw.photomovie.opengl.GLESCanvas; 7 | import com.hw.photomovie.segment.layer.MovieLayer; 8 | import com.hw.photomovie.segment.layer.ScaleTransLayer; 9 | import com.hw.photomovie.segment.layer.SubtitleLayer; 10 | 11 | import java.util.List; 12 | 13 | /** 14 | * Created by huangwei on 2015/6/10. 15 | */ 16 | public class ScaleTransSegment extends AbsLayerSegment{ 17 | 18 | private static final int SCALE_DURATION_SHORT = 2000; 19 | private static final int SCALE_DURATION_LONG = 3000; 20 | private static final int TRANS_DURATION_LONG = 700; 21 | 22 | private int mScaleDuration; 23 | 24 | private String mDesStr; 25 | 26 | private ScaleTransLayer mScaleLayer; 27 | private SubtitleLayer mSubtitleLayer; 28 | private float mScaleRate; 29 | 30 | public ScaleTransSegment(){ 31 | IS_DURATION_VARIABLE = true; 32 | } 33 | @Override 34 | protected MovieLayer[] initLayers() { 35 | mScaleLayer = new ScaleTransLayer(1f, 1.05f); 36 | mSubtitleLayer = new SubtitleLayer(); 37 | return new MovieLayer[]{mScaleLayer, mSubtitleLayer}; 38 | } 39 | 40 | @Override 41 | public void drawFrame(GLESCanvas canvas, float segmentProgress) { 42 | super.drawFrame(canvas, segmentProgress); 43 | } 44 | 45 | @Override 46 | public void onPrepare() { 47 | super.onPrepare(); 48 | PhotoInfo photoInfo = null; 49 | if (mPhotos != null && mPhotos.size() > 0) { 50 | photoInfo = mPhotos.get(0).getPhotoInfo(); 51 | } 52 | initSubtitle(photoInfo); 53 | } 54 | 55 | @Override 56 | public void allocPhotos(List photos) { 57 | super.allocPhotos(photos); 58 | // PhotoInfo photoInfo = null; 59 | // if (getAllocatedPhotos() != null && getAllocatedPhotos().size() > 0) { 60 | // photoInfo = getAllocatedPhotos().get(0).getPhotoInfo(); 61 | // } 62 | // initSubtitle(photoInfo); 63 | } 64 | 65 | private void initSubtitle(PhotoInfo photoInfo) { 66 | mDesStr = photoInfo == null ? null : photoInfo.description; 67 | //字幕 68 | if (TextUtils.isEmpty(mDesStr)) { 69 | mScaleDuration = SCALE_DURATION_SHORT; 70 | } else { 71 | int count = mDesStr.length() / 15; 72 | count += mDesStr.length() % 15 == 0 ? 0 : 1; 73 | mScaleDuration = count * SCALE_DURATION_LONG; 74 | } 75 | mScaleRate = mScaleDuration / (float) (mScaleDuration + TRANS_DURATION_LONG); 76 | mScaleLayer.setScaleRate(mScaleRate); 77 | mSubtitleLayer.setDisappearRate(SCALE_DURATION_LONG / (float) (SCALE_DURATION_LONG + TRANS_DURATION_LONG)); 78 | mSubtitleLayer.setSubtitle(mDesStr); 79 | } 80 | 81 | @Override 82 | public int getDuration() { 83 | return mScaleDuration + TRANS_DURATION_LONG; 84 | } 85 | 86 | @Override 87 | public int getRequiredPhotoNum() { 88 | return 1; 89 | } 90 | 91 | @Override 92 | public boolean showNextAsBackground() { 93 | return true; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/segment/TestLayerSegment.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.segment; 2 | 3 | import com.hw.photomovie.segment.layer.MovieLayer; 4 | import com.hw.photomovie.segment.layer.MovieTextLayer; 5 | import com.hw.photomovie.segment.layer.TestBaseLayer; 6 | import com.hw.photomovie.segment.layer.TestMuiltBitmapLayer; 7 | 8 | /** 9 | * Created by huangwei on 2015/6/4. 10 | */ 11 | public class TestLayerSegment extends AbsLayerSegment { 12 | 13 | public TestLayerSegment() { 14 | super(); 15 | } 16 | 17 | public TestLayerSegment(int duration) { 18 | super(duration); 19 | } 20 | 21 | @Override 22 | protected MovieLayer[] initLayers() { 23 | TestBaseLayer baseLayer = new TestBaseLayer(); 24 | TestMuiltBitmapLayer testMuiltBitmapLayer = new TestMuiltBitmapLayer(); 25 | testMuiltBitmapLayer.setParentLayer(baseLayer); 26 | MovieTextLayer movieTextLayer = new MovieTextLayer(); 27 | return new MovieLayer[]{testMuiltBitmapLayer, baseLayer,movieTextLayer}; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/segment/ThawSegment.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.segment; 2 | 3 | import android.graphics.Color; 4 | import com.hw.photomovie.opengl.GLESCanvas; 5 | import com.hw.photomovie.segment.animation.SegmentAnimation; 6 | import com.hw.photomovie.segment.animation.SrcScaleAnimation; 7 | import com.hw.photomovie.segment.animation.SrcTransAnimation; 8 | 9 | /** 10 | * Created by huangwei on 2015/5/29. 11 | */ 12 | public class ThawSegment extends SingleBitmapSegment { 13 | 14 | private SegmentAnimation mSrcAnimation; 15 | private int mType; 16 | 17 | public ThawSegment(int duration, int type) { 18 | mDuration = duration; 19 | mType = type; 20 | } 21 | 22 | @Override 23 | public void drawFrame(GLESCanvas canvas, float segmentRate) { 24 | if (!mDataPrepared) { 25 | return; 26 | } 27 | if (mBitmapInfo != null && mBitmapInfo.bitmapTexture != null && !mViewportRect.isEmpty()) { 28 | if(mSrcAnimation==null){ 29 | createAnimation(); 30 | } 31 | if (segmentRate < 0.2) { 32 | mSrcAnimation.update(0); 33 | float ratio = getValue(1, 0, 1 / 0.2f * segmentRate); 34 | if (mType == 0) { 35 | ratio = 0; 36 | } 37 | canvas.drawMixed(mBitmapInfo.bitmapTexture, Color.WHITE, ratio, mBitmapInfo.srcShowRect, mViewportRect); 38 | } else if (segmentRate > 0.8) { 39 | float ratio = getValue(0, 1, (segmentRate - 0.8f) * 5f); 40 | canvas.drawMixed(mBitmapInfo.bitmapTexture, Color.WHITE, ratio, mBitmapInfo.srcShowRect, mViewportRect); 41 | } else { 42 | float ratio = getValue(0, 1, (segmentRate - 0.2f) * 1 / 0.6f); 43 | mSrcAnimation.update(ratio); 44 | canvas.drawTexture(mBitmapInfo.bitmapTexture, mBitmapInfo.srcShowRect, mViewportRect); 45 | } 46 | } 47 | } 48 | 49 | @Override 50 | protected void onDataPrepared() { 51 | super.onDataPrepared(); 52 | createAnimation(); 53 | } 54 | 55 | @Override 56 | public int getRequiredPhotoNum() { 57 | return 1; 58 | } 59 | 60 | protected void createAnimation() { 61 | if (!mBitmapInfo.srcRect.isEmpty() && !mViewportRect.isEmpty()) { 62 | // mSrcAnimation = new SrcScaleAnimation(mSrcRect, mShowSrcRect, mViewportRect, 1f, 0.5f); 63 | switch (mType) { 64 | case 0: 65 | mSrcAnimation = new SrcScaleAnimation(mBitmapInfo.srcRect, mBitmapInfo.srcShowRect, mViewportRect, 1.0f, 1.1f); 66 | break; 67 | case 1: 68 | mSrcAnimation = new SrcTransAnimation(mBitmapInfo.srcRect, mBitmapInfo.srcShowRect, mViewportRect, -0.4f, 0); 69 | break; 70 | case 2: 71 | mSrcAnimation = new SrcTransAnimation(mBitmapInfo.srcRect, mBitmapInfo.srcShowRect, mViewportRect, 0.4f, 0f); 72 | break; 73 | } 74 | } 75 | } 76 | 77 | private float getValue(float from, float to, float progress) { 78 | return from + (to - from) * progress; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /library/src/main/java/com/hw/photomovie/segment/TransitionSegment.java: -------------------------------------------------------------------------------- 1 | package com.hw.photomovie.segment; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * 转场片段,本身不需求照片,只持有上一个以及下一个片段,实现转场动画 7 | */ 8 | public abstract class TransitionSegment

 extends MulitBitmapSegment {
 9 | 
10 |     protected PRE mPreSegment;
11 |     protected NEXT mNextSegment;
12 | 
13 |     @Override
14 |     public void onPrepare() {
15 |         List movieSegments = mPhotoMovie.getMovieSegments();
16 |         int index = movieSegments.indexOf(this);
17 |         if (index <= 0 || index == movieSegments.size() - 1) {
18 |             throw new TransitionSegmentException("TransitionSegment must be in the middle of two other Segments");
19 |         }
20 |         mPreSegment = (PRE) movieSegments.get(index - 1);
21 |         mNextSegment = (NEXT) movieSegments.get(index + 1);
22 |         if (mPreSegment instanceof TransitionSegment || mNextSegment instanceof TransitionSegment) {
23 |             throw new TransitionSegmentException("TransitionSegment must be in the middle of two other Segments");
24 |         }
25 |         mNextSegment.setOnSegmentPrepareListener(new OnSegmentPrepareListener() {
26 |             @Override
27 |             public void onSegmentPrepared(boolean success) {
28 |                 onDataPrepared();
29 |                 mNextSegment.setOnSegmentPrepareListener(null);
30 |             }
31 |         });
32 |         mNextSegment.prepare();
33 |         mPreSegment.enableRelease(false);
34 |     }
35 | 
36 |     @Override
37 |     public int getRequiredPhotoNum() {
38 |         return 0;
39 |     }
40 | 
41 |     private static class TransitionSegmentException extends RuntimeException {
42 |         public TransitionSegmentException(String message) {
43 |             super(message);
44 |         }
45 |     }
46 | 
47 |     @Override
48 |     public void onRelease() {
49 |         super.onRelease();
50 |         if(mPreSegment!=null) {
51 |             mPreSegment.enableRelease(true);
52 |             mPreSegment.release();
53 |         }
54 |     }
55 | 
56 |     @Override
57 |     protected boolean checkPrepared() {
58 |         return false;
59 |     }
60 | }
61 | 


--------------------------------------------------------------------------------
/library/src/main/java/com/hw/photomovie/segment/WaterMarkSegment.java:
--------------------------------------------------------------------------------
 1 | package com.hw.photomovie.segment;
 2 | 
 3 | import android.graphics.Bitmap;
 4 | import android.graphics.Rect;
 5 | import android.graphics.RectF;
 6 | import android.util.Log;
 7 | import com.hw.photomovie.opengl.BitmapTexture;
 8 | import com.hw.photomovie.opengl.GLESCanvas;
 9 | import com.hw.photomovie.util.ScaleType;
10 | 
11 | /**
12 |  * Created by huangwei on 2018/10/26.
13 |  */
14 | public class WaterMarkSegment extends SingleBitmapSegment implements Cloneable{
15 | 
16 |     private Bitmap mBitmap;
17 |     private RectF mDstRect;
18 |     private float mAlpha;
19 | 
20 |     public void setWaterMark(Bitmap bitmap, RectF dstRect,float alpha) {
21 |         mBitmap = bitmap;
22 |         mDstRect = new RectF(dstRect);
23 |         mAlpha = alpha;
24 |         synchronized (this) {
25 |             mBitmapInfo = null;
26 |         }
27 |     }
28 | 
29 |     @Override
30 |     public void onPrepare() {
31 |         onDataPrepared();
32 |     }
33 | 
34 |     @Override
35 |     public void drawFrame(GLESCanvas canvas, float segmentRate) {
36 |         synchronized (this) {
37 |             if (mBitmapInfo == null && mBitmap != null && mDstRect != null) {
38 |                 BitmapTexture bitmapTexture = new BitmapTexture(mBitmap);
39 |                 bitmapTexture.setOpaque(false);
40 |                 mBitmapInfo = new BitmapInfo();
41 |                 mBitmapInfo.srcRect = new Rect(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
42 |                 mBitmapInfo.srcShowRect.set(mBitmapInfo.srcRect);
43 |                 mBitmapInfo.scaleType = ScaleType.FIT_XY;
44 |                 mBitmapInfo.bitmapTexture = bitmapTexture;
45 |                 onDataPrepared();
46 |             }
47 |         }
48 |         if (!mDataPrepared) {
49 |             return;
50 |         }
51 |         if (mBitmapInfo != null && mBitmapInfo.makeTextureAvailable(canvas)) {
52 |             canvas.save();
53 |             canvas.setAlpha(mAlpha);
54 |             canvas.drawTexture(mBitmapInfo.bitmapTexture, mBitmapInfo.srcShowRect, mDstRect);
55 |             canvas.restore();
56 |         }
57 |     }
58 | 
59 |     @Override
60 |     public WaterMarkSegment clone(){
61 |         WaterMarkSegment waterMarkSegment = new WaterMarkSegment();
62 |         waterMarkSegment.setWaterMark(mBitmap,mDstRect,mAlpha);
63 |         return waterMarkSegment;
64 |     }
65 | }
66 | 


--------------------------------------------------------------------------------
/library/src/main/java/com/hw/photomovie/segment/animation/DstAnimation.java:
--------------------------------------------------------------------------------
 1 | package com.hw.photomovie.segment.animation;
 2 | 
 3 | import android.graphics.RectF;
 4 | 
 5 | /**
 6 |  * 作用在输出Rect的动画,可用于缩放平移
 7 |  */
 8 | public class DstAnimation extends SegmentAnimation {
 9 | 
10 |     public RectF mDstRect ;
11 | 
12 |     public DstAnimation(RectF dstRect) {
13 |         mDstRect = dstRect;
14 |     }
15 | 
16 |     @Override
17 |     public RectF update(float progress) {
18 |         return mDstRect;
19 |     }
20 | 
21 |     public void updateDstRect(RectF dstRect){
22 |         mDstRect = dstRect;
23 |     }
24 | }
25 | 


--------------------------------------------------------------------------------
/library/src/main/java/com/hw/photomovie/segment/animation/DstScaleAnimation.java:
--------------------------------------------------------------------------------
 1 | package com.hw.photomovie.segment.animation;
 2 | 
 3 | import android.graphics.Matrix;
 4 | import android.graphics.RectF;
 5 | 
 6 | /**
 7 |  * Created by huangwei on 2015/6/10.
 8 |  */
 9 | public class DstScaleAnimation extends DstAnimation {
10 | 
11 |     private float mFromScale;
12 |     private float mToScale;
13 |     private RectF mProgressDstRect = new RectF();
14 |     private float mProgress;
15 |     private Matrix mScaleMatrix = new Matrix();
16 | 
17 |     public DstScaleAnimation(RectF dstRect, float fromScale, float toScale) {
18 |         super(dstRect);
19 |         mFromScale = fromScale;
20 |         mToScale = toScale;
21 |     }
22 | 
23 |     @Override
24 |     public RectF update(float progress) {
25 |         mProgress = mInterpolator.getInterpolation(progress);
26 |         mProgressDstRect.set(mDstRect);
27 |         float scale = mFromScale + (mToScale - mFromScale) * mProgress;
28 |         mScaleMatrix.setScale(scale, scale, mDstRect.centerX(), mDstRect.centerY());
29 |         mScaleMatrix.mapRect(mProgressDstRect);
30 |         return mProgressDstRect;
31 |     }
32 | 
33 |     @Override
34 |     public void updateDstRect(RectF dstRect) {
35 |         super.updateDstRect(dstRect);
36 |         update(mProgress);
37 |     }
38 | }
39 | 


--------------------------------------------------------------------------------
/library/src/main/java/com/hw/photomovie/segment/animation/DstTransAnimation.java:
--------------------------------------------------------------------------------
 1 | package com.hw.photomovie.segment.animation;
 2 | 
 3 | import android.graphics.RectF;
 4 | 
 5 | /**
 6 |  * Created by huangwei on 2015/6/10.
 7 |  */
 8 | public class DstTransAnimation extends DstAnimation {
 9 | 
10 |     private float mTransX;
11 |     private float mTransY;
12 |     private RectF mProgressDstRect = new RectF();
13 |     private float mProgress;
14 | 
15 |     public DstTransAnimation(RectF dstRect, float transX, float transY) {
16 |         super(dstRect);
17 |         mTransX = transX;
18 |         mTransY = transY;
19 |     }
20 | 
21 |     @Override
22 |     public RectF update(float progress) {
23 |         mProgress = mInterpolator.getInterpolation(progress);
24 |         mProgressDstRect.set(mDstRect);
25 |         mProgressDstRect.offset(mProgress * mDstRect.width() * mTransX, mProgress * mDstRect.height() * mTransY);
26 |         return mProgressDstRect;
27 |     }
28 | 
29 |     @Override
30 |     public void updateDstRect(RectF dstRect) {
31 |         super.updateDstRect(dstRect);
32 |         update(mProgress);
33 |     }
34 | }
35 | 


--------------------------------------------------------------------------------
/library/src/main/java/com/hw/photomovie/segment/animation/SegmentAnimation.java:
--------------------------------------------------------------------------------
 1 | package com.hw.photomovie.segment.animation;
 2 | 
 3 | import android.animation.TimeInterpolator;
 4 | import android.view.animation.LinearInterpolator;
 5 | 
 6 | /**
 7 |  * Created by huangwei on 2015/5/29.
 8 |  */
 9 | public abstract class SegmentAnimation {
10 |     protected TimeInterpolator mInterpolator = new LinearInterpolator();
11 | 
12 |     public abstract Object update(float progress);
13 | 
14 |     public void setInterpolator(TimeInterpolator interpolator) {
15 |         mInterpolator = interpolator;
16 |     }
17 | }
18 | 


--------------------------------------------------------------------------------
/library/src/main/java/com/hw/photomovie/segment/animation/SrcAnimation.java:
--------------------------------------------------------------------------------
 1 | package com.hw.photomovie.segment.animation;
 2 | 
 3 | import android.graphics.Rect;
 4 | import android.graphics.RectF;
 5 | 
 6 | /**
 7 |  * 作用在图片本身Rect的动画,可用于缩放平移
 8 |  */
 9 | public abstract class SrcAnimation extends SegmentAnimation {
10 | 
11 |     protected Rect mSrcRect;
12 |     protected RectF mSrcShowRect;
13 |     protected RectF mDstRect;
14 |     protected float mProgress;
15 | 
16 |     public SrcAnimation(Rect srcRect, RectF srcShowRect, RectF dstRect) {
17 |         mSrcShowRect = srcShowRect;
18 |         mSrcRect = srcRect;
19 |         mDstRect = dstRect;
20 |     }
21 | 
22 |     @Override
23 |     public RectF update(float progress) {
24 |         mProgress = progress;
25 |         return mSrcShowRect;
26 |     }
27 | 
28 |     public abstract void updateDstRect(RectF dstRect);
29 | }
30 | 


--------------------------------------------------------------------------------
/library/src/main/java/com/hw/photomovie/segment/animation/SrcLeftRightAnimation.java:
--------------------------------------------------------------------------------
 1 | package com.hw.photomovie.segment.animation;
 2 | 
 3 | import android.graphics.Rect;
 4 | import android.graphics.RectF;
 5 | import com.hw.photomovie.util.PhotoUtil;
 6 | 
 7 | /**
 8 |  * Created by huangwei on 2015/6/10.
 9 |  * 从最左边扫到最右边
10 |  */
11 | public class SrcLeftRightAnimation extends SrcAnimation {
12 |     private RectF mMaxShowRect = new RectF();
13 |     /**
14 |      * 转移开始前的初始位置
15 |      */
16 |     private RectF mInitRect = new RectF();
17 | 
18 |     private float mTransDisX;
19 | 
20 |     /**
21 |      * @param srcRect
22 |      * @param srcShowRect
23 |      * @param dstRect
24 |      */
25 |     public SrcLeftRightAnimation(Rect srcRect, RectF srcShowRect, RectF dstRect) {
26 |         super(srcRect, srcShowRect, dstRect);
27 |         updateDstRect(dstRect);
28 |     }
29 | 
30 |     @Override
31 |     public RectF update(float progress) {
32 |         mProgress = mInterpolator.getInterpolation(progress);
33 |         mSrcShowRect.set(mInitRect);
34 |         mSrcShowRect.offset(mTransDisX * mProgress, 0);
35 |         return mSrcShowRect;
36 |     }
37 | 
38 |     @Override
39 |     public void updateDstRect(RectF dstRect) {
40 |         mDstRect = dstRect;
41 | 
42 |         mMaxShowRect.set(PhotoUtil.getCroppedRect(
43 |                 null,
44 |                 mSrcRect.width(),
45 |                 mSrcRect.height(),
46 |                 dstRect.width(),
47 |                 dstRect.height()));
48 | 
49 |         float cy = mSrcRect.centerY();
50 |         float h = mMaxShowRect.height();
51 |         mInitRect.set(0, cy - h / 2f, mMaxShowRect.width(), cy + h / 2f);
52 |         mTransDisX = mSrcRect.width() - mMaxShowRect.width();
53 | 
54 |         update(mProgress);
55 |     }
56 | }
57 | 


--------------------------------------------------------------------------------
/library/src/main/java/com/hw/photomovie/segment/animation/SrcScaleAnimation.java:
--------------------------------------------------------------------------------
 1 | package com.hw.photomovie.segment.animation;
 2 | 
 3 | import android.graphics.Rect;
 4 | import android.graphics.RectF;
 5 | import com.hw.photomovie.util.PhotoUtil;
 6 | 
 7 | /**
 8 |  * Created by huangwei on 2015/5/29.
 9 |  */
10 | public class SrcScaleAnimation extends SrcAnimation {
11 | 
12 |     private float mFrom;
13 |     private float mTo;
14 | 
15 |     private RectF mMaxShowRect = new RectF();
16 | 
17 |     private float mFromW, mFromH, mToW, mToH;
18 |     private float mX, mY;
19 | 
20 |     public SrcScaleAnimation(Rect srcRect, RectF srcShowRect, RectF dstRect, float from, float to) {
21 |         super(srcRect, srcShowRect, dstRect);
22 |         mFrom = from;
23 |         mTo = to;
24 |         updateDstRect(dstRect);
25 |     }
26 | 
27 |     @Override
28 |     public RectF update(float progress) {
29 |         mProgress = mInterpolator.getInterpolation(progress);
30 |         float w = mFromW + (mToW - mFromW) * mProgress;
31 |         float h = mFromH + (mToH - mFromH) * mProgress;
32 |         mSrcShowRect.set(mX - w / 2, mY - h / 2, mX + w / 2, mY + h / 2);
33 |         return mSrcShowRect;
34 |     }
35 | 
36 |     @Override
37 |     public void updateDstRect(RectF dstRect) {
38 |         mDstRect = dstRect;
39 |         mMaxShowRect.set(PhotoUtil.getCroppedRect(null, mSrcRect.width(), mSrcRect.height(), dstRect.width(), dstRect.height()));
40 |         mX = mSrcRect.centerX();
41 |         mY = mSrcRect.centerY();
42 |         if (mFrom >= mTo) {
43 |             mToW = mMaxShowRect.width();
44 |             mToH = mMaxShowRect.height();
45 |             mFromH = mToH * (mTo / mFrom);
46 |             mFromW = mToW * (mTo / mFrom);
47 |         } else {
48 |             mFromW = mMaxShowRect.width();
49 |             mFromH = mMaxShowRect.height();
50 |             mToH = mFromH * (mFrom / mTo);
51 |             mToW = mFromW * (mFrom / mTo);
52 |         }
53 | 
54 |         update(mProgress);
55 |     }
56 | }
57 | 


--------------------------------------------------------------------------------
/library/src/main/java/com/hw/photomovie/segment/animation/SrcTransAnimation.java:
--------------------------------------------------------------------------------
 1 | package com.hw.photomovie.segment.animation;
 2 | 
 3 | import android.graphics.Rect;
 4 | import android.graphics.RectF;
 5 | import com.hw.photomovie.util.PhotoUtil;
 6 | 
 7 | /**
 8 |  * Created by huangwei on 2015/5/29.
 9 |  */
10 | public class SrcTransAnimation extends SrcAnimation {
11 | 
12 |     private RectF mMaxShowRect = new RectF();
13 |     /**
14 |      * 转移开始前的初始位置
15 |      */
16 |     private RectF mInitRect = new RectF();
17 | 
18 |     private float mTransDisX, mTransDisY;
19 |     private float mTransX, mTransY;
20 | 
21 |     public SrcTransAnimation(Rect srcRect, RectF srcShowRect, RectF dstRect, float transX, float transY) {
22 |         super(srcRect, srcShowRect, dstRect);
23 |         mTransX = transX;
24 |         mTransY = transY;
25 |         updateDstRect(dstRect);
26 |     }
27 | 
28 |     @Override
29 |     public RectF update(float progress) {
30 |         mProgress = mInterpolator.getInterpolation(progress);
31 |         mSrcShowRect.set(mInitRect);
32 |         mSrcShowRect.offset(mTransDisX * mProgress, mTransDisY * mProgress);
33 |         return mSrcShowRect;
34 |     }
35 | 
36 |     @Override
37 |     public void updateDstRect(RectF dstRect) {
38 |         mDstRect = dstRect;
39 |         mMaxShowRect.set(PhotoUtil.getCroppedRect(
40 |                 null,
41 |                 mSrcRect.width(),
42 |                 mSrcRect.height(),
43 |                 dstRect.width() * (1 + Math.abs(mTransX)),
44 |                 dstRect.height() * (1 + Math.abs(mTransY))));
45 |         float w = mMaxShowRect.width() / (1 + Math.abs(mTransX));
46 |         float h = mMaxShowRect.height() / (1 + Math.abs(mTransY));
47 |         mSrcShowRect.set(0, 0, w, h);
48 | 
49 |         if (mTransX > 0) {
50 |             mSrcShowRect.offsetTo(mMaxShowRect.left, mSrcShowRect.top);
51 |         } else if (mTransX < 0) {
52 |             mSrcShowRect.offsetTo(mMaxShowRect.right - mSrcShowRect.width(), mSrcShowRect.top);
53 |         } else {
54 |             mSrcShowRect.offsetTo(mMaxShowRect.centerX() - w / 2, mSrcShowRect.top);
55 |         }
56 | 
57 |         if (mTransY > 0) {
58 |             mSrcShowRect.offsetTo(mSrcShowRect.left, mMaxShowRect.top);
59 |         } else if (mTransY < 0) {
60 |             mSrcShowRect.offsetTo(mSrcShowRect.left, mMaxShowRect.bottom - mSrcShowRect.height());
61 |         } else {
62 |             mSrcShowRect.offsetTo(mSrcShowRect.left, mMaxShowRect.centerY() - h / 2);
63 |         }
64 | 
65 |         mInitRect.set(mSrcShowRect);
66 |         mTransDisX = mSrcShowRect.width() * mTransX;
67 |         mTransDisY = mSrcShowRect.height() * mTransY;
68 | 
69 |         update(mProgress);
70 |     }
71 | }
72 | 


--------------------------------------------------------------------------------
/library/src/main/java/com/hw/photomovie/segment/layer/AvailableRect.java:
--------------------------------------------------------------------------------
 1 | package com.hw.photomovie.segment.layer;
 2 | 
 3 | import android.graphics.PointF;
 4 | import android.graphics.RectF;
 5 | 
 6 | /**
 7 |  * Created by huangwei on 2015/6/3.
 8 |  */
 9 | public class AvailableRect {
10 |       public RectF rectF;
11 |       public float rotation;
12 |       /**
13 |        * 为null则以区域中点为中心点
14 |        */
15 |       public PointF rotationPivot;
16 | }
17 | 


--------------------------------------------------------------------------------
/library/src/main/java/com/hw/photomovie/segment/layer/GaussianBlurLayer.java:
--------------------------------------------------------------------------------
 1 | package com.hw.photomovie.segment.layer;
 2 | 
 3 | import android.graphics.Bitmap;
 4 | import com.hw.photomovie.opengl.BitmapTexture;
 5 | import com.hw.photomovie.opengl.GLESCanvas;
 6 | import com.hw.photomovie.segment.BitmapInfo;
 7 | import com.hw.photomovie.util.AppResources;
 8 | import com.hw.photomovie.util.stackblur.StackBlurManager;
 9 | 
10 | import java.util.List;
11 | 
12 | /**
13 |  * Created by huangwei on 2015/6/10.
14 |  */
15 | public class GaussianBlurLayer extends MovieLayer {
16 |     public static final int BLUR_RADIUS_DEFAULT = 10;
17 |     private BitmapInfo mBitmapInfo;
18 |     private BitmapInfo mBluredBitmapInfo;
19 | 
20 |     private float mBlurRadius = 10;
21 | 
22 |     @Override
23 |     public void drawFrame(GLESCanvas canvas, float progress) {
24 |         if (mBitmapInfo != null && mBluredBitmapInfo != null) {
25 |             canvas.drawTexture(mBitmapInfo.bitmapTexture, mBitmapInfo.srcShowRect, mViewprotRect);
26 |             canvas.drawMixed(mBluredBitmapInfo.bitmapTexture, 0, 1 - progress, mBluredBitmapInfo.srcShowRect, mViewprotRect);
27 |         }
28 |     }
29 | 
30 |     @Override
31 |     public int getRequiredPhotoNum() {
32 |         return 1;
33 |     }
34 | 
35 |     @Override
36 |     public void prepare() {
37 | 
38 |     }
39 | 
40 |     @Override
41 |     public void release() {
42 | 
43 |     }
44 | 
45 |     @Override
46 |     public void allocPhotos(List bitmapInfos) {
47 |         super.allocPhotos(bitmapInfos);
48 |         if (bitmapInfos != null && bitmapInfos.size() > 0) {
49 |             mBitmapInfo = bitmapInfos.get(0);
50 |         }
51 | 
52 |         if (mBitmapInfo != null) {
53 |             mBlurRadius = BLUR_RADIUS_DEFAULT * AppResources.getInstance().getAppDensity() + 0.5f;
54 |             Bitmap bitmap = mBitmapInfo.bitmapTexture.getBitmap();
55 |             StackBlurManager manager = new StackBlurManager(bitmap, 0.125f);
56 |             Bitmap bluredBitmap = manager.process((int) (mBlurRadius * 0.125f));
57 |             mBluredBitmapInfo = new BitmapInfo();
58 |             mBluredBitmapInfo.bitmapTexture = new BitmapTexture(bluredBitmap);
59 |             mBluredBitmapInfo.bitmapTexture.setOpaque(false);
60 |             mBluredBitmapInfo.srcRect.set(0, 0, bluredBitmap.getWidth(), bluredBitmap.getHeight());
61 |             mBluredBitmapInfo.applyScaleType(mViewprotRect);
62 |         }
63 |     }
64 | 
65 |     @Override
66 |     public void setViewprot(int l, int t, int r, int b) {
67 |         super.setViewprot(l, t, r, b);
68 |         if (mBluredBitmapInfo != null) {
69 |             mBluredBitmapInfo.applyScaleType(mViewprotRect);
70 |         }
71 |     }
72 | }
73 | 


--------------------------------------------------------------------------------
/library/src/main/java/com/hw/photomovie/segment/layer/MovieLayer.java:
--------------------------------------------------------------------------------
 1 | package com.hw.photomovie.segment.layer;
 2 | 
 3 | import android.graphics.RectF;
 4 | import com.hw.photomovie.opengl.GLESCanvas;
 5 | import com.hw.photomovie.segment.BitmapInfo;
 6 | 
 7 | import java.util.ArrayList;
 8 | import java.util.List;
 9 | 
10 | /**
11 |  * Created by huangwei on 2015/6/3.
12 |  */
13 | public abstract class MovieLayer {
14 | 
15 |     protected List mBitmapInfos = new ArrayList();
16 |     protected RectF mViewprotRect = new RectF();
17 | 
18 |     protected MovieLayer mParentLayer;
19 |     /**
20 |      * 给child指定的显示区域
21 |      */
22 |     protected AvailableRect[] mBaseChildAvailableRect;
23 |     /**
24 |      * 指定下一层的可用区域,左上角0,0,右下角1,1
25 |      * 该数组长度必须是5的整数倍
26 |      * 每五个元素分别代表一个显示区域的x1,y1,x2,y2,rotation
27 |      * 在{@link #setViewprot(int, int, int, int)}时会将次数组转化成实际的{@link #mBaseChildAvailableRect}数组
28 |      */
29 |     protected float[] NEXT_AVAILABLE_RECT;
30 |     private String subtitle;
31 | 
32 |     public abstract void drawFrame(GLESCanvas canvas, float progress);
33 | 
34 |     /**
35 |      * 获取该层指定的更上层的输出区域
36 |      *
37 |      * @return
38 |      */
39 |     public AvailableRect[] getChildLayerRects(float progress) {
40 |         return mBaseChildAvailableRect;
41 |     }
42 | 
43 |     /**
44 |      * 指定该层的parent
45 |      */
46 |     public void setParentLayer(MovieLayer parentLayer) {
47 |         mParentLayer = parentLayer;
48 |     }
49 | 
50 |     public void setViewprot(int l, int t, int r, int b) {
51 |         mViewprotRect.set(l, t, r, b);
52 |         if (NEXT_AVAILABLE_RECT == null || NEXT_AVAILABLE_RECT.length == 0 || NEXT_AVAILABLE_RECT.length % 5 != 0) {
53 |             //默认指定chilid的显示区域为整个窗口区域
54 |             AvailableRect availableRect = new AvailableRect();
55 |             availableRect.rectF = new RectF(mViewprotRect);
56 |             availableRect.rotation = 0;
57 |             mBaseChildAvailableRect = new AvailableRect[]{availableRect};
58 |             return;
59 |         }
60 |         mBaseChildAvailableRect = new AvailableRect[NEXT_AVAILABLE_RECT.length / 5];
61 |         for (int i = 0; i < NEXT_AVAILABLE_RECT.length; i += 5) {
62 |             float x1 = NEXT_AVAILABLE_RECT[i];
63 |             float y1 = NEXT_AVAILABLE_RECT[i + 1];
64 |             float x2 = NEXT_AVAILABLE_RECT[i + 2];
65 |             float y2 = NEXT_AVAILABLE_RECT[i + 3];
66 |             float rotation = NEXT_AVAILABLE_RECT[i + 4];
67 | 
68 |             AvailableRect availableRect = new AvailableRect();
69 |             availableRect.rectF = new RectF(
70 |                     l + mViewprotRect.width() * x1,
71 |                     t + mViewprotRect.height() * y1,
72 |                     l + mViewprotRect.width() * x2,
73 |                     t + mViewprotRect.height() * y2);
74 |             availableRect.rotation = rotation;
75 |             mBaseChildAvailableRect[i / 5] = availableRect;
76 |         }
77 |     }
78 | 
79 |     /**
80 |      * 该layer需要多少张照片
81 |      *
82 |      * @return
83 |      */
84 |     public abstract int getRequiredPhotoNum();
85 | 
86 |     public void allocPhotos(List bitmapInfos) {
87 |         mBitmapInfos.clear();
88 |         mBitmapInfos.addAll(bitmapInfos);
89 |     }
90 | 
91 |     public abstract void prepare();
92 | 
93 |     public abstract void release();
94 | }
95 | 


--------------------------------------------------------------------------------
/library/src/main/java/com/hw/photomovie/segment/layer/TestBaseLayer.java:
--------------------------------------------------------------------------------
 1 | package com.hw.photomovie.segment.layer;
 2 | 
 3 | import android.graphics.PointF;
 4 | import android.graphics.RectF;
 5 | import com.hw.photomovie.opengl.BitmapTexture;
 6 | import com.hw.photomovie.opengl.GLESCanvas;
 7 | 
 8 | /**
 9 |  * Created by huangwei on 2015/6/3.
10 |  */
11 | public class TestBaseLayer extends MovieLayer {
12 | 
13 |     protected BitmapTexture mBitmapTexture;
14 |     protected RectF mSrcRect = new RectF();
15 | 
16 |     public TestBaseLayer() {
17 | //        NEXT_AVAILABLE_RECT = new float[]{
18 | //                0.25f, 0.25f, 0.35f, 0.35f, 0f,
19 | //                0.5f, 0.5f, 0.85f, 0.9f, 60f
20 | //        };
21 |         NEXT_AVAILABLE_RECT = new float[]{
22 |                 40 / 800f, 110 / 589f, 410 / 800f, 388 / 598f, 0f,
23 |                 607 / 800f, 43 / 589f, 741 / 800f, 141 / 598f, 0f,
24 |                 623 / 800f, 229 / 589f, 731 / 800f, 376 / 598f, 0f,
25 |                 607 / 800f, 468 / 589f, 741 / 800f, 564 / 598f, 0f
26 |         };
27 |     }
28 | 
29 |     @Override
30 |     public void prepare() {
31 | //        Bitmap bitmap = BitmapFactory.decodeResource(AppResources.getInstance().getAppRes(), R.drawable.testpng);
32 | //        mSrcRect.set(0, 0, bitmap.getWidth(), bitmap.getHeight());
33 | //        mBitmapTexture = new BitmapTexture(bitmap);
34 | //        mBitmapTexture.setOpaque(false);
35 |     }
36 | 
37 |     @Override
38 |     public void release() {
39 |         if (mBitmapTexture != null) {
40 |             mBitmapTexture.recycle();
41 |         }
42 |     }
43 | 
44 |     @Override
45 |     public void drawFrame(GLESCanvas canvas, float progress) {
46 |         if (mBitmapTexture != null) {
47 |             canvas.save();
48 |             canvas.translate(mViewprotRect.centerX(), mViewprotRect.centerY());
49 |             canvas.rotate(-0, 0, 0, -1f);
50 |             canvas.translate(-mViewprotRect.centerX(), -mViewprotRect.centerY());
51 |             canvas.drawTexture(mBitmapTexture, mSrcRect, mViewprotRect);
52 |             canvas.restore();
53 |         }
54 |     }
55 | 
56 |     @Override
57 |     public AvailableRect[] getChildLayerRects(float progress) {
58 |         AvailableRect[] availableRects = super.getChildLayerRects(progress);
59 |         for (int i = 0; availableRects != null && i < availableRects.length; i++) {
60 |             availableRects[i].rotation =  0;
61 |                     //720*2 * progress;
62 |             if (availableRects[i].rotationPivot == null) {
63 |                 availableRects[i].rotationPivot = new PointF();
64 |             }
65 |             availableRects[i].rotationPivot.set(mViewprotRect.centerX(), mViewprotRect.centerY());
66 |         }
67 |         return availableRects;
68 |     }
69 | 
70 |     @Override
71 |     public int getRequiredPhotoNum() {
72 |         return 0;
73 |     }
74 | }
75 | 


--------------------------------------------------------------------------------
/library/src/main/java/com/hw/photomovie/segment/layer/TestMuiltBitmapLayer.java:
--------------------------------------------------------------------------------
 1 | package com.hw.photomovie.segment.layer;
 2 | 
 3 | import android.graphics.Rect;
 4 | import com.hw.photomovie.opengl.GLESCanvas;
 5 | import com.hw.photomovie.segment.BitmapInfo;
 6 | import com.hw.photomovie.util.PhotoUtil;
 7 | import com.hw.photomovie.util.ScaleType;
 8 | 
 9 | import java.util.List;
10 | 
11 | /**
12 |  * Created by huangwei on 2015/6/3.
13 |  */
14 | public class TestMuiltBitmapLayer extends MovieLayer {
15 | 
16 |     private Rect mTempRect = new Rect();
17 | 
18 |     @Override
19 |     public void drawFrame(GLESCanvas canvas, float progress) {
20 |         AvailableRect[] dstAvailableRect = mParentLayer == null ? null : mParentLayer.getChildLayerRects(progress);
21 | 
22 |         if (mBitmapInfos == null || dstAvailableRect == null || dstAvailableRect.length == 0) {
23 |             return;
24 |         }
25 | 
26 |         for (int i = 0; i < dstAvailableRect.length; i++) {
27 |             AvailableRect availableRect = dstAvailableRect[i];
28 |             BitmapInfo bitmapInfo = i < mBitmapInfos.size() ? mBitmapInfos.get(i) : null;
29 |             if (bitmapInfo == null || bitmapInfo.bitmapTexture == null || availableRect == null || availableRect.rectF == null) {
30 |                 continue;
31 |             }
32 |             //更新bitmap显示区域
33 |             if (bitmapInfo.scaleType == ScaleType.CENTER_CROP) {
34 |                 PhotoUtil.getCroppedRect(
35 |                         mTempRect,
36 |                         bitmapInfo.srcRect.width(),
37 |                         bitmapInfo.srcRect.height(),
38 |                         dstAvailableRect[i].rectF.width(),
39 |                         dstAvailableRect[i].rectF.height());
40 |                 bitmapInfo.srcShowRect.set(mTempRect);
41 |             }
42 | 
43 |             canvas.save();
44 |             float cx, cy;
45 |             if (availableRect.rotationPivot == null) {
46 |                 cx = availableRect.rectF.centerX();
47 |                 cy = availableRect.rectF.centerY();
48 |             } else {
49 |                 cx = availableRect.rotationPivot.x;
50 |                 cy = availableRect.rotationPivot.y;
51 |             }
52 |             canvas.translate(cx, cy);
53 |             canvas.rotate(-availableRect.rotation, 0f, 0f, -1f);
54 |             canvas.translate(-cx, -cy);
55 |             canvas.drawTexture(bitmapInfo.bitmapTexture, bitmapInfo.srcShowRect, availableRect.rectF);
56 |             canvas.restore();
57 |         }
58 |     }
59 | 
60 |     @Override
61 |     public void allocPhotos(List bitmapInfos) {
62 |         super.allocPhotos(bitmapInfos);
63 |     }
64 | 
65 |     @Override
66 |     public AvailableRect[] getChildLayerRects(float progress) {
67 |         return null;
68 |     }
69 | 
70 |     @Override
71 |     public int getRequiredPhotoNum() {
72 |         return 4;
73 |     }
74 | 
75 |     @Override
76 |     public void prepare() {
77 | 
78 |     }
79 | 
80 |     @Override
81 |     public void release() {
82 | 
83 |     }
84 | }
85 | 


--------------------------------------------------------------------------------
/library/src/main/java/com/hw/photomovie/segment/strategy/NotRetryStrategy.java:
--------------------------------------------------------------------------------
 1 | package com.hw.photomovie.segment.strategy;
 2 | 
 3 | import com.hw.photomovie.PhotoMovie;
 4 | import com.hw.photomovie.model.PhotoData;
 5 | import com.hw.photomovie.segment.MovieSegment;
 6 | 
 7 | import java.util.List;
 8 | 
 9 | /**
10 |  * Created by Administrator on 2015/6/12.
11 |  */
12 | public class NotRetryStrategy implements RetryStrategy {
13 |     @Override
14 |     public List getAvailableData(PhotoMovie photoMovie, MovieSegment movieSegment) {
15 |         return movieSegment==null?null:movieSegment.getAllocatedPhotos();
16 |     }
17 | }
18 | 


--------------------------------------------------------------------------------
/library/src/main/java/com/hw/photomovie/segment/strategy/ReallocStrategy.java:
--------------------------------------------------------------------------------
 1 | package com.hw.photomovie.segment.strategy;
 2 | 
 3 | import com.hw.photomovie.PhotoMovie;
 4 | import com.hw.photomovie.model.PhotoData;
 5 | import com.hw.photomovie.segment.MovieSegment;
 6 | 
 7 | import java.util.ArrayList;
 8 | import java.util.LinkedList;
 9 | import java.util.List;
10 | 
11 | /**
12 |  * Created by Administrator on 2015/6/12.
13 |  */
14 | public class ReallocStrategy implements RetryStrategy {
15 |     @Override
16 |     public List getAvailableData(PhotoMovie photoMovie, MovieSegment movieSegment) {
17 |         if (movieSegment == null) {
18 |             return null;
19 |         }
20 |         if (photoMovie == null || photoMovie.getPhotoSource() == null) {
21 |             return movieSegment.getAllocatedPhotos();
22 |         }
23 | 
24 |         int required = movieSegment.getRequiredPhotoNum();
25 |         List segmentDatas = new LinkedList(movieSegment.getAllocatedPhotos());
26 |         for (int i = segmentDatas.size() - 1; i >= 0; i--) {
27 |             PhotoData photoData = segmentDatas.get(i);
28 |             //未加载好
29 |             if (photoData.getState() < PhotoData.STATE_LOCAL) {
30 |                 segmentDatas.remove(i);
31 |             }
32 |         }
33 |         //还需要多少
34 |         int need = required - segmentDatas.size();
35 |         List source = photoMovie.getPhotoSource().getSourceData();
36 |         List availableList = new ArrayList();
37 |         for (PhotoData photoData : source) {
38 |             //跳过没准备好或者已有的
39 |             if (photoData.getState() < PhotoData.STATE_LOCAL || segmentDatas.contains(photoData)) {
40 |                 continue;
41 |             }
42 |             if (need <= 0) {
43 |                 return segmentDatas;
44 |             }
45 |             availableList.add(photoData);
46 |         }
47 |         //从可用的里面随机选
48 |         while(need > 0 && availableList.size()>0){
49 |             int ran = (int) (Math.random() * availableList.size());
50 |             segmentDatas.add(availableList.get(ran));
51 |             need--;
52 |         }
53 | 
54 |         //如果还不够,就从自己身上重复
55 |         int size = segmentDatas.size();
56 |         for(int i=0;i getAvailableData(PhotoMovie photoMovie, MovieSegment movieSegment);
14 | }
15 | 


--------------------------------------------------------------------------------
/library/src/main/java/com/hw/photomovie/timer/IMovieTimer.java:
--------------------------------------------------------------------------------
 1 | package com.hw.photomovie.timer;
 2 | 
 3 | /**
 4 |  * Created by huangwei on 2015/5/25.
 5 |  */
 6 | public interface IMovieTimer {
 7 | 
 8 |     public void start();
 9 | 
10 |     public void pause();
11 | 
12 |     public void setMovieListener(MovieListener movieListener);
13 | 
14 |     public int getCurrentPlayTime();
15 | 
16 |     void setLoop(boolean loop);
17 | 
18 |     public interface MovieListener {
19 |         void onMovieUpdate(int elapsedTime);
20 | 
21 |         void onMovieStarted();
22 | 
23 |         void onMoviedPaused();
24 | 
25 |         void onMovieResumed();
26 | 
27 |         void onMovieEnd();
28 |     }
29 | }
30 | 


--------------------------------------------------------------------------------
/library/src/main/java/com/hw/photomovie/timer/MovieTimer.java:
--------------------------------------------------------------------------------
  1 | package com.hw.photomovie.timer;
  2 | 
  3 | import android.animation.Animator;
  4 | import android.animation.ValueAnimator;
  5 | import android.view.animation.LinearInterpolator;
  6 | import com.hw.photomovie.PhotoMovie;
  7 | 
  8 | /**
  9 |  * Created by yellowcat on 2015/6/12.
 10 |  */
 11 | public class MovieTimer implements IMovieTimer, ValueAnimator.AnimatorUpdateListener, Animator.AnimatorListener {
 12 | 
 13 |     private final ValueAnimator mAnimator;
 14 | 
 15 |     private MovieListener mMovieListener;
 16 | 
 17 |     private long mPausedPlayTime;
 18 |     private boolean mPaused;
 19 | 
 20 |     private PhotoMovie mPhotoMovie;
 21 |     private boolean mLoop;
 22 | 
 23 |     public MovieTimer(PhotoMovie photoMovie) {
 24 |         mPhotoMovie = photoMovie;
 25 | 
 26 |         mAnimator = ValueAnimator.ofInt(0, 1);
 27 |         mAnimator.setInterpolator(new LinearInterpolator());
 28 |         mAnimator.addUpdateListener(this);
 29 |         mAnimator.addListener(this);
 30 |         mAnimator.setDuration(Long.MAX_VALUE);
 31 |     }
 32 | 
 33 |     public void start() {
 34 |         if (!mPaused) {
 35 |             mAnimator.start();
 36 |         } else {
 37 |             mAnimator.start();
 38 |         }
 39 |     }
 40 | 
 41 |     public void pause() {
 42 |         if (mPaused) {
 43 |             return;
 44 |         }
 45 |         mPaused = true;
 46 |         mPausedPlayTime = mAnimator.getCurrentPlayTime();
 47 |         mAnimator.cancel();
 48 |     }
 49 | 
 50 |     @Override
 51 |     public void setMovieListener(IMovieTimer.MovieListener movieListener) {
 52 |         this.mMovieListener = movieListener;
 53 |     }
 54 | 
 55 |     @Override
 56 |     public int getCurrentPlayTime() {
 57 |         return (int) mPausedPlayTime;
 58 |     }
 59 | 
 60 |     @Override
 61 |     public void setLoop(boolean loop) {
 62 |         mLoop = loop;
 63 |     }
 64 | 
 65 |     @Override
 66 |     public void onAnimationUpdate(ValueAnimator animation) {
 67 |         if (mPaused || !animation.isRunning()) {
 68 |             return;
 69 |         }
 70 | 
 71 |         long curTime = animation.getCurrentPlayTime();
 72 | 
 73 |         if (curTime >= mPhotoMovie.getDuration()) {
 74 |             mAnimator.removeUpdateListener(this);
 75 |             mAnimator.removeListener(this);
 76 |             mAnimator.end();
 77 |             if (mMovieListener != null) {
 78 |                 mMovieListener.onMovieEnd();
 79 |             }
 80 |             mAnimator.addUpdateListener(this);
 81 |             mAnimator.addListener(this);
 82 |             if(mLoop){
 83 |                 mAnimator.start();
 84 |             }
 85 |         }else{
 86 |             if (mMovieListener != null) {
 87 |                 mMovieListener.onMovieUpdate((int) curTime);
 88 |             }
 89 |         }
 90 |     }
 91 | 
 92 |     @Override
 93 |     public void onAnimationStart(Animator animation) {
 94 |         if (mMovieListener != null) {
 95 |             if (mPaused) {
 96 |                 mMovieListener.onMovieResumed();
 97 |             } else {
 98 |                 mMovieListener.onMovieStarted();
 99 |             }
100 |         }
101 |         if (mPaused) {
102 |             mAnimator.setCurrentPlayTime(mPausedPlayTime);
103 |         }
104 |         mPaused = false;
105 |         mPausedPlayTime = 0;
106 |     }
107 | 
108 |     @Override
109 |     public void onAnimationEnd(Animator animation) {
110 |         if (mMovieListener != null) {
111 |             if (mPaused) {
112 |                 mMovieListener.onMoviedPaused();
113 |             } else {
114 |                 mMovieListener.onMovieEnd();
115 |             }
116 |         }
117 |     }
118 | 
119 |     @Override
120 |     public void onAnimationCancel(Animator animation) {
121 |         mPausedPlayTime = mAnimator.getCurrentPlayTime();
122 |     }
123 | 
124 |     @Override
125 |     public void onAnimationRepeat(Animator animation) {
126 | 
127 |     }
128 | }
129 | 


--------------------------------------------------------------------------------
/library/src/main/java/com/hw/photomovie/util/AppResources.java:
--------------------------------------------------------------------------------
 1 | package com.hw.photomovie.util;
 2 | 
 3 | import android.content.res.AssetManager;
 4 | import android.content.res.Resources;
 5 | import android.graphics.Bitmap;
 6 | import android.graphics.BitmapFactory;
 7 | 
 8 | import java.io.BufferedReader;
 9 | import java.io.IOException;
10 | import java.io.InputStream;
11 | import java.io.InputStreamReader;
12 | 
13 | /**
14 |  * Created by huangwei on 2015/6/4.
15 |  */
16 | public class AppResources {
17 | 
18 |     private Resources mResources;
19 | 
20 |     private AppResources() {
21 | 
22 |     }
23 | 
24 |     public void init(Resources resources) {
25 |         mResources = resources;
26 |     }
27 | 
28 |     public Resources getAppRes() {
29 |         if (mResources == null) {
30 |             throw new RuntimeException("ApplicationResource never inited.");
31 |         }
32 |         return mResources;
33 |     }
34 | 
35 |     public float getAppDensity() {
36 |         if (mResources == null) {
37 |             throw new RuntimeException("ApplicationResource never inited.");
38 |         }
39 |         return mResources.getDisplayMetrics().density;
40 |     }
41 | 
42 |     public static AppResources getInstance() {
43 |         return Holder.INSTANCE;
44 |     }
45 | 
46 |     private static final class Holder {
47 |         private static AppResources INSTANCE = new AppResources();
48 |     }
49 | 
50 |     public static String loadShaderFromAssets(String assetsName){
51 |         AssetManager am = AppResources.getInstance().getAppRes().getAssets();
52 |         StringBuffer stringBuffer = new StringBuffer();
53 |         InputStream inputStream = null;
54 |         try {
55 |             inputStream = am.open(assetsName);
56 |             BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
57 |             String str = null;
58 |             while ((str = br.readLine()) != null) {
59 |                 stringBuffer.append(str);
60 |             }
61 |         }catch (IOException e){
62 |             e.printStackTrace();
63 |         }finally {
64 |             if(inputStream!=null) {
65 |                 try {
66 |                     inputStream.close();
67 |                 } catch (IOException e) {
68 |                     e.printStackTrace();
69 |                 }
70 |             }
71 |         }
72 |         return stringBuffer.toString();
73 |     }
74 | 
75 |     public static Bitmap loadBitmapFromAssets(String assetsName){
76 |         AssetManager am = AppResources.getInstance().getAppRes().getAssets();
77 |         InputStream inputStream = null;
78 |         try {
79 |             inputStream = am.open(assetsName);
80 |             return BitmapFactory.decodeStream(inputStream);
81 |         }catch (IOException e){
82 |             e.printStackTrace();
83 |         }finally {
84 |             if(inputStream!=null) {
85 |                 try {
86 |                     inputStream.close();
87 |                 } catch (IOException e) {
88 |                     e.printStackTrace();
89 |                 }
90 |             }
91 |         }
92 |         return null;
93 |     }
94 | }
95 | 


--------------------------------------------------------------------------------
/library/src/main/java/com/hw/photomovie/util/BitmapUtil.java:
--------------------------------------------------------------------------------
 1 | package com.hw.photomovie.util;
 2 | 
 3 | import android.graphics.Bitmap;
 4 | import android.graphics.Canvas;
 5 | import android.graphics.Paint;
 6 | import android.text.TextPaint;
 7 | 
 8 | /**
 9 |  * Created by huangwei on 2018/10/27.
10 |  */
11 | public class BitmapUtil {
12 |     public static Bitmap generateBitmap(String text,int textSizePx,int textColor){
13 |         TextPaint textPaint = new TextPaint();
14 |         textPaint.setTextSize(textSizePx);
15 |         textPaint.setColor(textColor);
16 |         int width = (int) Math.ceil(textPaint.measureText(text));
17 |         Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
18 |         int height = (int) Math.ceil(Math.abs(fontMetrics.bottom) + Math.abs(fontMetrics.top));
19 |         Bitmap bitmap = Bitmap.createBitmap(width,height, Bitmap.Config.ARGB_8888);
20 |         Canvas canvas = new Canvas(bitmap);
21 |         canvas.drawText(text,0,Math.abs(fontMetrics.ascent),textPaint);
22 |         return bitmap;
23 |     }
24 | }
25 | 


--------------------------------------------------------------------------------
/library/src/main/java/com/hw/photomovie/util/IntArray.java:
--------------------------------------------------------------------------------
 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 | 
17 | package com.hw.photomovie.util;
18 | 
19 | public class IntArray {
20 |     private static final int INIT_CAPACITY = 8;
21 | 
22 |     private int mData[] = new int[INIT_CAPACITY];
23 |     private int mSize = 0;
24 | 
25 |     public void add(int value) {
26 |         if (mData.length == mSize) {
27 |             int temp[] = new int[mSize + mSize];
28 |             System.arraycopy(mData, 0, temp, 0, mSize);
29 |             mData = temp;
30 |         }
31 |         mData[mSize++] = value;
32 |     }
33 | 
34 |     public int removeLast() {
35 |         mSize--;
36 |         return mData[mSize];
37 |     }
38 | 
39 |     public int size() {
40 |         return mSize;
41 |     }
42 | 
43 |     // For testing only
44 |     public int[] toArray(int[] result) {
45 |         if (result == null || result.length < mSize) {
46 |             result = new int[mSize];
47 |         }
48 |         System.arraycopy(mData, 0, result, 0, mSize);
49 |         return result;
50 |     }
51 | 
52 |     public int[] getInternalArray() {
53 |         return mData;
54 |     }
55 | 
56 |     public void clear() {
57 |         mSize = 0;
58 |         if (mData.length != INIT_CAPACITY) {
59 |             mData = new int[INIT_CAPACITY];
60 |         }
61 |     }
62 | }
63 | 


--------------------------------------------------------------------------------
/library/src/main/java/com/hw/photomovie/util/MLog.java:
--------------------------------------------------------------------------------
 1 | package com.hw.photomovie.util;
 2 | 
 3 | import android.util.Log;
 4 | 
 5 | /**
 6 |  * Created by huangwei on 2015/5/25.
 7 |  */
 8 | public class MLog {
 9 | 
10 |     public static final boolean DEBUG = true;
11 | 
12 |     public static void i(String tag, String msg){
13 |         if(DEBUG){
14 |             Log.i(tag,msg);
15 |         }
16 |     }
17 | 
18 |     public static void v(String tag, String msg){
19 |         if(DEBUG){
20 |             Log.v(tag, msg);
21 |         }
22 |     }
23 | 
24 |     public static void d(String tag, String msg){
25 |         if(DEBUG){
26 |             Log.d(tag, msg);
27 |         }
28 |     }
29 | 
30 |     public static void w(String tag, String msg,Throwable t){
31 |         if(DEBUG){
32 |             Log.w(tag, msg,t);
33 |         }
34 |     }
35 | 
36 |     public static void w(String tag, String msg){
37 |         if(DEBUG){
38 |             Log.w(tag, msg);
39 |         }
40 |     }
41 | 
42 |     public static void e(String tag, String msg){
43 |         if(DEBUG){
44 |             Log.e(tag, msg);
45 |         }
46 |     }
47 | 
48 |     public static void e(String tag, String msg,Throwable t){
49 |         if(DEBUG){
50 |             Log.e(tag,msg,t);
51 |         }
52 |     }
53 | 
54 | }
55 | 


--------------------------------------------------------------------------------
/library/src/main/java/com/hw/photomovie/util/PhotoUtil.java:
--------------------------------------------------------------------------------
  1 | package com.hw.photomovie.util;
  2 | 
  3 | import android.graphics.Bitmap;
  4 | import android.graphics.Rect;
  5 | import android.graphics.RectF;
  6 | 
  7 | /**
  8 |  * Created by huangwei on 14-12-31.
  9 |  */
 10 | public class PhotoUtil {
 11 |     /**
 12 |      * 根据toWidth和toHieght,返回适用于bitmap的srcRect,只裁剪不压缩
 13 |      * 裁剪方式为裁上下或两边
 14 |      *
 15 |      * @param srcRect
 16 |      * @param bitmapWidth
 17 |      * @param bitmapHeight
 18 |      * @param toWidth
 19 |      * @param toHeight
 20 |      * @return
 21 |      */
 22 |     public static Rect getCroppedRect(Rect srcRect, int bitmapWidth, int bitmapHeight, float toWidth, float toHeight) {
 23 |         if (srcRect == null) {
 24 |             srcRect = new Rect();
 25 |         }
 26 |         float rate = toWidth / toHeight;
 27 |         float bitmapRate = bitmapWidth / (float) bitmapHeight;
 28 | 
 29 |         if (Math.abs(rate - bitmapRate) < 0.01) {
 30 | 
 31 |             srcRect.left = 0;
 32 |             srcRect.top = 0;
 33 |             srcRect.right = bitmapWidth;
 34 |             srcRect.bottom = bitmapHeight;
 35 |         } else if (bitmapRate > rate) {
 36 |             //裁两边
 37 |             float cutRate = toHeight / (float) bitmapHeight;
 38 |             float toCutWidth = cutRate * bitmapWidth - toWidth;
 39 |             float toCutWidthReal = toCutWidth / cutRate;
 40 | 
 41 |             srcRect.left = (int) (toCutWidthReal / 2);
 42 |             srcRect.top = 0;
 43 |             srcRect.right = bitmapWidth - (int) (toCutWidthReal / 2);
 44 |             srcRect.bottom = bitmapHeight;
 45 |         } else {
 46 |             //裁上下
 47 |             float cutRate = toWidth / (float) bitmapWidth;
 48 |             float toCutHeight = cutRate * bitmapHeight - toHeight;
 49 |             float toCutHeightReal = toCutHeight / cutRate;
 50 | 
 51 |             srcRect.left = 0;
 52 |             srcRect.top = (int) (toCutHeightReal / 2);
 53 |             srcRect.right = bitmapWidth;
 54 |             srcRect.bottom = bitmapHeight - (int) (toCutHeightReal / 2);
 55 | 
 56 |         }
 57 |         return srcRect;
 58 |     }
 59 | 
 60 |     /**
 61 |      * 计算图片根据高宽居中情况下的目标显示区域
 62 |      *
 63 |      * @return
 64 |      */
 65 |     public static RectF getFitCenterRect(RectF dstRect, int bitmapWidth, int bitmapHeight, int outWidth, int outHeight) {
 66 |         if (dstRect == null) {
 67 |             dstRect = new RectF();
 68 |         }
 69 |         float rate = outWidth / outHeight;
 70 |         float bitmapRate = bitmapWidth / (float) bitmapHeight;
 71 | 
 72 |         if (Math.abs(rate - bitmapRate) < 0.01) {
 73 |             dstRect.left = 0;
 74 |             dstRect.top = 0;
 75 |             dstRect.right = outWidth;
 76 |             dstRect.bottom = outHeight;
 77 |         } else if (bitmapRate > rate) {
 78 |             //宽满,上下留白
 79 |             int showWidth = outWidth;
 80 |             int showHeight = (int) (showWidth / bitmapRate);
 81 | 
 82 |             dstRect.left = 0;
 83 |             dstRect.right = outWidth;
 84 |             dstRect.top = outHeight / 2 - showHeight / 2;
 85 |             dstRect.bottom = outHeight / 2 + showHeight / 2;
 86 |         } else {
 87 |             //高满,左右留白
 88 |             int showHeight = outHeight;
 89 |             int showWidth = (int) (showHeight * bitmapRate);
 90 | 
 91 |             dstRect.left = outWidth / 2 - showWidth / 2;
 92 |             dstRect.right = outWidth / 2 + showWidth / 2;
 93 |             dstRect.top = 0;
 94 |             dstRect.bottom = outHeight;
 95 |         }
 96 |         return dstRect;
 97 |     }
 98 | 
 99 | 
100 |     public static Bitmap createBitmapOrNull(int width, int height, Bitmap.Config config) {
101 |         try {
102 |             return Bitmap.createBitmap(width, height, config);
103 |         } catch (OutOfMemoryError e) {
104 |             return null;
105 |         }
106 |     }
107 | }
108 | 


--------------------------------------------------------------------------------
/library/src/main/java/com/hw/photomovie/util/ScaleType.java:
--------------------------------------------------------------------------------
 1 | package com.hw.photomovie.util;
 2 | 
 3 | /**
 4 |  * Created by huangwei on 2015/6/4.
 5 |  */
 6 | public enum  ScaleType {
 7 |     /**
 8 |      * 左右上下裁剪填满输出窗口
 9 |      */
10 |     CENTER_CROP,
11 |     /**
12 |      * 不管比例拉伸填满输出窗口
13 |      */
14 |     FIT_XY,
15 |     /**
16 |      * 居中,同时填满输出窗口的宽或者高
17 |      */
18 |     FIT_CENTER
19 | }
20 | 


--------------------------------------------------------------------------------
/library/src/main/java/com/hw/photomovie/util/SystemPropertiesUtil.java:
--------------------------------------------------------------------------------
 1 | package com.hw.photomovie.util;
 2 | 
 3 | import java.lang.reflect.InvocationTargetException;
 4 | import java.lang.reflect.Method;
 5 | 
 6 | /**
 7 |  * Created by huangwei on 2018/9/6 0006.
 8 |  */
 9 | public class SystemPropertiesUtil {
10 | 
11 |     public static int getInt(String key, int defaultValue) {
12 |         try {
13 |             return Integer.parseInt(get(key));
14 |         } catch (Exception e) {
15 |             e.printStackTrace();
16 |             return defaultValue;
17 |         }
18 |     }
19 | 
20 |     public static int getInt(String key) {
21 |         return Integer.parseInt(get(key));
22 |     }
23 | 
24 |     public static String get(String key) {
25 |         String result = "";
26 |         try {
27 |             Class c = Class.forName("android.os.SystemProperties");
28 | 
29 |             Method get = c.getMethod("get", String.class);
30 |             result = (String) get.invoke(c, key);
31 | 
32 |         } catch (ClassNotFoundException e) {
33 |             // TODO Auto-generated catch block
34 |             e.printStackTrace();
35 |         } catch (NoSuchMethodException e) {
36 |             // TODO Auto-generated catch block
37 |             e.printStackTrace();
38 |         } catch (IllegalAccessException e) {
39 |             // TODO Auto-generated catch block
40 |             e.printStackTrace();
41 |         } catch (IllegalArgumentException e) {
42 |             // TODO Auto-generated catch block
43 |             e.printStackTrace();
44 |         } catch (InvocationTargetException e) {
45 |             // TODO Auto-generated catch block
46 |             e.printStackTrace();
47 |         }
48 |         return result;
49 |     }
50 | 
51 |     /**
52 |      * Set the value for the given key.
53 |      *
54 |      * @throws IllegalArgumentException if the key exceeds 32 characters
55 |      * @throws IllegalArgumentException if the value exceeds 92 characters
56 |      */
57 |     public static void set(String key, String val) {
58 |         try {
59 |             Class c = Class.forName("android.os.SystemProperties");
60 |             Method set = c.getMethod("set", String.class, String.class);
61 |             set.invoke(c, key, val);
62 |         } catch (ClassNotFoundException e) {
63 |             // TODO Auto-generated catch block
64 |             e.printStackTrace();
65 |         } catch (NoSuchMethodException e) {
66 |             // TODO Auto-generated catch block
67 |             e.printStackTrace();
68 |         } catch (IllegalAccessException e) {
69 |             // TODO Auto-generated catch block
70 |             e.printStackTrace();
71 |         } catch (IllegalArgumentException e) {
72 |             // TODO Auto-generated catch block
73 |             e.printStackTrace();
74 |         } catch (InvocationTargetException e) {
75 |             // TODO Auto-generated catch block
76 |             e.printStackTrace();
77 |         }
78 | 
79 |     }
80 | 
81 | }


--------------------------------------------------------------------------------
/library/src/main/java/com/hw/photomovie/util/stackblur/BlurProcess.java:
--------------------------------------------------------------------------------
 1 | package com.hw.photomovie.util.stackblur;
 2 | 
 3 | import android.graphics.Bitmap;
 4 | 
 5 | interface BlurProcess {
 6 | 	/**
 7 | 	 * Process the given image, blurring by the supplied radius.
 8 | 	 * If radius is 0, this will return original
 9 | 	 * @param original the bitmap to be blurred
10 | 	 * @param radius the radius in pixels to blur the image
11 | 	 * @return the blurred version of the image.
12 | 	 */
13 |     public Bitmap blur(Bitmap original, float radius);
14 | }
15 | 


--------------------------------------------------------------------------------
/library/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 | 
2 |     
5 |     64dp
6 | 
7 | 


--------------------------------------------------------------------------------
/library/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 | 
2 |     
3 |     16dp
4 |     16dp
5 | 
6 | 


--------------------------------------------------------------------------------
/library/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 | 
2 |     library
3 | 
4 |     Hello world!
5 |     Settings
6 | 
7 | 


--------------------------------------------------------------------------------
/library/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 | 
2 | 
3 | 


--------------------------------------------------------------------------------
/readme/PhotoMovie.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yellowcath/PhotoMovie/ed952bb6c9cbb556ae138d5c32bcc09b61bf8be6/readme/PhotoMovie.png


--------------------------------------------------------------------------------
/readme/filter.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yellowcath/PhotoMovie/ed952bb6c9cbb556ae138d5c32bcc09b61bf8be6/readme/filter.gif


--------------------------------------------------------------------------------
/readme/gradient.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yellowcath/PhotoMovie/ed952bb6c9cbb556ae138d5c32bcc09b61bf8be6/readme/gradient.gif


--------------------------------------------------------------------------------
/readme/gradient_timeline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yellowcath/PhotoMovie/ed952bb6c9cbb556ae138d5c32bcc09b61bf8be6/readme/gradient_timeline.png


--------------------------------------------------------------------------------
/readme/transfer.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yellowcath/PhotoMovie/ed952bb6c9cbb556ae138d5c32bcc09b61bf8be6/readme/transfer.gif


--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':library', ':dynamicdemo'
2 | 


--------------------------------------------------------------------------------