如何编辑/保存pdf多版本?

w6lpcovy  于 2021-06-29  发布在  Java
关注(0)|答案(0)|浏览(278)

关闭。这个问题需要更加突出重点。它目前不接受答案。
**想改进这个问题吗?**通过编辑这篇文章更新这个问题,使它只关注一个问题。

8天前关门了。
改进这个问题
如何在平板电脑设备上通过自由手写在pdf上绘制线条、文本?
我想保存编辑的pdf版本历史记录。因此,如果用户想查看历史,那么用户可以检查它。
我在这里面临着pdf质量问题:当我从版面生成pdf时,pdf质量太低。
我正在使用androidpdfviewer库打开pdf,并在pdfview上创建canvasdrawingview来绘制和删除。
活动\u drawing.xml:

<com.exmple.pdfdrawing.ZoomLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:visibility="visible"
    android:id="@+id/zoomLayout"
    android:layout_marginTop="30dp"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@id/tvTime"
    >

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/frameLayout"
        >

        <com.github.barteksc.pdfviewer.PDFView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/pdfView"
            android:clickable="false"
            />
        <com.example.pdfdrawing.CanvasDrawingView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:visibility="visible"
            android:id="@+id/drawingView"
            />

    </FrameLayout>

</ com.exmple.pdfdrawing.ZoomLayout>

zoom layout用于缩放pdfview和canvasdrawingview,这样我们就可以准确地在所需的位置写入/绘制。
zoomlayout.java文件:

public class ZoomLayout extends FrameLayout implements ScaleGestureDetector.OnScaleGestureListener {

    private enum Mode {
        NONE,
        DRAG,
        ZOOM
    }

    private static final String TAG = "ZoomLayout";
    private static final float MIN_ZOOM = 1.0f;
    private static final float MAX_ZOOM = 5.0f;

    private Mode mode = Mode.NONE;
    private float scale = 1.0f;
    private float lastScaleFactor = 0f;

    // Where the finger first  touches the screen
    private float startX = 0f;
    private float startY = 0f;

    // How much to translate the canvas
    private float dx = 0f;
    private float dy = 0f;
    private float prevDx = 0f;
    private float prevDy = 0f;

    public ZoomLayout(Context context) {
        super(context);
        init(context);
    }

    public ZoomLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public ZoomLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }

    private void init(Context context) {
        final ScaleGestureDetector scaleDetector = new ScaleGestureDetector(context, this);
        this.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) {
                    case MotionEvent.ACTION_DOWN:
                        Log.i(TAG, "DOWN");
                        if (scale > MIN_ZOOM) {
                            mode = Mode.DRAG;
                            startX = motionEvent.getX() - prevDx;
                            startY = motionEvent.getY() - prevDy;
                        }
                        break;
                    case MotionEvent.ACTION_MOVE:
                        if (mode == Mode.DRAG) {
                            dx = motionEvent.getX() - startX;
                            dy = motionEvent.getY() - startY;
                        }
                        break;
                    case MotionEvent.ACTION_POINTER_DOWN:
                        mode = Mode.ZOOM;
                        break;
                    case MotionEvent.ACTION_POINTER_UP:
                        mode = Mode.DRAG;
                        break;
                    case MotionEvent.ACTION_UP:
                        Log.i(TAG, "UP");
                        mode = Mode.NONE;
                        prevDx = dx;
                        prevDy = dy;
                        break;
                }
                scaleDetector.onTouchEvent(motionEvent);

                if ((mode == Mode.DRAG && scale >= MIN_ZOOM) || mode == Mode.ZOOM) {
                    getParent().requestDisallowInterceptTouchEvent(true);
                    float maxDx = (child().getWidth() - (child().getWidth() / scale)) / 2 * scale;
                    float maxDy = (child().getHeight() - (child().getHeight() / scale))/ 2 * scale;
                    dx = Math.min(Math.max(dx, -maxDx), maxDx);
                    dy = Math.min(Math.max(dy, -maxDy), maxDy);
                    Log.i(TAG, "Width: " + child().getWidth() + ", scale " + scale + ", dx " + dx
                            + ", max " + maxDx);
                    applyScaleAndTranslation();
                }

                return true;
            }
        });
    }

    // ScaleGestureDetector

    @Override
    public boolean onScaleBegin(ScaleGestureDetector scaleDetector) {
        Log.i(TAG, "onScaleBegin");
        return true;
    }

    @Override
    public boolean onScale(ScaleGestureDetector scaleDetector) {
        float scaleFactor = scaleDetector.getScaleFactor();
        Log.i(TAG, "onScale" + scaleFactor);
        if (lastScaleFactor == 0 || (Math.signum(scaleFactor) == Math.signum(lastScaleFactor))) {
            scale *= scaleFactor;
            scale = Math.max(MIN_ZOOM, Math.min(scale, MAX_ZOOM));
            lastScaleFactor = scaleFactor;
        } else {
            lastScaleFactor = 0;
        }
        return true;
    }

    @Override
    public void onScaleEnd(ScaleGestureDetector scaleDetector) {
        Log.i(TAG, "onScaleEnd");
    }

    private void applyScaleAndTranslation() {
        child().setScaleX(scale);
        child().setScaleY(scale);
        child().setTranslationX(dx);
        child().setTranslationY(dy);
    }

    public void resetLayout(){
        Log.d(TAG,"reset layout called");
        scale=1.0f;
        dx=0f;
        dy=0f;
        applyScaleAndTranslation();
    }

    private View child() {
        return getChildAt(0);
    }
}

canvasdrawingview.java:

public class CanvasDrawingView extends View {
    private Context context;
    private static final float STROKE_WIDTH = 2f;
    private static final float HALF_STROKE_WIDTH = STROKE_WIDTH / 2;

    private Path m_path = new Path();
    private float m_lastTouchX;
    private float m_lastTouchY;
    private final RectF m_dirtyRect = new RectF();
    private Paint m_paint = new Paint();

    private int currentColor;
    private  boolean eraserMode=false;
    private boolean brushMode=false;
    private boolean penMode=true;

    private boolean editMode=false;

    LinkedHashMap<Path, Paint> pathMap = new LinkedHashMap<>();
    public CanvasDrawingView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context=context;

        setLayerType(LAYER_TYPE_HARDWARE, null);
        currentColor=Color.RED;
        m_paint.setAntiAlias(true);
        m_paint.setColor(currentColor);
        m_paint.setStyle(Paint.Style.STROKE);
        m_paint.setStrokeJoin(Paint.Join.ROUND);
        m_paint.setStrokeWidth(STROKE_WIDTH);
        m_paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
        m_paint.setAntiAlias(true);
        m_paint.setDither(true);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        getParent().requestDisallowInterceptTouchEvent(true);
        if(pathMap!=null){
            for(Path p: pathMap.keySet()){
                canvas.drawPath(p,pathMap.get(p));
            }
        }
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if(editMode){
            float m_eventX = event.getX();
            float m_eventY = event.getY();
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    m_path=new Path();
                    Paint newPaint;
                    if(eraserMode){
                        newPaint= getEraserPaint();
                    } else if(brushMode){
                        newPaint= getBrushPaint();
                    }else{
                        newPaint = getPenPaint();
                    }
//                m_paint.setColor(currentColor);

                    pathMap.put(m_path,newPaint);

                    m_path.moveTo(m_eventX, m_eventY);
                    m_lastTouchX = m_eventX;
                    m_lastTouchY = m_eventY;
                    return true;
                case MotionEvent.ACTION_MOVE:
                case MotionEvent.ACTION_UP:
                    resetDirtyRect(m_eventX, m_eventY);
                    int historySize = event.getHistorySize();
                    for (int i = 0; i < historySize; i++) {
                        float historicalX = event.getHistoricalX(i);
                        float historicalY = event.getHistoricalY(i);
                        expandDirtyRect(historicalX, historicalY);
                        m_path.lineTo(historicalX, historicalY);
                    }
                    m_path.lineTo(m_eventX, m_eventY);
//                m_path= new Path();
                    break;
                default:
                    return false;
            }
            invalidate((int) (m_dirtyRect.left - HALF_STROKE_WIDTH),
                    (int) (m_dirtyRect.top - HALF_STROKE_WIDTH),
                    (int) (m_dirtyRect.right + HALF_STROKE_WIDTH),
                    (int) (m_dirtyRect.bottom + HALF_STROKE_WIDTH));
            m_lastTouchX = m_eventX;
            m_lastTouchY = m_eventY;
            return true;
        } else{
            return false;
        }
    }

    public void setEditMode(boolean editMode) {
        this.editMode = editMode;
    }

    private Paint getEraserPaint() {
        Paint erasePaint = new Paint();
        erasePaint.setAntiAlias(true);
//        erasePaint.setColor(getResources().getColor(android.R.color.transparent));
        erasePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        erasePaint.setColor(Color.WHITE);
        erasePaint.setStyle(Paint.Style.STROKE);
        erasePaint.setStrokeJoin(Paint.Join.ROUND);
        erasePaint.setStrokeWidth(6f);
        erasePaint.setAntiAlias(true);
        erasePaint.setDither(true);
        return erasePaint;
    }

    private Paint getPenPaint() {
        Paint penPaint = new Paint();
        penPaint.setAntiAlias(true);
        penPaint.setColor(currentColor);
        penPaint.setStyle(Paint.Style.STROKE);
        penPaint.setStrokeJoin(Paint.Join.ROUND);
        penPaint.setStrokeWidth(STROKE_WIDTH);
        penPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
        penPaint.setAntiAlias(true);
        penPaint.setDither(true);
        return penPaint;
    }

    private Paint getBrushPaint() {
        Paint brushPaint = new Paint();
        brushPaint.setAntiAlias(true);
        brushPaint.setColor(currentColor);
        brushPaint.setStyle(Paint.Style.STROKE);
        brushPaint.setStrokeJoin(Paint.Join.ROUND);
        brushPaint.setStrokeWidth(15f);
        brushPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
        brushPaint.setAntiAlias(true);
        brushPaint.setDither(true);
        return brushPaint;
    }

    private void expandDirtyRect(float historicalX, float historicalY) {
        if (historicalX < m_dirtyRect.left) {
            m_dirtyRect.left = historicalX;
        } else if (historicalX > m_dirtyRect.right) {
            m_dirtyRect.right = historicalX;
        }
        if (historicalY < m_dirtyRect.top) {
            m_dirtyRect.top = historicalY;
        } else if (historicalY > m_dirtyRect.bottom) {
            m_dirtyRect.bottom = historicalY;
        }
    }

    private void resetDirtyRect(float eventX, float eventY) {
        m_dirtyRect.left = Math.min(m_lastTouchX, eventX);
        m_dirtyRect.right = Math.max(m_lastTouchX, eventX);
        m_dirtyRect.top = Math.min(m_lastTouchY, eventY);
        m_dirtyRect.bottom = Math.max(m_lastTouchY, eventY);
    }

    public void setPaintColor(String color){
        m_paint=null;
        m_paint=new Paint();
        m_paint.setStyle(Paint.Style.STROKE);
        m_paint.setStrokeJoin(Paint.Join.ROUND);
        m_paint.setStrokeWidth(STROKE_WIDTH);
        m_paint.setColor(Color.parseColor(color));
            }

    public void setCurrentColor(int color){
        currentColor=color;
    }

    public void setEraserMode(boolean eraserMode){
        this.eraserMode=eraserMode;
    }

    public void setBrushMode(boolean brushMode){
        this.brushMode=brushMode;
    }

    public void setPenMode(boolean penMode){
        this.penMode=penMode;
    }
}

现在,当我使用以下代码从framelayout生成pdf时,pdf质量太低(可能取决于设备分辨率):
drawingactivity.java文件:

public void saveToPDF(){

    FrameLayout contentView=(FrameLayout) findViewById(R.id.frameLayout);
    float orginalPDFHeight= contentView.getHeight();
float orginalPDFWidth= contentView.getWidth();

PdfDocument pdfDocument = new PdfDocument();
PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder((int)orginalPDFWidth,(int) orginalPDFHeight,0).create();

PdfDocument.Page page = pdfDocument.startPage(pageInfo);

Canvas pageCanvas = page.getCanvas();
pageCanvas.scale(1f,1f);
contentView.draw(pageCanvas);
pdfDocument.finishPage(page);
File applicationPath = getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS);
String targetPdf = applicationPath+"/test.pdf";
File filePath = new File(targetPdf);
try {
            pdfDocument.writeTo(new FileOutputStream(filePath));
            Toast.makeText(this, "Done", Toast.LENGTH_LONG).show();
        } catch (IOException e) {
                        Toast.makeText(this, "Something wrong: " + e.toString(),  Toast.LENGTH_LONG).show();
        }
                pdfDocument.close();

}

这里有什么解决办法?另外,指导我,如果有任何其他方式做,非常感谢它。提前谢谢。
pdf质量:
原始pdf:https://drive.google.com/file/d/1dnfgq1qjdbslnzo_j_ds8ugloeuu2jwl/view?usp=sharing
版本1 pdf:https://drive.google.com/file/d/19doz4ywygit1r488elvffdgassu5lrot/view?usp=sharing

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题