<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Uday</title>
    <description>The latest articles on Forem by Uday (@ug2454).</description>
    <link>https://forem.com/ug2454</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F497339%2Fa42df006-0c83-4bba-b1a4-e430dc846be3.jpeg</url>
      <title>Forem: Uday</title>
      <link>https://forem.com/ug2454</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/ug2454"/>
    <language>en</language>
    <item>
      <title>How to make an image editor in android</title>
      <dc:creator>Uday</dc:creator>
      <pubDate>Sat, 13 Feb 2021 17:36:38 +0000</pubDate>
      <link>https://forem.com/ug2454/how-to-make-an-image-editor-in-android-1al6</link>
      <guid>https://forem.com/ug2454/how-to-make-an-image-editor-in-android-1al6</guid>
      <description>&lt;p&gt;So in this post i will tell you about how you can make an image editor with rotate, crop, undo and save functionality.&lt;br&gt;
I must tell you that making this was no easy feat i had to research for 2-3 whole days to implement the functionality when clicking pictures from camera.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjkm8npqmwb8mgexs3s0k.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjkm8npqmwb8mgexs3s0k.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8s9crtpkpbev2xzrqjsz.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8s9crtpkpbev2xzrqjsz.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  There are a few things to take care of:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Camera Permission, Read External Storage Permission&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;api 'com.theartofdev.edmodo:android-image-cropper:2.8.+'&lt;/code&gt; Library for cropping image&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So to begin, the requirement given to me was: &lt;br&gt;
"There will be 2 screens Home and Edit, in the Home screen there will be an ImageView for the final image to show and 2 buttons, one for camera and other to choose image from gallery. This post will be only for the image from camera.&lt;/p&gt;

&lt;p&gt;So first design the Home page with 2 buttons and an &lt;code&gt;ImageView&lt;/code&gt; in your layout file.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"&amp;gt;

    &amp;lt;ImageView
        android:id="@+id/imageView"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_marginTop="126dp"
        android:scaleType="fitCenter"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.497"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" /&amp;gt;

    &amp;lt;LinearLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_marginStart="32dp"
        android:layout_marginLeft="32dp"
        android:layout_marginTop="106dp"
        android:layout_marginEnd="32dp"
        android:layout_marginRight="32dp"
        android:orientation="horizontal"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/imageView"&amp;gt;

        &amp;lt;Button
            android:id="@+id/selfieButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="30dp"
            android:layout_marginLeft="30dp"
            android:layout_marginEnd="30dp"
            android:layout_marginRight="30dp"
            android:layout_weight="1"
            android:onClick="clickSelfie"
            android:text="Selfie" /&amp;gt;

        &amp;lt;Button
            android:id="@+id/galleryButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="30dp"
            android:layout_marginLeft="30dp"
            android:layout_marginEnd="30dp"
            android:layout_marginRight="30dp"
            android:layout_weight="1"
            android:onClick="clickGallery"
            android:text="Gallery" /&amp;gt;
    &amp;lt;/LinearLayout&amp;gt;

    &amp;lt;TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="28dp"
        android:text="Select an Image"
        android:textSize="24sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/imageView" /&amp;gt;

&amp;lt;/androidx.constraintlayout.widget.ConstraintLayout&amp;gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;It will look something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fr2fwym0ry5psp4rgvbam.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fr2fwym0ry5psp4rgvbam.png" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After that, you will need to set the camera permission in &lt;code&gt;AndroidManifest.xml&lt;/code&gt; and your &lt;code&gt;MainActivity&lt;/code&gt; from where you are calling the camera Intent.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

 @RequiresApi(api = Build.VERSION_CODES.Q)
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == 1) {
            if (grantResults.length &amp;gt; 0 &amp;amp;&amp;amp; grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                getPhoto();
            }
        }
    }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then when all the permissions are setup you can start the camera Intent, &lt;/p&gt;

&lt;p&gt;So to get a high quality image, you have to store the Uri of the image in the device folder and retrieve it in the onActivityResult and store it into a &lt;code&gt;Bitmap&lt;/code&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

private void getPhoto() {
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        // Ensure that there's a camera activity to handle the intent
        if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
            // Create the File where the photo should go
            File photoFile = null;
            try {
                photoFile = createImageFile();
            } catch (IOException ex) {
                // Error occurred while creating the File
                System.out.println(ex.getMessage());
            }
            // Continue only if the File was successfully created
            if (photoFile != null) {
                Uri photoURI = FileProvider.getUriForFile(this,
                        "com.example.imageeditor.fileprovider",
                        photoFile);
                takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
                startActivityForResult(takePictureIntent, 1);
            }
        }

    }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;So this will create a filename in .jpg format and save it in the &lt;code&gt;externalFilesDirectory&lt;/code&gt; which will not be accessible to media sharing apps and it will be only used for your app.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

  private File createImageFile() throws IOException {
        // Create an image file name
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        imageFileName = "JPEG_" + timeStamp + "_";
        File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
        File image = File.createTempFile(
                imageFileName,  /* prefix */
                ".jpg",         /* suffix */
                storageDir      /* directory */
        );

        // Save a file: path for use with ACTION_VIEW intents
        currentPhotoPath = image.getAbsolutePath();
        System.out.println(currentPhotoPath);
        return image;
    }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Above code will set the unique image name for our image using a Date Time format.&lt;/p&gt;

&lt;p&gt;To save it in the files directory, you need to assign a content provider. So give it in your manifest.xml under  tag.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&amp;lt;application&amp;gt;
\\
  &amp;lt;provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="com.example.imageeditor.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true"&amp;gt;
            &amp;lt;meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" /&amp;gt;
        &amp;lt;/provider&amp;gt;
\\
&amp;lt;/application&amp;gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You also need to create a path.xml file &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;paths xmlns:android="http://schemas.android.com/apk/res/android"&amp;gt;
    &amp;lt;external-files-path name="my_images" path="Pictures" /&amp;gt;
&amp;lt;/paths&amp;gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This will set the path where the image will be downloaded under your package in your device.&lt;/p&gt;

&lt;p&gt;Then you need to save the bitmap image in your gallery and for that you need to make use of ContentValues because the writing of image in the device is deprecated for API 21 and higher.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

 ContentValues contentValues = new ContentValues();
                contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, imageFileName + ".jpg");
                contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");
                contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES);

                ContentResolver resolver = getContentResolver();
                uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
                OutputStream imageOutStream = null;

                try {
                    if (uri == null) {
                        throw new IOException("Failed to insert MediaStore row");
                    }

                    imageOutStream = resolver.openOutputStream(uri);

                    if (!bitmap.compress(Bitmap.CompressFormat.JPEG, 100, imageOutStream)) {
                        throw new IOException("Failed to compress bitmap");
                    }


                    Toast.makeText(this, "Imave Saved", Toast.LENGTH_SHORT).show();

                } finally {
                    if (imageOutStream != null) {
                        imageOutStream.close();


                    }
                    Intent intent = new Intent(this, EditImageActivity.class);

                    startActivity(intent);


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;So with this, your image is now saved in the gallery with full quality and it will be set on the image view in the next screen.&lt;/p&gt;

&lt;h3&gt;
  
  
  Edit Screen
&lt;/h3&gt;

&lt;p&gt;So now comes the edit screen.&lt;/p&gt;

&lt;p&gt;Most of your logic will be written here, for the rotate, crop save and undo.&lt;/p&gt;

&lt;p&gt;Make a layout file it will look something like this &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fb5l6gluphd3ph3o5w1ff.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fb5l6gluphd3ph3o5w1ff.png" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First lets do the rotate button.&lt;br&gt;
So now you have the image in a bitmap and its set on the iamgeview on the edit screen. Question is how to make it rotate and then save it to a new bitmap to be saved.&lt;/p&gt;

&lt;p&gt;For rotation i have used RotateAnimation class which takes fromRotation angle, toRotation angle, image height and width.&lt;/p&gt;

&lt;p&gt;then create a Matrix object and set its rotation to the toRotaion value. Initialize 3 variables, mCurrentRotation, fromRotation, toRotation.&lt;/p&gt;

&lt;p&gt;Now when you first press rotate button the image will rotate 90 degree from current angle which is 0.&lt;br&gt;
So add 90 each time you press the button and set it to currentRotation and toRotation. And set mCurrentRotation to be %360 so that after 1 complete cycle it resets to 0.&lt;br&gt;
Then after this, you need to create a new bitmap with updated angles.&lt;/p&gt;

&lt;p&gt;Like below, then start the animation and the imageview will rotate with a smooth animation for easy look and feel.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

 public void rotate(View view) {
        isRotate = true;
        mCurrRotation %= 360;
        Matrix matrix = new Matrix();


        System.out.println(imageView.getRotation());
        fromRotation = mCurrRotation;
        toRotation = mCurrRotation += 90;

        final RotateAnimation rotateAnimation = new RotateAnimation(
                fromRotation, toRotation, imageView.getWidth() / 2, imageView.getHeight() / 2);

        rotateAnimation.setDuration(1000);
        rotateAnimation.setFillAfter(true);


        matrix.setRotate(toRotation);
        System.out.println(toRotation + "TO ROTATION");
        System.out.println(fromRotation + "FROM ROTATION");
        if (croppedBitmap != null) {
            cropThenRotateBitmap = Bitmap.createBitmap(croppedBitmap, 0, 0, croppedBitmap.getWidth(), croppedBitmap.getHeight(), matrix, true);
        } else {
            rotateBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
        }


        imageView.startAnimation(rotateAnimation);


    }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  Now for crop image
&lt;/h4&gt;

&lt;p&gt;For this add the library in the grade &lt;br&gt;
&lt;code&gt;api 'com.theartofdev.edmodo:android-image-cropper:2.8.+'&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;thats it you're good to use the crop functionality.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

 public void crop(View view) {

        if(rotateBitmap!=null){
            ByteArrayOutputStream bytes = new ByteArrayOutputStream();
            rotateBitmap.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
            String path = MediaStore.Images.Media.insertImage(getContentResolver(), rotateBitmap, imageFileName+".jpg", null);
//            System.out.println(Uri.parse(path));
             uri=Uri.parse(path);
        }
        CropImage.activity(uri)
                .start(this);
    }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;using CropImage.activity it will open a crop view where you can set the crop size and then handle it into the onActivityResult method&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

 public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE) {
            CropImage.ActivityResult result = CropImage.getActivityResult(data);
            if (resultCode == RESULT_OK) {
                resultUri = result.getUri();
                imageView.setImageURI(resultUri);
//                Matrix matrix = new Matrix();
                BitmapDrawable bitmapDrawable = (BitmapDrawable) imageView.getDrawable();
                System.out.println(imageView.getRotation());
                croppedBitmap = bitmapDrawable.getBitmap();
                if (isRotate) {
                    rotateThenCropBitmap = croppedBitmap;
                }

            } else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE) {
                Exception error = result.getError();
            }
        }
    }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;so in this get the uri and set it into the imageview.&lt;br&gt;
Then you need to get the bitmap from for the cropped image so extract the bitmap from the imageview using &lt;code&gt;BitmapDrawable&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;and for undo you just have to null everybitmap and set the image view to the original bitmal and make all the angles 0 so that it goes back to its original rotation.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

public void undo(View view) {
        Matrix matrix = new Matrix();


         toRotation = mCurrRotation += 90;

        final RotateAnimation rotateAnimation = new RotateAnimation(
                fromRotation, 0, imageView.getWidth() / 2, imageView.getHeight() / 2);

        rotateAnimation.setDuration(1000);
        rotateAnimation.setFillAfter(true);


        matrix.setRotate(toRotation);
        System.out.println(toRotation + "TO ROTATION");
        System.out.println(fromRotation + "FROM ROTATION");
        if (croppedBitmap != null) {
            cropThenRotateBitmap = Bitmap.createBitmap(croppedBitmap, 0, 0, croppedBitmap.getWidth(), croppedBitmap.getHeight(), matrix, true);
        } else {
            rotateBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
        }

        imageView.setImageBitmap(bitmap);
        imageView.startAnimation(rotateAnimation);
        makeBitmapNull();
    }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;then lastly save. in here you have to handle all the different scenarios.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

@RequiresApi(api = Build.VERSION_CODES.Q)
    public void save(View view) throws IOException {


        ContentValues contentValues = new ContentValues();
        contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, imageFileName + ".jpg");
        contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");
        contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES);

        ContentResolver resolver = getContentResolver();
        Uri uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
        OutputStream imageOutStream = null;

        try {
            if (uri == null) {
                throw new IOException("Failed to insert MediaStore row");
            }

            imageOutStream = resolver.openOutputStream(uri);
            if (cropThenRotateBitmap != null) {
                if (!cropThenRotateBitmap.compress(Bitmap.CompressFormat.JPEG, 100, imageOutStream)) {
                    throw new IOException("Failed to compress bitmap");
                }
            } else if (rotateThenCropBitmap != null) {
                if (!rotateThenCropBitmap.compress(Bitmap.CompressFormat.JPEG, 100, imageOutStream)) {
                    throw new IOException("Failed to compress bitmap");
                }
            } else if (croppedBitmap != null) {
                if (!croppedBitmap.compress(Bitmap.CompressFormat.JPEG, 100, imageOutStream)) {
                    throw new IOException("Failed to compress bitmap");
                }
            } else if (rotateBitmap != null) {
                if (!rotateBitmap.compress(Bitmap.CompressFormat.JPEG, 100, imageOutStream)) {
                    throw new IOException("Failed to compress bitmap");
                }
            } else {
                if (!bitmap.compress(Bitmap.CompressFormat.JPEG, 100, imageOutStream)) {
                    throw new IOException("Failed to compress bitmap");
                }
            }

            Toast.makeText(this, "Imave Saved", Toast.LENGTH_SHORT).show();

        } finally {
            if (imageOutStream != null) {
                imageOutStream.close();
                Intent intent = new Intent(this, MainActivity.class);
                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

                finish();
                startActivity(intent);
            }
        }

    }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then you have to take extra care on saving if you have rotated the photo before doing crop or you are cropping then rotating the image. Because all this will effect the bitmap which will finally be saved and displayed in the image view on the main screen. &lt;br&gt;
To solve this was the most challenging part. Sometimes images where not saving, sometimes there comes a previously saved image on the crop button, sometimes a previously saved image would be shown upon saving on the main screen.&lt;/p&gt;

&lt;p&gt;To handle all this scenarios i have to make different bitmap for each scenario.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;rotate then save&lt;/li&gt;
&lt;li&gt;crop then save&lt;/li&gt;
&lt;li&gt;rotate then crop then save&lt;/li&gt;
&lt;li&gt;crop then rotate then save&lt;/li&gt;
&lt;li&gt;rotate undo then save&lt;/li&gt;
&lt;li&gt;crop undo then save&lt;/li&gt;
&lt;li&gt;save the original image as is&lt;/li&gt;
&lt;li&gt;rotate then crop then undo then save&lt;/li&gt;
&lt;li&gt;crop then rotate then undo then save&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All these scenarios needed to handled to make the app more robust and effective.&lt;/p&gt;

&lt;p&gt;Then finally in the onCreate method in the MainActivity set the image view to whatever bitmap is not null &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

  if (cropThenRotateBitmap != null) {
            imageView.setImageBitmap(cropThenRotateBitmap);
            textView.setText("Edited Image");
            makeBitmapNull();

        } else if (rotateThenCropBitmap != null) {
            imageView.setImageBitmap(rotateThenCropBitmap);
            textView.setText("Edited Image");
            makeBitmapNull();

        } else if (rotateBitmap != null) {
            imageView.setImageBitmap(rotateBitmap);
            textView.setText("Edited Image");
            makeBitmapNull();
        } else if (croppedBitmap != null) {
            imageView.setImageBitmap(croppedBitmap);
            textView.setText("Edited Image");
            makeBitmapNull();
        } else if(bitmap!=null) {
            imageView.setImageBitmap(bitmap);
            textView.setText("Edited Image");
            makeBitmapNull();
        }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;check each condition and according to that set the bitmap.&lt;/p&gt;

&lt;p&gt;So with this this tutorial comes to an end.&lt;/p&gt;

&lt;p&gt;I learned various things with this assignment, it increased my knowledge about image saving and retriving from the device and use of bitmap and camera. This whole work took me 3 days to finish but the next time i am tasked with a similar requirement it will take me the least amount of time to complete.&lt;/p&gt;

</description>
      <category>android</category>
      <category>androidstudio</category>
      <category>developer</category>
      <category>imageeditor</category>
    </item>
    <item>
      <title>How to convert and use SVG in an android app</title>
      <dc:creator>Uday</dc:creator>
      <pubDate>Fri, 29 Jan 2021 15:07:10 +0000</pubDate>
      <link>https://forem.com/ug2454/how-to-convert-and-use-svg-in-an-android-app-287a</link>
      <guid>https://forem.com/ug2454/how-to-convert-and-use-svg-in-an-android-app-287a</guid>
      <description>&lt;h4&gt;
  
  
  How to convert jpg or png to SVG
&lt;/h4&gt;

&lt;p&gt;To use SVG in android there are a number of ways but the one i used was to create a vector of a SVG and then putting that into a drawable. It sounds straightforward but it was not for me, had to solve some pesky issues before i got it working.&lt;/p&gt;

&lt;p&gt;First, convert your png or jpg to SVG using any online tool, you can find it on google. &lt;br&gt;
Then create a vector drawable with that SVG by going to below link:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://svg2vector.com/"&gt;svg2vector&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now put that xml in your drawable folder and then you can use that in your &lt;code&gt;ImageView&lt;/code&gt; resource.&lt;/p&gt;

</description>
      <category>android</category>
      <category>svg</category>
      <category>androiddev</category>
      <category>androidstudio</category>
    </item>
    <item>
      <title>How to display List of Followers or Following in your Image sharing app(Flutter)</title>
      <dc:creator>Uday</dc:creator>
      <pubDate>Tue, 01 Dec 2020 11:20:09 +0000</pubDate>
      <link>https://forem.com/ug2454/how-to-display-list-of-followers-or-following-in-your-image-sharing-app-flutter-20j5</link>
      <guid>https://forem.com/ug2454/how-to-display-list-of-followers-or-following-in-your-image-sharing-app-flutter-20j5</guid>
      <description>&lt;h1&gt;
  
  
  Title
&lt;/h1&gt;

&lt;p&gt;So in todays post, i will tell you about how to display the list of users who are following you and list of users you are following.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pre Requisite
&lt;/h3&gt;

&lt;p&gt;Pre-requisite for this is that you already have a basic structure and code of the image sharing app like Instagram.&lt;/p&gt;

&lt;p&gt;So now you are on your profile page and you want to view all your follower and following list. So to do that, provided you have a 'follower' and 'following' collection setup in firebase, you have to Fetch all the documents of the particular Profile which you are cliking and then use that id as a doc id for the 'user' collection. So first, fetch all the records of 'Follower' colection for that id using &lt;code&gt;QuerySnapshot&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;the code for it will be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;QuerySnapshot querySnapshot = await followersRef
        .doc(widget.profileId) // the id of profile you are cliking
        .collection('userFollowers')
        .get();

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;add all the records in a List of string, using a map and then converting it into a list, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;followers = querySnapshot.docs.map((doc) =&amp;gt; doc.id).toList();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now implement a &lt;code&gt;FutureBuilder&lt;/code&gt; or &lt;code&gt;StreamBuilder&lt;/code&gt; of type &lt;code&gt;&amp;lt;QuerySnapshot&amp;gt;&lt;/code&gt; whatever is your choice and then in the &lt;code&gt;future&lt;/code&gt; or &lt;code&gt;stream&lt;/code&gt; , give the 'user' collection reference. &lt;br&gt;
Then using &lt;code&gt;snapshot&lt;/code&gt;, loop through all the user records and add only those in a new List which contains id in the &lt;code&gt;followers&lt;/code&gt; list(defined earlier).&lt;/p&gt;

&lt;p&gt;so,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if(followers.contains(user.id)){
// add that user to the List else return from the loop
}
else return;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then using the new List, pass it to the &lt;code&gt;ListView&lt;/code&gt; which you will return in the &lt;code&gt;FutureBuilder&lt;/code&gt; or &lt;code&gt;StreamBuilder&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Thats it to show the follower list, and same thing has to be done to show the following list. Just in place of 'follower' collection, get the records from 'following' collection.&lt;/p&gt;

&lt;p&gt;Thats it! thats all you have to do to show all the users in your Follower or Following section. :D&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>firebase</category>
      <category>dart</category>
      <category>programming</category>
    </item>
    <item>
      <title>Saving unique data in firebase using sub-collection</title>
      <dc:creator>Uday</dc:creator>
      <pubDate>Fri, 23 Oct 2020 13:12:43 +0000</pubDate>
      <link>https://forem.com/ug2454/saving-unique-data-in-firebase-using-sub-collection-1678</link>
      <guid>https://forem.com/ug2454/saving-unique-data-in-firebase-using-sub-collection-1678</guid>
      <description>&lt;h3&gt;
  
  
  In this post i will tell you how you can save unique data for each user which can be saved only once a day.
&lt;/h3&gt;

&lt;p&gt;So i had this requirement where user wants to save their data but only once a day. If user tries to save the data again, they will get an error saying 'You can only save data once per day'. The meaning of doing this was so that we can get the average data of a week or a month and then display it as a graph for the user. &lt;/p&gt;

&lt;p&gt;There are often user scenarios where you don't want to overwrite the data and need to set some business rule around how often the user can log the data or not. &lt;/p&gt;

&lt;p&gt;The key is in the hierarchy of the data and how that is structured.&lt;/p&gt;

&lt;p&gt;So let's say just for the sake of argument the user wants to log when they get to work in the morning and once this is logged, it should not be edited.&lt;/p&gt;

&lt;p&gt;It is very easy, first of all you have to create a collection, say 'arrival'. Then you have to give its document id, in my case the document id is the uid of the current user who is logged in.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; _firestore
                        .collection('arrival')
                        .doc(_auth.currentUser.uid)
                        .collection('userarrival')
                        .doc(current1)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;in above code, &lt;code&gt;_auth.currentUser.uid&lt;/code&gt; is giving me the unique id of each user as doc id. Then i have created a sub-collection named 'userarrival'. And then for its document-id i am giving the current date in the format(YYYY-MM-DD).&lt;/p&gt;

&lt;p&gt;So whenever user enters data on a new day it will be added in the cloud firestore. For checking if data document already exists in the database, i am checking it with a method which returns a bool.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Future&amp;lt;bool&amp;gt; checkIfDocExists(id) async {
    try {
      var collectionRef = _firestore
          .collection('arrival')
          .doc(_auth.currentUser.uid)
          .collection('userarrival');
      var doc = await collectionRef.doc(id).get();
      return doc.exists;
    } catch (e) {
      throw e;
    }
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So in the above code, i am giving id as current date in the format(YYYY-MM-DD), it will check if todays date document is already present or not. If exists, it will return true, else false.&lt;br&gt;
and if document is present, it will give an error using &lt;code&gt;showDialog()&lt;/code&gt; in flutter. Else, add the data in the database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;_firestore
                        .collection('arrival')
                        .doc(_auth.currentUser.uid)
                        .collection('userarrival')
                        .doc(current1)
                        .set({
                      //data
                    });
                    Navigator.pop(context);
                    print('pain value saved in db');
                  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thats, it. Thats all you have to do to save unique user data for each day.&lt;/p&gt;

</description>
      <category>dart</category>
      <category>flutter</category>
      <category>firebase</category>
    </item>
  </channel>
</rss>
