GithubHelp home page GithubHelp logo

lyft / scissors Goto Github PK

View Code? Open in Web Editor NEW
1.8K 264.0 236.0 4.4 MB

✂ Android image cropping library

Home Page: https://eng.lyft.com/scissors-an-image-cropping-library-for-android-a56369154a19

License: Apache License 2.0

Shell 0.93% Java 99.07%
lyft

scissors's Introduction

⚠️ This repository has been archived and is no longer accepting contributions ⚠️

Scissors

Fixed viewport image cropping library for Android with built-in support for Picasso, Glide or Universal Image Loader.

Usage

See scissors-sample.

  • Include it on your layout:
<com.lyft.android.scissors.CropView
    android:id="@+id/crop_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:cropviewViewportRatio="1"
    />
  • Set a Bitmap to be cropped. In example by calling cropView.setImageBitmap(someBitmap);
  • Call Bitmap croppedBitmap = cropView.crop(); to obtain a cropped Bitmap to match viewport dimensions

Extensions

Scissors comes with handy extensions which help with common tasks like:

Loading a Bitmap

To load a Bitmap automatically with Picasso, Glide or Universal Image Loader into CropView use as follows:

cropView.extensions()
    .load(galleryUri);

Cropping into a File

To save a cropped Bitmap into a File use as follows:

cropView.extensions()
    .crop()
    .quality(87)
    .format(PNG)
    .into(croppedFile))

Questions

For questions please use github issues. Mark question issue with "question" label.

Download

compile 'com.lyft:scissors:1.1.1'

Snapshots of development version are available in Sonatype's snapshots repository.

License

Copyright (C) 2015 Lyft, Inc.

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.

Contributing

Please see CONTRIBUTING.md.

Contributors

scissors's People

Contributors

damien5314 avatar elevenfive avatar eveliotc avatar eygraber avatar hlau-lyft avatar keith avatar lexer avatar mmartin101 avatar rharter avatar ryan-lane avatar skyfishjy avatar tfcporciuncula 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  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

scissors's Issues

cropviewViewportOverlayPadding

No resource identifier found for attribute 'cropviewViewportOverlayPadding' in package .Why use android studio to add dependency can not find this attribute.

pickUsing method does not support fragments

when calling cropView.extensions() .pickUsing(this, RequestCodes.PICK_IMAGE_FROM_GALLERY); from with in a fragment returns the result to the parent activity and not back to the fragments onActivityResult Is there a work around or is this something that can be added. Thanks for the library, loving it so far.

Cannot load file into cropView

Hi @davidbeloosesky , @eveliotc

I am trying to load an image into the cropview but it does not show up. I pass a string extra to my crop image activity.

I then try to load it into the cropview using the following

@AfterViews
void setupUI() {
    if (getIntent().getExtras() != null) {
        if (getIntent().getExtras().getString(KEY_IMAGE_FILE_PATH) != null) {
            cropView.extensions()
                    .load(Uri.fromFile(new File(getIntent().getStringExtra(KEY_IMAGE_FILE_PATH))));

        }
    }

}

The value of the string on debugging is

/storage/emulated/0/Pictures/PrismApp/Current/96adeca7-79a3-4cf9-bc1c-8c736bb26ee2.jpg

Why does the image not show up? Am I using the api wrong or is it a bug?

I have even tried removing the Uri.fromFile bit and directly loading a File.

I am not using the

cropView.extensions().load(galleryPictureUri);

Instead, I am using my own intent and request code to launch my CropImageActivity before returning to my current activity.

Your page is incorrect

Front page code directs to set app:cropviewViewportHeightRatio="1" when that parameter no longer exists. I think the correct entry is app:cropviewViewportRatio="1" to function correctly. The crop aspect appears to be correct, is there any issues with setting this?

Question: How come CropViewExtensions pickUsing Fragment, is not using the support fragment?

Hello everyone!

I was wondering why the pickUsing relies on a android.app.Fragment instead of the support fragment?

    static void pickUsing(Fragment fragment, int requestCode) {
        fragment.startActivityForResult(createChooserIntent(), requestCode);
    }

I have my hands tied, as I'm using the v4 support fragment, and using the Activity counterpart is going to be really messy. Is there any plans to bring in the support functionality? Or at least is there a suggestion anyone has that I could make use of?

It doesn't work when trying to pick picture from camera.

Here is the related code:

private void loadImageFromCamera() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Uri imageUri = Uri.fromFile(createExternalCacheFile("avatar_camera.png"));
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(intent, PICK_IMAGE_FROM_CAMERA);
}

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_IMAGE_FROM_GALLERY && resultCode == RESULT_OK) {
Uri imageUri = data.getData();
mCropView.extensions().load(imageUri);
}
if (requestCode == PICK_IMAGE_FROM_CAMERA && requestCode == RESULT_OK) {
Bitmap bitmap = null;
try {
bitmap = BitmapFactory.decodeStream(new FileInputStream(createExternalCacheFile("avatar_camera.png")));
mCropView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}

CropView doesn't show the bitmap.

Fresco Integration

My project has a Fresco Drawee for the imageview.
Can I use scissors with this?

Image does not load + selecting an image loop

I tested my app on a Sony Ericsson Xperia S. It is using scissors to select images to crop before adding them.
I have used the selection as shown in the sample app.

cropView.extensions().pickUsing (this,REQ_CODE)

This works perfectly well on other devices that I have tested it on - Xiaomi, Samsung s3, Galaxy S4.
However on the Sony Ericsson Xperia S, when I select an image to crop, many times the cropView does not load the image instead the selection prompt pops up again. Is this related to the other load issue?

Library fails loading images when using Glide v4 and causes exception.

A few months ago Glide 4 has been released and there are some incompatibilities with Glide 3.
In Glide 4, there's an object that needs to be used to pass options when loading an image, as you can see in this link.
Glide options documentation

In particular, I'm using the CropView library that ends calling Scissor's load method of the GlideBitmapLoader class which has a code not supported in Glide v4.

Thanks,
Pablo

Sending to intent goes wrong

After crop, if i send picture via intent like in sample with Picasso, most of the times does nothing because file is corrupted or other causes. I made an AsyncTask with weak reference to load bitmap. I set image to crop, first time resulted bitmap is null. Second time bitmap is decoded successful. Is decoding when he wants. I do something wrong or is some bug? I followed the sample at first time and it isn't work at all.

I find sth Question by use this With Glide,and setViewportRatio(1f) aslo has some Question

Thanks for you share the Demo。

if i use
<com.lyft.android.scissors.CropView
android:id="@+id/clipfilter_img"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:cropviewViewportOverlayColor="#a0000000"
/>
at layout XML ,the picture display like fit end on bottom cropline(picture bottom coincidence with app:cropviewViewportRatio line),not the bottom your CropView。
and i use cropview.setViewportRatio(1f) aslo has this questiong.

i find that if the picture not load done then use cropview.setViewportRatio(1) will has this question。
so i ues the
Glide.with(this).load(imgPath).listener(new RequestListener<String, GlideDrawable>() {
@OverRide
public boolean onException(Exception e, String model, Target target, boolean isFirstResource) {
return false;
}

        @Override
        public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    imageView.setViewportRatio(1f);
                }
            }, 0);
            return false;
        }
    }).into(imageView);

it can solve thisquestion。
but i find another question ,the android:scaleType="" not work。the pic always fill the corpview like i use the fitXY,even a square picture aslo stretch to fill parent。

Now i use
@OverRide
protected void onResume() {
super.onResume();
handler.postDelayed(new Runnable() {
@OverRide
public void run() {
imageView.setViewportRatio(1f);
}
}, 300);
}
,but if the pic is too big or my phone not have a stronger CPU,cropView load pic 0.3S not done aslo has the fist question 。but the time aslo can't set too long which cause i can saw the setViewportRatio anim 。

Thank you。

Can I use scissors library to crop an image taken with my camera? <question>

First of all, this is a question, but sorry, I don't know how to add the label to it.

Hi, from what I've seen, this library is useful to select an image from the fallery and then crop it. Is there a way to open the device's camera, take a picture, and then crop it? If so, can you tell me how?

Thanks!

Crop to File, cannot access CropViewExtensions

Trying to crop into file using scissors 1.1.1 and i get the following error when compiling

Error:(49, 22) Cannot access 'CropViewExtensions': it is public/package/ in 'com.lyft.android.scissors'

The code in question is basically the same as the example provided.

mCropView.extensions()
                    .crop()
                    .quality(87)
                    .format(PNG)
                    .into(file)

does scissors require READ_EXTERNAL_STORAGE permission?

I've been seeing some crashes come in with the following error message:

Permission Denial: reading com.android.providers.media.MediaProvider uri content://media/external/images/media/1037 from pid=23237, uid=10079 requires android.permission.READ_EXTERNAL_STORAGE, or grantUriPermission()

This happens after I call cropView.extensions().pickUsing(...), but I can't seem to reproduce it on any of my devices.

Thanks in advance!

Is it possible to remove scaling ?

I'm following your method for cropping.So I would like to remove the scale feature from this method.May I know how I can remove the scaling ?

Guidelines over the image

It would be nice if you could add some guidelines over the image or anything that would offer the familiar look of an image-cropping screen so that the user will instantly understand that this is where cropping happens, not just to read the activity title to know they now can crop

Does that make sense?

Glide and square image

Hi?
Are there examples showing how to use this library with glide? Also, i want the cropped image to fit into a square of specific dimensions e.g 200px by 200px, how do i achieve that?

Getting position and Current scale of the image

Can the Crop view be used to re position an image in a container. the image is bigger than the CropView and i need to chose which area is visible trough the view port. to do this i would need to get the x and y position of the image in relation tho the cropView. I am using this library for cropping image in another section of my app and would like to reuse it for this function as it handles the dragging and scaling for me but after playing around with it i could not get ant information on the positioning of the image. is this supported or do i need to look else where.

Proguard Setup

@eveliotc .

The debug version of my app works fine. I created a release build for my app, and on selecting a picture to be cropped the app crashes stating the following.

java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=10001, result=-1,     data=Intent { dat=content://media/external/images/media/9279 }} to activity    {com.prism.prismapp/com.prism.prismapp.CropImageActivity_}: java.lang.IllegalStateException:    You must provide a BitmapLoader.
at android.app.ActivityThread.deliverResults(ActivityThread.java:3367)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:3410)
at android.app.ActivityThread.access$1300(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1260)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5113)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:609)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.IllegalStateException: You must provide a BitmapLoader.
at com.lyft.android.scissors.CropViewExtensions.resolveBitmapLoader(Unknown Source)
at com.lyft.android.scissors.CropViewExtensions$LoadRequest.load(Unknown Source)
at com.lyft.android.scissors.CropView$Extensions.load(Unknown Source)
at com.prism.prismapp.g.onActivityResult(Unknown Source)
at android.app.Activity.dispatchActivityResult(Activity.java:5440)
at android.app.ActivityThread.deliverResults(ActivityThread.java:3363)

Can we have an updated read me with the proguard setup?

Extensions more trouble than worth it

I'd like to suggest to remove the use of extensions completely and focusing more on the core functionality. Here are some reasons:

  1. Loading a bitmap using the loading libraries is already easy enough.
  2. ***FillViewportTransformations are suboptimal as they always create bitmaps matching the viewport size:
    • for bitmaps smaller than the viewport they will create unnecessary large bitmaps in memory.
    • for bitmaps larger than the viewport they will create bitmaps that will be blurry when zoomed in (which it mostly will be, that's the purpose of this library)
  3. Additional feature requests regarding extensions (like issue #23) are unnecessary as the loading libraries already implement it.
  4. I briefly looked over the extensions code and it seems like requests never get canceled. This might crash or leak, depending on the library in use. Again, the loading libraries already have their own mechanisms for this in place (e.g. Volley or Ion, i'm not familiar with UIL/Glide/Picasso).
  5. Images are always loaded uncached (?)

Although all of the above can be fixed, I think it's simply unnecessary as the loading libraries already do all that.

reset transform

We have a flow requiring multiple images to be selected and cropped. The issue is the CropView's transform sticks around even after loading a new image. Is there a way to reset the transform applied to the CropView before we load the next image?

Support cropping based on original image size

Currently, the cropped image can be significantly degraded from the original since the cropping is based on the view's dimensions. If the image is significantly larger than the view, the cropped image will be the size of the view, which isn't ideal, especially on budget devices.

Regardless of view size, I think the cropping should be based on the original image size, since the representation on screen is simply proportional to the actual file.

Add callback to image loading?

As far as I know there is no way to provide a "loading finished" callback to the framework. Assuming this is not a deliberate design decision, can we consider adding a method to the BitmapLoader interface that accepts a callback?

i.e. something to the effect of:

public interface BitmapLoader {
   void load(@Nullable Object model, @NonNull ImageView view);
   void load(@Nullable Object model, @NonNull ImageView view, ScissorCallback callback);
}

public interface ScissorCallback {
    void onComplete();
}

PicassoBitmapLoader / GlideBitmapLoader's implementations can then forward events generated from their respective libraries to ScissorCallback's onComplete(). This is obviously not a complete solution as we're losing a lot of information from the library callbacks but it's a start and super simple to implement.

Crop View only configurable via XML

The current CropViewConfig mechanism really cleans up attribute parsing, but also greatly limits the view since it can only be configured via xml. Want to programmatically create a view with non-default options? No, thank you.

I think we need standard getters/setters on the CropView object so that we can not only programmatically configure the view, but also alter the view at runtime (like allowing the user to choose from standard aspect ratios.

Viewport Ratio not correct when setImageURI is used.

I have code such as:

cropView.setImageURI(imageFileUri);
cropView.setViewportRatio(viewportRatioValue);

The only time the TouchManager's setViewport() code is called is when the we set the viewport. However at this state, the bitmap width/height is 0 (because the Bitmap isn't loaded yet), so we get an imageAspect of NaN, making our viewport non-existent.

GlideBitmapLoader.createUsing uses cropView's size while it might not be laid out

The following code:

cropView
  .extensions()
  .using(GlideBitmapLoader.createUsing(cropView))
  .load(uri)

won't work if cropView is not yet laid out – even with #16 in – because GlideBitmapLoader.createUsing directly extracts cropView.getHeight() and cropView.getWidth(): https://github.com/lyft/scissors/blob/master/scissors/src/main/java/com/lyft/android/scissors/GlideBitmapLoader.java#L57-L61. At this point, cropView's dimension is 0:0.

I worked around this by adding a 100ms delay, but that's obviously hacky.

Support for rotation

Is it possible to have a rotate feature?

I know this is primarily a cropping library but something like a rotate/mirror feature could add a lot of value. Thoughts?

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.