Git Product home page Git Product logo

advancedluban's Introduction

AdvancedLuban

build license

中文版

sketch

AdvancedLuban —— Is a convenient simple Android image compression tool library.Provides multiple compression strategies.Different calling methods,Custom compression,Multi-Image synchronous compression and so on,Focus on a better picture compression experience

Image Count Origin Total size Compressed Total size Time Cost
1 4.3Mb 85Kb 0.23s
4 14.22Mb 364Kb 1.38s
9 36.23Mb 745Kb 4.43s

Import

Maven

<dependency>
  <groupId>me.shaohui.advancedluban</groupId>
  <artifactId>library</artifactId>
  <version>1.3.5</version>
  <type>pom</type>
</dependency>

or Gradle

compile 'me.shaohui.advancedluban:library:1.3.5'

Usage

Listener mode

Advanced Luban internal Computation thread for image compression, external calls simply set the Listener can be:

Luban.compress(context, file)
    .putGear(Luban.THIRD_GEAR)      // set the compress mode, default is : THIRD_GEAR
    .launch(listener);              // start compression and set the listener

RxJava mode

RxJava call the same default Computation thread to compress, you can also define any thread, can be observed in any thread:

Luban.compress(context, file)                          
        .putGear(Luban.CUSTOM_GEAR)                 
        .asObservable()                             // generate Observable
        .subscribe(successAction, errorAction)      // subscribe the compress result

Compression mode

1. CUSTOM_GEAR

compress image file according to the restrictions you set, you can limit: the width, height or file size of the image file

    Luban.compress(context, file)
            .setMaxSize(500)                // limit the final image size(unit:Kb)
            .setMaxHeight(1920)             // limit image height
            .setMaxWidth(1080)              // limit image width
            .putGear(Luban.CUSTOM_GEAR)     // use CUSTOM GEAR compression mode
            .asObservable()

2. THIRD_GEAR

Using custom algorithms, according to the picture aspect ratio, the picture is compressed quickly, the resulting image size is about 100Kb, for general compression, no file size limit and picture width limit

3. FIRST_GEAR

The simplified version of THIRD GEAR, the compressed image resolution is less than 1280 x 720, the final file is less than 60Kb. suitable for fast compression, regardless of the final picture quality

Multi-Image synchronous compression

If you choose to call the way Listener:

    Luban.get(this)
            .putGear(Luban.CUSTOM_GEAR)             
            .load(fileList)                     // load all images
            .launch(multiCompressListener);     // passing an OnMultiCompress Listener

or the RxJava way to use:

    Luban.get(this)
            .putGear(Luban.CUSTOM_GEAR)             
            .load(fileList)                     // load all images
            .asListObservable()                 // Generates Observable <List<File>. Returns the result of all the images compressed successfully

About OOM

If you use a multi-map compression, we must take into account the risk of OOM, recommend you use CUSTOM_GEAR, and then customize the compression index, to a large extent reduce the risk of OOM, the current test did not find the problem of OOM

ChangeLog

1.3.5

  • Add custom compression cache directory

1.3.4

  • update RxJava to RxJava2

1.3.3

  • Set the default observed in the main thread

1.3.2

  • Optimize memory usage

1.3.1

  • Added custom compression format
  • COMO_GEAR used to solve the problem of OOM
  • Refactored most of the code
  • To support WebP, the minimum supported version is increased to 14

Issue

You can according to your needs to choose a different compression mode and call mode ! b( ̄▽ ̄)d !Finally, I welcome the Issue

Thanks For

License

Copyright 2016 shaohui10086

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

advancedluban's People

Contributors

itretyak avatar shaohui10086 avatar ysy950803 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

advancedluban's Issues

多文件压缩,会返回相同的文件路径

压缩的路径是根据时间戳来命名的?多文件压缩,会返回相同的文件路径。。。下面是4张不同的图片多图压缩后返回的路径:
压缩后 file path:/data/user/0/com.xxxx.bbb/cache/luban_disk_cache/1477981667061.jpg
压缩后 file path:/data/user/0/com.xxxx.bbb/cache/luban_disk_cache/1477981667061.jpg
压缩后 file path:/data/user/0/com.xxxx.bbb/cache/luban_disk_cache/1477981667062.jpg
压缩后 file path:/data/user/0/com.xxxx.bbb/cache/luban_disk_cache/1477981667063.jpg

关于多图压缩

使用listener方式 实现多图压缩 使用customgear 压缩后查看模拟器,一共压缩5张图片,但是实际结果是生成了13个压缩后的图片,虽然,最终Onsuccess里边回调的list<File>数组 最终也是5张图
但是模拟器中 一张图确实压缩了多次,生成了多张相同的图虽然名字不一样。求解释,难道是线程同步没做好?

优雅的外表

苦苦寻找真正的效率内存都兼顾的大图压缩算法,看到接口后眼前一亮,然后继续读代码实现。
恕我直言 看过代码后 ,compress 接口以及 saveImage 接口实现应该还有更优雅的实现。

Luban.CUSTOM_GEAR

Luban.CUSTOM_GEAR 这样的压缩感觉有点问题,压缩的图片下载下来,比原图还要大很多,加上限制条件感觉没太大的用还是很大

同时引入rxjava1和rxjava2报错

Error:FAILURE: Build failed with an exception.

  • What went wrong:
    Execution failed for task ':app:transformResourcesWithMergeJavaResForDevDebug'.

com.android.build.api.transform.TransformException: com.android.builder.packaging.DuplicateFileException: Duplicate files copied in APK META-INF/rxjava.properties
File1: /Users//.gradle/caches/modules-2/files-2.1/io.reactivex.rxjava2/rxjava/2.0.5/4f1ac7ec0215e8f87ac80269baadc82878b87ed8/rxjava-2.0.5.jar
File2: /Users/
/.gradle/caches/modules-2/files-2.1/io.reactivex/rxjava/1.2.1/4e4cfa4adc74521d5966799fa5ab70b733552f68/rxjava-1.2.1.jar

  • Try:
    Run with --stacktrace option to get the stack trace. Run with --debug option to get more log output.

two questions

1 rxjava bug, change thread error.
Observable singleAction(final File file) {
return Observable.fromCallable(new Callable() {
@OverRide
public File call() throws Exception {
return compressImage(mLuban.gear, file);
}
}).subscribeOn(Schedulers.computation()).observeOn(AndroidSchedulers.mainThread());
}
2 customCompress about pic's 16:9 error
thanks~ @shaohui10086

关于处理多图压缩的优化建议

  • 作者有没有把算法用Jni实现一遍的想法? 如果多线程压图的话,或者图片内容过大, 势必会导致OOM, 如果按照队列来处理, 又会导致压缩速度很慢, @@或者能不能把图片数据处理交给jni,利用公共内存空间来避免OOM呢?@shaohui10086
  • 具体可以参考 Fresco

多图压缩内存溢出

E/AndroidRuntime: FATAL EXCEPTION: RxComputationScheduler-3
Process: com.ikongjian.worker, PID: 12642
java.lang.IllegalStateException: Fatal Exception thrown on Scheduler.Worker thread.
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:59)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:423)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:154)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:269)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.OutOfMemoryError: Failed to allocate a 3244812 byte allocation with 2117648 free bytes and 2MB until OOM
at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
at android.graphics.BitmapFactory.decodeStreamInternal(BitmapFactory.java:639)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:615)
at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:391)
at me.shaohui.advancedluban.Luban.compress(Luban.java:585)
at me.shaohui.advancedluban.Luban.compress(Luban.java:629)
at me.shaohui.advancedluban.Luban.customCompress(Luban.java:502)
at me.shaohui.advancedluban.Luban.compressImage(Luban.java:357)
at me.shaohui.advancedluban.Luban.access$200(Luban.java:42)
at me.shaohui.advancedluban.Luban$9.call(Luban.java:218)
at me.shaohui.advancedluban.Luban$9.call(Luban.java:215)
at rx.internal.operators.OnSubscribeMap$MapSubscriber.onNext(OnSubscribeMap.java:69)
at rx.internal.util.ScalarSynchronousObservable$WeakSingleProducer.request(ScalarSynchronousObservable.java:276)
at rx.internal.operators.OperatorSubscribeOn$1$1$1.request(OperatorSubscribeOn.java:80)
at rx.Subscriber.setProducer(Subscriber.java:211)
at rx.internal.operators.OperatorSubscribeOn$1$1.setProducer(OperatorSubscribeOn.java:76)
at rx.internal.operators.OnSubscribeMap$MapSubscriber.setProducer(OnSubscribeMap.java:102)
at rx.internal.util.ScalarSynchronousObservable$JustOnSubscribe.call(ScalarSynchronousObservable.java:138)
at rx.internal.util.ScalarSynchronousObservable$JustOnSubscribe.call(ScalarSynchronousObservable.java:129)
at rx.Observable.unsafeSubscribe(Observable.java:10200)
at rx.internal.operators.OnSubscribeMap.call(OnSubscribeMap.java:48)
at rx.internal.operators.OnSubscribeMap.call(OnSubscribeMap.java:33)
at rx.Observable.unsafeSubscribe(Observable.java:10200)
at rx.internal.operators.OperatorSubscribeOn$1.call(OperatorSubscribeOn.java:94)
at rx.internal.schedulers.EventLoopsScheduler$EventLoopWorker$1.call(EventLoopsScheduler.java:172)
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:423) 
at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:154) 
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:269) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 
at java.lang.Thread.run(Thread.java:818) 

多图批量压缩

在进行多图压缩的时候,返回的List 虽然每个File的名字都不一样,所有的File打开来看之后,其实是同一张图片或者存在多张一样的图片(压缩之前的图片都是不同的)。

建议加入压缩图片格式控制

图片压缩希望添加保存图片格式自定义啊,因为同质量下webp格式的体积比jpeg小很多啊。而且现在android4.0以上都支持webp了。

    /**
     * Specifies the known formats a bitmap can be compressed into
     */
    public enum CompressFormat {
        JPEG    (0),
        PNG     (1),
        WEBP    (2);

        CompressFormat(int nativeInt) {
            this.nativeInt = nativeInt;
        }
        final int nativeInt;
    }
    bitmap.compress(Bitmap.CompressFormat.JPEG, options, stream);

混淆问题

混淆之后报错Caused by: java.lang.NoSuchFieldException: No field producerIndex in class Lc/e/e/b/n;
在混淆规则里添加-keep class me.shaohui.advancedluban.**{*;}仍然报错,请问怎么解决?谢谢!

能不能去掉RX

为了一个压缩工具类,引入RX,增加APK的大小.没必要.

小体积图片压缩

设置了压缩后最大体积为250KB(setMaxSize(250))一张180KB的图片压缩后变成230KB,建议在customCompress()方法大小判断:
long fileSize = mMaxSize > 0 ? mMaxSize : file.length() / 1024;
中再加一个判断:
long fileSize =( mMaxSize > 0 && mMaxSize < file.lengh())? mMaxSize : file.length() / 1024;

关于自定义缓存路径

private static boolean isCacheDirValid(File cacheDir) {
return cacheDir.isDirectory() && (cacheDir.exists() || cacheDir.mkdirs());
}

在实际使用时当目录未创建时 cacheDir.isDirectory() =false ,是否可以切换为
return cacheDir.isDirectory() && (cacheDir.exists() || cacheDir.mkdirs());

关于代码混淆

如果我的项目中启用了代码混淆,需要在混淆规则文件(如:proguard-rules.pro)中添加哪些代码?

压缩时候会生成多个图片

用此库做测试,压缩一张图片 在cache文件夹了生成了多张图片,大概是5张,没看源码不知道为何,所以每次使用时 我都调用了clearcache方法,避免生成过多图片

批量压缩时图片压缩顺序

  请问作者,如果我使用批量压缩,压缩出来的图片顺序是否会改变?    例如传入的List<File>顺序是a,b。压缩出来的List<File>是不是顺序一定是a压缩后的文件,b压缩后的文件?

有些图片一直报这个错java.io.IOException: Invalid marker: 52什么情况

Invalid image.
java.io.IOException: Invalid marker: 52
at android.media.ExifInterface.getJpegAttributes(ExifInterface.java:1627)
at android.media.ExifInterface.loadAttributes(ExifInterface.java:1353)
at android.media.ExifInterface.(ExifInterface.java:1070)
at me.shaohui.advancedluban.LubanCompresser.getImageSpinAngle(LubanCompresser.java:294)
at me.shaohui.advancedluban.LubanCompresser.thirdCompress(LubanCompresser.java:91)
at me.shaohui.advancedluban.LubanCompresser.compressImage(LubanCompresser.java:75)
at me.shaohui.advancedluban.LubanCompresser.access$100(LubanCompresser.java:28)
at me.shaohui.advancedluban.LubanCompresser$1.call(LubanCompresser.java:44)
at me.shaohui.advancedluban.LubanCompresser$1.call(LubanCompresser.java:41)
at io.reactivex.internal.operators.observable.ObservableFromCallable.subscribeActual(ObservableFromCallable.java:42)
at io.reactivex.Observable.subscribe(Observable.java:10700)
at io.reactivex.internal.operators.observable.ObservableSubscribeOn$1.run(ObservableSubscribeOn.java:39)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:423)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:154)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:269)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:833)

压缩条件疑问

  一张png图实际大小不高,转成BitMap占用内存也不高,但是尺寸有点大.如果压缩,就会严重失真,这种情况怎么处理.源码压缩条件没有考虑到.
  也就是说,有些图片Bitmap后实际占用内存不大,不需要压缩,一压缩就严重失真.

横向长图压缩完后变得超级小

您好,在压缩横向的超长图时,我的一个23776_3568分辨率的图片被压成1009_153,特别的模糊,几乎设么都看不见了,设置成THIRD_GEAR也没什么作用
想请教下怎么解决这个问题

压缩后的缓存目录

压缩过后的图片缓存目录是在/data/data/.... 如果直接使用这个路径上传图图片到服务器,就会FileNotFound, 这个可以设置压缩后图片存放路径吗

Image rotated

Hi,
First, thanks for a great lib.
Second, I am getting an issue: Images are getting rotated 90% after compression. Could you please assist?

压缩图片存储路径的问题

之前版本是有设置压缩存储路径的,怎么后面版本没有了,默认都是data/data/...假如把文件存到内部存储中再复制出来,然后再clean缓存我觉得可能太多余了,在图片比较多的情况下,会显得更耗时,建议使用更灵活的配置满足不同的需求。

压塑后的file 再转为bitmap 发现尺寸和size 又是原来的此存

之前是传base64字符串给服务器的,但因为总是bitmap压塑效果不明显(需求在300-400kB),又不能裁剪原图片的尺寸,后用了您的压塑框架,是从path --> file -->bitmap -->base64 传给服务器,在file的时候file.length 是符合项目需求的,但下载下来网络上传的图片 大小又和没压塑之前一样了,还有通过file.getAbsolutePath() 获取bitmap 时,bitmap == null
楼主能否给一些提示,谢谢

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.