diff --git a/app/src/main/java/swati4star/createpdf/activity/MainActivity.java b/app/src/main/java/swati4star/createpdf/activity/MainActivity.java index ca4237690..c8690cff4 100644 --- a/app/src/main/java/swati4star/createpdf/activity/MainActivity.java +++ b/app/src/main/java/swati4star/createpdf/activity/MainActivity.java @@ -22,6 +22,7 @@ import io.github.tonnyl.whatsnew.item.WhatsNewItem; import swati4star.createpdf.R; import swati4star.createpdf.fragment.AboutUsFragment; +import swati4star.createpdf.fragment.ExtractImagesFragment; import swati4star.createpdf.fragment.HistoryFragment; import swati4star.createpdf.fragment.ImageToPdfFragment; import swati4star.createpdf.fragment.MergeFilesFragment; @@ -238,6 +239,9 @@ public boolean onNavigationItemSelected(@NonNull MenuItem item) { case R.id.nav_about: fragment = new AboutUsFragment(); break; + case R.id.nav_extract_images: + fragment = new ExtractImagesFragment(); + break; } if (fragment != null) { diff --git a/app/src/main/java/swati4star/createpdf/fragment/ExtractImagesFragment.java b/app/src/main/java/swati4star/createpdf/fragment/ExtractImagesFragment.java new file mode 100644 index 000000000..ad29bc61b --- /dev/null +++ b/app/src/main/java/swati4star/createpdf/fragment/ExtractImagesFragment.java @@ -0,0 +1,240 @@ +package swati4star.createpdf.fragment; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.net.Uri; +import android.os.Bundle; +import android.os.Environment; +import android.support.annotation.NonNull; +import android.support.design.widget.BottomSheetBehavior; +import android.support.design.widget.Snackbar; +import android.support.v4.app.Fragment; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; + +import com.dd.morphingbutton.MorphingButton; +import com.itextpdf.text.pdf.PRStream; +import com.itextpdf.text.pdf.PdfName; +import com.itextpdf.text.pdf.PdfObject; +import com.itextpdf.text.pdf.PdfReader; +import com.itextpdf.text.pdf.parser.PdfImageObject; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Objects; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.OnClick; +import swati4star.createpdf.R; +import swati4star.createpdf.adapter.MergeFilesAdapter; +import swati4star.createpdf.util.DirectoryUtils; +import swati4star.createpdf.util.FileUtils; +import swati4star.createpdf.util.MorphButtonUtility; +import swati4star.createpdf.util.ViewFilesDividerItemDecoration; + +import static android.app.Activity.RESULT_OK; + +public class ExtractImagesFragment extends Fragment implements MergeFilesAdapter.OnClickListener { + + private Activity mActivity; + private String mPath; + private MorphButtonUtility mMorphButtonUtility; + private FileUtils mFileUtils; + private DirectoryUtils mDirectoryUtils; + private static final int INTENT_REQUEST_PICKFILE_CODE = 10; + + @BindView(R.id.selectFile) + Button selectFileButton; + @BindView(R.id.extractImages) + MorphingButton extractImagesButton; + BottomSheetBehavior sheetBehavior; + @BindView(R.id.bottom_sheet) + LinearLayout layoutBottomSheet; + @BindView(R.id.upArrow) + ImageView mUpArrow; + @BindView(R.id.downArrow) + ImageView mDownArrow; + @BindView(R.id.layout) + RelativeLayout mLayout; + @BindView(R.id.recyclerViewFiles) + RecyclerView mRecyclerViewFiles; + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View rootview = inflater.inflate(R.layout.fragment_extract_images, container, false); + ButterKnife.bind(this, rootview); + sheetBehavior = BottomSheetBehavior.from(layoutBottomSheet); + sheetBehavior.setBottomSheetCallback(new ExtractImagesFragment.BottomSheetCallback()); + + ArrayList mAllFilesPaths = mDirectoryUtils.getAllFilePaths(); + if (mAllFilesPaths == null || mAllFilesPaths.size() == 0) { + mLayout.setVisibility(View.GONE); + } + + // Init recycler view + MergeFilesAdapter mergeFilesAdapter = new MergeFilesAdapter(mActivity, mAllFilesPaths, this); + RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(mActivity); + mRecyclerViewFiles.setLayoutManager(mLayoutManager); + mRecyclerViewFiles.setAdapter(mergeFilesAdapter); + mRecyclerViewFiles.addItemDecoration(new ViewFilesDividerItemDecoration(mActivity)); + + return rootview; + } + + @OnClick(R.id.viewFiles) + void onViewFilesClick(View view) { + if (sheetBehavior.getState() != BottomSheetBehavior.STATE_EXPANDED) { + sheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED); + } else { + sheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED); + } + } + + /** + * Displays file chooser intent + */ + @OnClick(R.id.selectFile) + public void showFileChooser() { + String folderPath = Environment.getExternalStorageDirectory() + "/"; + Intent intent = new Intent(); + intent.setAction(Intent.ACTION_GET_CONTENT); + Uri myUri = Uri.parse(folderPath); + intent.setDataAndType(myUri, getString(R.string.pdf_type)); + Intent intentChooser = Intent.createChooser(intent, getString(R.string.merge_file_select)); + startActivityForResult(intentChooser, INTENT_REQUEST_PICKFILE_CODE); + } + + public void onActivityResult(int requestCode, int resultCode, Intent data) throws NullPointerException { + if (data == null || resultCode != RESULT_OK || data.getData() == null) + return; + if (requestCode == INTENT_REQUEST_PICKFILE_CODE) { + setTextAndActivateButtons(getFilePath(data.getData())); + } + } + + //Returns the complete filepath of the PDF as a string + private String getFilePath(Uri uri) { + String uriString = uri.toString(); + File file = new File(uri.toString()); + String path = file.getPath(); + String returnPath = Environment.getExternalStorageDirectory().getAbsolutePath(); + Boolean success; + String name = null; + if (uriString.startsWith("content://") && uriString.contains("com.google.android.")) { + success = false; + } else { + success = true; + name = mFileUtils.getFileName(uri); + } + if (success) { + String folname = mDirectoryUtils.getParentFolder(path); + if (folname != null) { + String c = getString(R.string.path_seperator); + returnPath = returnPath + c + folname + c + name; + } + } + return returnPath; + } + + @OnClick(R.id.extractImages) + public void parse() { + PdfReader reader = null; + int imagesCount = 0; + try { + reader = new PdfReader(mPath); + Log.v("path", mPath); + PdfObject obj; + for (int i = 1; i <= reader.getXrefSize(); i++) { + obj = reader.getPdfObject(i); + if (obj != null && obj.isStream()) { + PRStream stream = (PRStream) obj; + PdfObject type = stream.get(PdfName.SUBTYPE); //get the object type + if (type != null && type.toString().equals(PdfName.IMAGE.toString())) { + PdfImageObject pio = new PdfImageObject(stream); + byte[] image = pio.getImageAsBytes(); + Bitmap bmp = BitmapFactory.decodeByteArray(image, 0, + image.length); + imagesCount++; + mFileUtils.saveImage(bmp); + } + } + } + } catch (IOException e) { + e.printStackTrace(); + } + if (imagesCount == 0) { + showSnackbar(getString(R.string.extract_images_failed)); + } else { + showSnackbar(String.format(getString(R.string.extract_images_success), + imagesCount)); + } + mPath = ""; + selectFileButton.setText(R.string.merge_file_select); + selectFileButton.setBackgroundColor(getResources().getColor(R.color.colorGray)); + mMorphButtonUtility.morphToGrey(extractImagesButton, mMorphButtonUtility.integer()); + extractImagesButton.setEnabled(false); + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + mActivity = (Activity) context; + mMorphButtonUtility = new MorphButtonUtility(mActivity); + mFileUtils = new FileUtils(mActivity); + mDirectoryUtils = new DirectoryUtils(mActivity); + } + + @Override + public void onItemClick(String path) { + sheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED); + setTextAndActivateButtons(path); + } + + private void setTextAndActivateButtons(String path) { + mPath = path; + selectFileButton.setText(mPath); + selectFileButton.setBackgroundColor(getResources().getColor(R.color.mb_green_dark)); + extractImagesButton.setEnabled(true); + mMorphButtonUtility.morphToSquare(extractImagesButton, mMorphButtonUtility.integer()); + } + + private class BottomSheetCallback extends BottomSheetBehavior.BottomSheetCallback { + + @Override + public void onStateChanged(@NonNull View bottomSheet, int newState) { + switch (newState) { + case BottomSheetBehavior.STATE_EXPANDED: + mUpArrow.setVisibility(View.GONE); + mDownArrow.setVisibility(View.VISIBLE); + break; + case BottomSheetBehavior.STATE_COLLAPSED: + mUpArrow.setVisibility(View.VISIBLE); + mDownArrow.setVisibility(View.GONE); + break; + } + } + + @Override + public void onSlide(@NonNull View bottomSheet, float slideOffset) { + } + } + + private void showSnackbar(String resID) { + Snackbar.make(Objects.requireNonNull(mActivity).findViewById(android.R.id.content), + resID, Snackbar.LENGTH_LONG).show(); + } +} diff --git a/app/src/main/java/swati4star/createpdf/util/FileUtils.java b/app/src/main/java/swati4star/createpdf/util/FileUtils.java index f7191883e..8e97b45b3 100644 --- a/app/src/main/java/swati4star/createpdf/util/FileUtils.java +++ b/app/src/main/java/swati4star/createpdf/util/FileUtils.java @@ -6,6 +6,7 @@ import android.content.Context; import android.content.Intent; import android.database.Cursor; +import android.graphics.Bitmap; import android.net.Uri; import android.os.Bundle; import android.os.CancellationSignal; @@ -19,6 +20,7 @@ import android.provider.MediaStore; import android.support.design.widget.Snackbar; import android.support.v4.content.FileProvider; +import android.util.Log; import java.io.File; import java.io.FileInputStream; @@ -288,4 +290,26 @@ else if (scheme.equals("content")) { public String getFileName(String path) { return path.substring(path.lastIndexOf(mContext.getString(R.string.path_seperator)) + 1); } + + /** + * Saves bitmap to external storage + * @param finalBitmap - bitmap to save + */ + public void saveImage(Bitmap finalBitmap) { + String root = Environment.getExternalStorageDirectory().toString(); + File myDir = new File(root + mContext.getString(R.string.pdf_dir)); + String fname = "image_" + System.currentTimeMillis() + ".jpg"; + + File file = new File(myDir, fname); + if (file.exists()) file.delete(); + try { + FileOutputStream out = new FileOutputStream(file); + finalBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out); + Log.v("saving", fname); + out.flush(); + out.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } } \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_broken_image_black_24dp.xml b/app/src/main/res/drawable/ic_broken_image_black_24dp.xml new file mode 100644 index 000000000..8d563a9b8 --- /dev/null +++ b/app/src/main/res/drawable/ic_broken_image_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/fragment_extract_images.xml b/app/src/main/res/layout/fragment_extract_images.xml new file mode 100644 index 000000000..bf64352e7 --- /dev/null +++ b/app/src/main/res/layout/fragment_extract_images.xml @@ -0,0 +1,51 @@ + + + + + +