Skip to content

Commit

Permalink
#512 - add invert pdf feature (#560)
Browse files Browse the repository at this point in the history
  • Loading branch information
Shivamdhuria authored and Swati4star committed Feb 17, 2019
1 parent 4673d9f commit db7fb30
Show file tree
Hide file tree
Showing 13 changed files with 442 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import swati4star.createpdf.fragment.HistoryFragment;
import swati4star.createpdf.fragment.HomeFragment;
import swati4star.createpdf.fragment.ImageToPdfFragment;
import swati4star.createpdf.fragment.InvertPdfFragment;
import swati4star.createpdf.fragment.MergeFilesFragment;
import swati4star.createpdf.fragment.PdfToImageFragment;
import swati4star.createpdf.fragment.QrBarcodeScanFragment;
Expand Down Expand Up @@ -379,6 +380,9 @@ public boolean onNavigationItemSelected(@NonNull MenuItem item) {
case R.id.nav_remove_duplicate_pages:
fragment = new RemoveDuplicatePagesFragment();
break;
case R.id.nav_invert_pdf:
fragment = new InvertPdfFragment();
break;
}

try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ public class HomeFragment extends Fragment implements View.OnClickListener {
MyCardView addImages;
@BindView(R.id.remove_duplicates_pages_pdf)
MyCardView removeDuplicatePages;
@BindView(R.id.invert_pdf)
MyCardView invertPdf;


private HashMap<Integer, Integer> mFragmentPositionMap;
Expand Down Expand Up @@ -97,6 +99,7 @@ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
addWatermark.setOnClickListener(this);
addImages.setOnClickListener(this);
removeDuplicatePages.setOnClickListener(this);
invertPdf.setOnClickListener(this);
return rootview;
}

Expand All @@ -120,6 +123,8 @@ private void fillMap() {
mFragmentPositionMap.put(R.id.remove_password, 13);
mFragmentPositionMap.put(R.id.add_images, 14);
mFragmentPositionMap.put(R.id.remove_duplicates_pages_pdf, 15);
mFragmentPositionMap.put(R.id.invert_pdf, 16);

}

@Override
Expand Down Expand Up @@ -216,6 +221,9 @@ public void onClick(View v) {
case R.id.remove_duplicates_pages_pdf:
fragment = new RemoveDuplicatePagesFragment();
break;
case R.id.invert_pdf:
fragment = new InvertPdfFragment();
break;
}

try {
Expand Down
195 changes: 195 additions & 0 deletions app/src/main/java/swati4star/createpdf/fragment/InvertPdfFragment.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
package swati4star.createpdf.fragment;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomSheetBehavior;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
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.afollestad.materialdialogs.MaterialDialog;
import com.airbnb.lottie.LottieAnimationView;
import com.dd.morphingbutton.MorphingButton;

import java.util.ArrayList;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import swati4star.createpdf.R;
import swati4star.createpdf.adapter.FilesListAdapter;
import swati4star.createpdf.adapter.MergeFilesAdapter;
import swati4star.createpdf.database.DatabaseHelper;
import swati4star.createpdf.interfaces.BottomSheetPopulate;
import swati4star.createpdf.interfaces.OnPDFCreatedInterface;
import swati4star.createpdf.util.BottomSheetCallback;
import swati4star.createpdf.util.BottomSheetUtils;
import swati4star.createpdf.util.FileUtils;
import swati4star.createpdf.util.InvertPdf;
import swati4star.createpdf.util.MorphButtonUtility;
import swati4star.createpdf.util.RemoveDuplicates;
import swati4star.createpdf.util.ViewFilesDividerItemDecoration;

import static android.app.Activity.RESULT_OK;
import static swati4star.createpdf.util.DialogUtils.createAnimationDialog;
import static swati4star.createpdf.util.FileUriUtils.getFilePath;
import static swati4star.createpdf.util.StringUtils.getSnackbarwithAction;
import static swati4star.createpdf.util.StringUtils.showSnackbar;

public class InvertPdfFragment extends Fragment implements MergeFilesAdapter.OnClickListener,
FilesListAdapter.OnFileItemClickedListener, BottomSheetPopulate, OnPDFCreatedInterface {

private Activity mActivity;
private String mPath;
private MorphButtonUtility mMorphButtonUtility;
private FileUtils mFileUtils;
private BottomSheetUtils mBottomSheetUtils;
private static final int INTENT_REQUEST_PICKFILE_CODE = 10;
private MaterialDialog mMaterialDialog;

@BindView(R.id.lottie_progress)
LottieAnimationView mLottieProgress;
@BindView(R.id.selectFile)
MorphingButton selectFileButton;
@BindView(R.id.invert)
MorphingButton invertPdfButton;
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;
@BindView(R.id.view_pdf)
Button mViewPdf;

@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootview = inflater.inflate(R.layout.fragment_invert_pdf, container, false);
ButterKnife.bind(this, rootview);
sheetBehavior = BottomSheetBehavior.from(layoutBottomSheet);
sheetBehavior.setBottomSheetCallback(new BottomSheetCallback(mUpArrow, isAdded()));
mLottieProgress.setVisibility(View.VISIBLE);
mBottomSheetUtils.populateBottomSheetWithPDFs(this);

resetValues();
return rootview;
}
@OnClick(R.id.viewFiles)
void onViewFilesClick(View view) {
mBottomSheetUtils.showHideSheet(sheetBehavior);
}

/**
* Displays file chooser intent
*/
@OnClick(R.id.selectFile)
public void showFileChooser() {
startActivityForResult(mFileUtils.getFileChooser(),
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()));
}


// Inverts colors in PDF
@OnClick(R.id.invert)
public void parse() {
new InvertPdf(mPath, this).execute();
}


private void resetValues() {
mPath = null;
mMorphButtonUtility.initializeButton(selectFileButton, invertPdfButton);
}

private void setTextAndActivateButtons(String path) {
mPath = path;
mMorphButtonUtility.setTextAndActivateButtons(path,
selectFileButton, invertPdfButton);
}

@Override
public void onPopulate(ArrayList<String> paths) {
if (paths == null || paths.size() == 0) {
mLayout.setVisibility(View.GONE);
} else {
// Init recycler view
mRecyclerViewFiles.setVisibility(View.VISIBLE);
MergeFilesAdapter mergeFilesAdapter = new MergeFilesAdapter(mActivity, paths, false, this);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(mActivity);
mRecyclerViewFiles.setLayoutManager(mLayoutManager);
mRecyclerViewFiles.setAdapter(mergeFilesAdapter);
mRecyclerViewFiles.addItemDecoration(new ViewFilesDividerItemDecoration(mActivity));
}
mLottieProgress.setVisibility(View.GONE);
}

@Override
public void onAttach(Context context) {
super.onAttach(context);
mActivity = (Activity) context;
mMorphButtonUtility = new MorphButtonUtility(mActivity);
mFileUtils = new FileUtils(mActivity);
mBottomSheetUtils = new BottomSheetUtils(mActivity);
}

@Override
public void onItemClick(String path) {
sheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
setTextAndActivateButtons(path);
}

@Override
public void onFileItemClick(String path) {
mFileUtils.openFile(path);
}

private void viewPdfButton(String path) {
mViewPdf.setVisibility(View.VISIBLE);
mViewPdf.setOnClickListener(v -> mFileUtils.openFile(path));
}

@Override
public void onPDFCreationStarted() {
mMaterialDialog = createAnimationDialog(mActivity);
mMaterialDialog.show();
}

@Override
public void onPDFCreated(boolean isNewPdfCreated, String path) {
mMaterialDialog.dismiss();
if (!isNewPdfCreated) {
showSnackbar(mActivity, R.string.snackbar_invert_unsuccessful);
//Hiding View PDF button
mViewPdf.setVisibility(View.GONE);
return;
}
new DatabaseHelper(mActivity).insertRecord(path, mActivity.getString(R.string.snackbar_invert_unsuccessful));
getSnackbarwithAction(mActivity, R.string.snackbar_pdfCreated)
.setAction(R.string.snackbar_viewAction, v -> mFileUtils.openFile(path)).show();
viewPdfButton(path);
resetValues();
}
}

124 changes: 124 additions & 0 deletions app/src/main/java/swati4star/createpdf/util/InvertPdf.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package swati4star.createpdf.util;

import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.os.ParcelFileDescriptor;

import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.GrayColor;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfGState;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;

import swati4star.createpdf.interfaces.OnPDFCreatedInterface;

import static android.os.ParcelFileDescriptor.MODE_READ_ONLY;
import static swati4star.createpdf.util.Constants.pdfExtension;

public class InvertPdf extends AsyncTask<Void, Void, Void> {
private String mPath;
private OnPDFCreatedInterface mOnPDFCreatedInterface;
private ArrayList<Bitmap> mBitmaps;
private StringBuilder mSequence;
private Boolean mIsNewPDFCreated;

public InvertPdf(String mPath, OnPDFCreatedInterface onPDFCreatedInterface) {
this.mPath = mPath;
mSequence = new StringBuilder();
mBitmaps = new ArrayList<>();
this.mOnPDFCreatedInterface = onPDFCreatedInterface;
}

@Override
protected void onPreExecute() {
super.onPreExecute();
mOnPDFCreatedInterface.onPDFCreationStarted();
mIsNewPDFCreated = false;
}


@Override
protected Void doInBackground(Void... voids) {
ParcelFileDescriptor fileDescriptor = null;
try {
if (mPath != null)
fileDescriptor = ParcelFileDescriptor.open(new File(mPath), MODE_READ_ONLY);
if (fileDescriptor != null) {
String outputPath = mPath.replace(".pdf", "_inverted" + pdfExtension);
if (createPDF(mPath, outputPath)) {
mPath = outputPath;
mIsNewPDFCreated = true;
}

}
} catch (IOException | SecurityException e) {
e.printStackTrace();
mIsNewPDFCreated = false;
}

return null;
}
/**
* invokes invert method passing stamper as parameter
*
* @param mPath original file path
* @param outputPath output file path
*/
private boolean createPDF(String mPath, String outputPath) {

try {
PdfReader reader = new PdfReader(mPath);
OutputStream os = new FileOutputStream(outputPath);
PdfStamper stamper = new PdfStamper(reader, os);
invert(stamper);
stamper.close();
os.close();
return true;
} catch (Exception er) {
er.printStackTrace();
return false;
}

}
void invert(PdfStamper stamper) {
for (int i = stamper.getReader().getNumberOfPages(); i > 0; i--) {
invertPage(stamper, i);
}
}

/**
* Draws a white rectangle in blend mode DIFFERENCE
* over the page and then draws a white rectangle
* under the page for compatibility for all acrobat versions.
*/
void invertPage(PdfStamper stamper, int page) {
Rectangle rect = stamper.getReader().getPageSize(page);
PdfContentByte cb = stamper.getOverContent(page);
PdfGState gs = new PdfGState();
gs.setBlendMode(PdfGState.BM_DIFFERENCE);
cb.setGState(gs);
cb.setColorFill(new GrayColor(1.0f));
cb.rectangle(rect.getLeft(), rect.getBottom(), rect.getWidth(), rect.getHeight());
cb.fill();

cb = stamper.getUnderContent(page);
cb.setColorFill(new GrayColor(1.0f));
cb.rectangle(rect.getLeft(), rect.getBottom(), rect.getWidth(), rect.getHeight());
cb.fill();
}
@Override
protected void onPostExecute(Void avoid) {
// Execution of result of Long time consuming operation
super.onPostExecute(avoid);
mOnPDFCreatedInterface.onPDFCreated(mIsNewPDFCreated, mPath);
}


}
4 changes: 4 additions & 0 deletions app/src/main/res/drawable/ic_invert_color_24dp.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<vector android:height="24dp" android:viewportHeight="1024"
android:viewportWidth="1024" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M512,64C264.6,64 64,264.6 64,512c0,247.4 200.6,448 448,448 247.4,0 448,-200.6 448,-448C960,264.6 759.4,64 512,64zM783.6,783.6C711,856 614,896 512,896L512,128c102,0 199,40 271.6,112.4C856,313 896,409.4 896,512 896,614.6 856,711 783.6,783.6z"/>
</vector>
8 changes: 8 additions & 0 deletions app/src/main/res/layout/fragment_home.xml
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,14 @@
android:layout_height="wrap_content"
android:orientation="horizontal">

<swati4star.createpdf.customviews.MyCardView
android:id="@+id/invert_pdf"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1.0"
app:option_icon="@drawable/ic_invert_color_24dp"
app:option_text="@string/invert_pdf" />

<swati4star.createpdf.customviews.MyCardView
android:id="@+id/compress_pdf"
android:layout_width="0dp"
Expand Down
Loading

0 comments on commit db7fb30

Please sign in to comment.