using ComPDFKit.Import; using ComPDFKit.PDFAnnotation; using ComPDFKit.PDFPage; using ComPDFKit.Tool.Help; using System; using System.IO; using System.Windows; using System.Windows.Media; using System.Windows.Media.Imaging; namespace ComPDFKit.Tool.UndoManger { public class StampAnnotHistory:AnnotHistory { public override int GetAnnotIndex() { if (CurrentParam != null) { return CurrentParam.AnnotIndex; } return base.GetAnnotIndex(); } public override int GetPageIndex() { if (CurrentParam != null) { return CurrentParam.PageIndex; } return base.GetPageIndex(); } public override void SetAnnotIndex(int newIndex) { if (CurrentParam != null) { CurrentParam.AnnotIndex = newIndex; } if (PreviousParam != null) { PreviousParam.AnnotIndex = newIndex; } } internal override bool Add() { StampParam currentParam = CurrentParam as StampParam; if (currentParam == null || PDFDoc == null || !PDFDoc.IsValid()) { return false; } if(currentParam.StampType==C_STAMP_TYPE.UNKNOWN_STAMP) { return false; } if(currentParam.StampType==C_STAMP_TYPE.IMAGE_STAMP && currentParam.ImageStream==null) { return false; } CPDFPage pdfPage = PDFDoc.PageAtIndex(currentParam.PageIndex); CPDFStampAnnotation stampAnnot = pdfPage?.CreateAnnot(C_ANNOTATION_TYPE.C_ANNOTATION_STAMP) as CPDFStampAnnotation; if (stampAnnot != null) { int annotIndex = pdfPage.GetAnnotCount() - 1; switch(currentParam.StampType) { case C_STAMP_TYPE.STANDARD_STAMP: { string stampText = currentParam.StampText; if (stampText == null) { stampText = string.Empty; } stampAnnot.SetStandardStamp(stampText, pdfPage.Rotation); //stampAnnot.SetRect(currentParam.ClientRect); } break; case C_STAMP_TYPE.TEXT_STAMP: { string dateText = currentParam.DateText; string stampText = currentParam.StampText; if (dateText == null) { dateText = string.Empty; } if (stampText == null) { stampText = string.Empty; } stampAnnot.SetTextStamp( stampText, dateText, currentParam.TextStampShape, currentParam.TextStampColor, pdfPage.Rotation); //stampAnnot.SetRect(currentParam.ClientRect); } break; case C_STAMP_TYPE.IMAGE_STAMP: { byte[] imageData = null; int imageWidth = 0; int imageHeight = 0; PDFHelp.ImageStreamToByte(currentParam.ImageStream, ref imageData, ref imageWidth, ref imageHeight); if (imageData != null && imageWidth > 0 && imageHeight > 0) { //stampAnnot.SetRect(currentParam.ClientRect); stampAnnot.SetImageStamp( imageData, imageWidth, imageHeight, pdfPage.Rotation); } } break; default: break; } stampAnnot.SetSourceRect(currentParam.SourceRect); stampAnnot.AnnotationRotator.SetRotation(currentParam.Rotation); stampAnnot.SetTransparency((byte)currentParam.Transparency); string imagePath = string.Empty; if (GetAnnotOpacityImage(stampAnnot, currentParam.Transparency / 255.0, 5, out imagePath) && File.Exists(imagePath)) { stampAnnot.SetImageStamp(imagePath, string.Empty); File.Delete(imagePath); } if (!string.IsNullOrEmpty(currentParam.Author)) { stampAnnot.SetAuthor(currentParam.Author); } if (!string.IsNullOrEmpty(currentParam.Content)) { stampAnnot.SetContent(currentParam.Content); } stampAnnot.SetIsLocked(currentParam.Locked); stampAnnot.SetCreationDate(PDFHelp.GetCurrentPdfTime()); stampAnnot.UpdateAp(); stampAnnot.ReleaseAnnot(); if (currentParam != null) { currentParam.AnnotIndex = annotIndex; } if (PreviousParam != null) { PreviousParam.AnnotIndex = annotIndex; } return true; } return false; } internal override bool Update(bool isUndo) { if (CurrentParam as StampParam == null || PreviousParam as StampParam == null) { return false; } if (MakeAnnotValid(CurrentParam)) { CPDFStampAnnotation stampAnnot = Annot as CPDFStampAnnotation; if (stampAnnot == null || !stampAnnot.IsValid()) { return false; } StampParam updateParam = (isUndo ? PreviousParam : CurrentParam) as StampParam; StampParam checkParam = (isUndo ? CurrentParam : PreviousParam) as StampParam; if (updateParam.Clockwise!=0) { string imagePath = string.Empty; bool clockwise = updateParam.Clockwise== 1 ? true : false; if(isUndo) { clockwise=!clockwise; } if (GetAnnotRotateImage(stampAnnot, clockwise, 5, out imagePath) && File.Exists(imagePath)) { CRect rawRect = stampAnnot.GetRect(); Point centerPos = new Point(rawRect.left + rawRect.width() / 2, rawRect.top + rawRect.height() / 2); Rect saveRect = new Rect(centerPos.X - rawRect.height() / 2, centerPos.Y - rawRect.width() / 2, rawRect.height(), rawRect.width()); stampAnnot.SetRect(new CRect((float)saveRect.Left, (float)saveRect.Bottom, (float)saveRect.Right, (float)saveRect.Top)); stampAnnot.SetImageStamp(imagePath, string.Empty); File.Delete(imagePath); } } if (updateParam.Transparency != checkParam.Transparency) { stampAnnot.SetTransparency((byte)updateParam.Transparency); string imagePath = string.Empty; if (GetAnnotOpacityImage(stampAnnot, updateParam.Transparency/255.0, 5, out imagePath) && File.Exists(imagePath)) { stampAnnot.SetImageStamp(imagePath, string.Empty); File.Delete(imagePath); } } if (!updateParam.SourceRect.Equals(checkParam.SourceRect)) { stampAnnot.SetSourceRect(updateParam.SourceRect); stampAnnot.AnnotationRotator.SetRotation(updateParam.Rotation); } if (updateParam.Rotation != checkParam.Rotation) { stampAnnot.AnnotationRotator.SetRotation(updateParam.Rotation); } if (updateParam.Author != checkParam.Author) { stampAnnot.SetAuthor(updateParam.Author); } if (updateParam.Content != checkParam.Content) { stampAnnot.SetContent(updateParam.Content); } if (updateParam.Locked != checkParam.Locked) { stampAnnot.SetIsLocked(updateParam.Locked); } stampAnnot.SetModifyDate(PDFHelp.GetCurrentPdfTime()); stampAnnot.UpdateAp(); return true; } return false; } internal override bool Remove() { if (MakeAnnotValid(CurrentParam)) { Annot.RemoveAnnot(); return true; } return false; } private bool GetAnnotRotateImage(CPDFStampAnnotation annot, bool clockwise, double zoom, out string imagePath) { imagePath = string.Empty; if (annot == null || annot.IsValid() == false) { return false; } try { double opacity = annot.GetTransparency() / 255.0; CRect rawRect = annot.GetRect(); Rect drawRect = new Rect(0, 0, (int)(rawRect.width() * 96.0 / 72.0 * zoom), (int)(rawRect.height() * 96.0 / 72.0 * zoom)); byte[] imageData = new byte[(int)drawRect.Width * (int)drawRect.Height * 4]; annot.RenderAnnot((int)drawRect.Width, (int)drawRect.Height, imageData); int stride = ((int)drawRect.Width) * 4; for (int i = 0; i < (int)(drawRect.Height); i++) { for (int j = 0; j < (int)(drawRect.Width); j++) { byte b = imageData[i * stride + j * 4]; byte g = imageData[i * stride + j * 4 + 1]; byte r = imageData[i * stride + j * 4 + 2]; byte a = imageData[i * stride + j * 4 + 3]; if (a == 0 && b == 255 && g == 255 && r == 255) { continue; } if (a == 0 && b == 0 && g == 0 && r == 0) { continue; } imageData[i * stride + j * 4 + 3] = (byte)(opacity * 255); } } WriteableBitmap writeImage = new WriteableBitmap((int)drawRect.Width, (int)drawRect.Height, 96, 96, PixelFormats.Bgra32, null); writeImage.WritePixels(new Int32Rect(0, 0, (int)drawRect.Width, (int)drawRect.Height), imageData, ((int)drawRect.Width) * 4, 0); RotateTransform rotateTransform = new RotateTransform(); rotateTransform.Angle = clockwise ? 90 : -90; rotateTransform.CenterX = drawRect.Width / 2; rotateTransform.CenterY = drawRect.Height / 2; TranslateTransform translateTransform = new TranslateTransform(); if (clockwise == false) { translateTransform.X = -(drawRect.Width - drawRect.Height) / 2; translateTransform.Y = -(drawRect.Width - drawRect.Height) / 2; } else { translateTransform.X = (drawRect.Width - drawRect.Height) / 2; translateTransform.Y = (drawRect.Width - drawRect.Height) / 2; } DrawingVisual drawVisual = new DrawingVisual(); DrawingContext drawDC = drawVisual.RenderOpen(); drawDC.PushTransform(rotateTransform); drawDC.PushTransform(translateTransform); drawDC.DrawImage(writeImage, new Rect(0, 0, writeImage.Width, writeImage.Height)); drawDC.Pop(); drawDC.Pop(); drawDC.Close(); RenderTargetBitmap renderBitmap = new RenderTargetBitmap((int)drawRect.Height, (int)drawRect.Width, 96, 96, PixelFormats.Pbgra32); renderBitmap.Render(drawVisual); string tempPath = System.IO.Path.Combine(System.IO.Path.GetTempPath(), Guid.NewGuid().ToString()); PngBitmapEncoder pngEncoder = new PngBitmapEncoder(); using (FileStream fs = File.Create(tempPath)) { pngEncoder.Frames.Add(BitmapFrame.Create(renderBitmap)); pngEncoder.Save(fs); } imagePath = tempPath; return true; } catch (Exception ex) { } return false; } private bool GetAnnotOpacityImage(CPDFStampAnnotation annot, double opacity, double zoom, out string imagePath) { imagePath = string.Empty; if (annot == null || annot.IsValid() == false) { return false; } try { CRect rawRect = annot.GetRect(); Rect drawRect = new Rect(0, 0, (int)(rawRect.width() * 96.0 / 72.0 * zoom), (int)(rawRect.height() * 96.0 / 72.0 * zoom)); byte[] imageData = new byte[(int)drawRect.Width * (int)drawRect.Height * 4]; annot.RenderAnnot((int)drawRect.Width, (int)drawRect.Height, imageData); int stride = ((int)drawRect.Width) * 4; for (int i = 0; i < (int)(drawRect.Height); i++) { for (int j = 0; j < (int)(drawRect.Width); j++) { byte b = imageData[i * stride + j * 4]; byte g = imageData[i * stride + j * 4 + 1]; byte r = imageData[i * stride + j * 4 + 2]; byte a = imageData[i * stride + j * 4 + 3]; if (a == 0 && b == 255 && g == 255 && r == 255) { continue; } if (a == 0 && b == 0 && g == 0 && r == 0) { continue; } imageData[i * stride + j * 4 + 3] = (byte)(opacity * 255); } } WriteableBitmap writeImage = new WriteableBitmap((int)drawRect.Width, (int)drawRect.Height, 96, 96, PixelFormats.Bgra32, null); writeImage.WritePixels(new Int32Rect(0, 0, (int)drawRect.Width, (int)drawRect.Height), imageData, stride, 0); string tempPath = System.IO.Path.Combine(System.IO.Path.GetTempPath(), Guid.NewGuid().ToString()); PngBitmapEncoder pngEncoder = new PngBitmapEncoder(); using (FileStream fs = File.Create(tempPath)) { pngEncoder.Frames.Add(BitmapFrame.Create(writeImage)); pngEncoder.Save(fs); } imagePath = tempPath; return true; } catch (Exception ex) { } return false; } } }