Skip to content

Commit 64d5fd0

Browse files
authored
Merge pull request #110 from aspose-pdf-cloud/pdfcloud-5010-added-snippets-rotate-resize-crop
PDFCLOUD-5010: added snippets rotate-resize-crop
2 parents 7a1c783 + 0c40b9f commit 64d5fd0

File tree

5 files changed

+278
-0
lines changed

5 files changed

+278
-0
lines changed
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
import os
2+
import shutil
3+
import json
4+
import logging
5+
from pathlib import Path
6+
from asposepdfcloud import ApiClient, PdfApi
7+
from asposepdfcloud import AsposeResponse, DocumentPageResponse, Page, Rectangle, DocumentConfig, DocumentProperties, DocumentProperty, DisplayProperties, DefaultPageConfig
8+
from asposepdfcloud import ImageStamp, HorizontalAlignment, VerticalAlignment, Rotation
9+
10+
# Configure logging
11+
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
12+
13+
class Config:
14+
"""Configuration parameters."""
15+
CREDENTIALS_FILE = Path(r"credentials.json")
16+
LOCAL_FOLDER = Path(r"C:\Samples")
17+
REMOTE_FOLDER = "Your_Temp_Pdf_Cloud"
18+
PDF_DOCUMENT = "sample.pdf"
19+
PDF_OUTPUT = "output_sample.pdf"
20+
21+
ROTATE_PAGES_ANGLE = Rotation.ON90
22+
ROTATE_PAGES = "1-3"
23+
24+
CROP_PAGE_TEMP_FILE = "sammple_temp_file.png"
25+
CROP_LOCAL_RESULT_DOCUMENT_NAME = "output_sample.pdf"
26+
CROP_PAGE_NUMBER = 3
27+
CROP_HEIGHT = 400
28+
CROP_WIDTH = 300
29+
CROP_LLX = 100
30+
CROP_LLY = 200
31+
32+
RESIZE_PDF_HTML_FILE = "sammple_temp_file.html"
33+
RESIZE_RESULT_DOCUMENT_NAME = "output_sample.pdf"
34+
RESIZE_PAGE_NUMBER = 2
35+
RESIZE_NEW_PAGE_WIDTH = 1000
36+
RESIZE_NEW_PAGE_HEIGHT = 500
37+
38+
CROP_PAGE_WIDTH = 0
39+
CROP_PAGE_HEIGHT = 0
40+
41+
42+
class PdfChangeLayoutHelper:
43+
def __init__(self, credentials_file: Path):
44+
self.pdf_api = None
45+
self._init_api(credentials_file)
46+
47+
def _init_api(self, credentials_file: Path):
48+
"""Initialize the API client."""
49+
try:
50+
with credentials_file.open("r", encoding="utf-8") as file:
51+
credentials = json.load(file)
52+
api_key, app_id = credentials.get("key"), credentials.get("id")
53+
if not api_key or not app_id:
54+
raise ValueError("Error: Missing API keys in the credentials file.")
55+
self.pdf_api = PdfApi(ApiClient(api_key, app_id))
56+
except (FileNotFoundError, json.JSONDecodeError, ValueError) as e:
57+
logging.error(f"Failed to load credentials: {e}")
58+
59+
def uploadFile(self, fileName: str, localFolder: Path, remoteFolder: str):
60+
""" Upload a local fileName to the Aspose Cloud server. """
61+
if self.pdf_api:
62+
file_path = localFolder / fileName
63+
try:
64+
self.pdf_api.upload_file(os.path.join(remoteFolder, fileName), file_path)
65+
logging.info(f"upload_file(): File '{fileName}' uploaded successfully.")
66+
except Exception as e:
67+
logging.error(f"upload_document(): Failed to upload file: {e}")
68+
69+
70+
def downloadFile(self, document: str, outputDocument: str, localFolder: Path, remoteFolder: Path, output_prefix: str):
71+
"""Download the processed PDF document from the Aspose Cloud server."""
72+
if self.pdf_api:
73+
try:
74+
temp_file = self.pdf_api.download_file(str(remoteFolder) + '/' + document)
75+
local_path = localFolder / ( output_prefix + outputDocument )
76+
shutil.move(temp_file, str(local_path))
77+
logging.info(f"download_result(): File successfully downloaded: {local_path}")
78+
except Exception as e:
79+
logging.error(f"download_result(): Failed to download file: {e}")
80+
81+
def getPageInfo(self, document: str, pageNumber: int, tempFolder: str):
82+
if self.pdf_api:
83+
args = {
84+
"folder": tempFolder,
85+
}
86+
response: DocumentPageResponse = self.pdf_api.get_page(document, pageNumber, **args)
87+
88+
if response.code == 200:
89+
logging.info(f"page {pageNumber} => id: '{response.page.id}', lLx: '{response.page.rectangle.llx}', lLY: '{response.page.rectangle.lly}', uRX: '{response.page.rectangle.urx}', uRY: '{response.page.rectangle.ury}'")
90+
Config.CROP_PAGE_HEIGHT = response.page.rectangle.ury - response.page.rectangle.lly
91+
Config.CROP_PAGE_WIDTH = response.page.rectangle.urx - response.page.rectangle.llx
92+
else:
93+
logging.error("Unexpected error : can't get pages!!!")
94+
95+
def extractPdfPage(self, document: str, pageNumber: int, width: int, height: int, localFolder: str, tempFolder: str):
96+
if self.pdf_api:
97+
args = {
98+
"folder": tempFolder,
99+
"width": int(width),
100+
"height": int(height),
101+
}
102+
103+
response = self.pdf_api.get_page_convert_to_png(document, pageNumber, **args)
104+
imageFile = document + ".png"
105+
imagePath = localFolder / imageFile
106+
shutil.move(response, str(imagePath))
107+
108+
self.uploadFile(imageFile, localFolder, tempFolder)
109+
110+
logging.info(f"Page #{pageNumber} extracted as image.")
111+
return imageFile
112+
113+
def createDocument(self, newDocumentName: str, width: int, height: int, tempFolder: Path):
114+
""" Create PDF document with required properties. """
115+
if self.pdf_api:
116+
args = {
117+
"folder" : str(tempFolder)
118+
}
119+
120+
document_config = DocumentConfig(
121+
pages_count = 1,
122+
document_properties=DocumentProperties(
123+
list=[
124+
DocumentProperty(
125+
built_in=False,
126+
name='prop1',
127+
value='Val1',
128+
)
129+
]),
130+
display_properties=DisplayProperties(
131+
center_window = True,
132+
hide_menu_bar = True,
133+
),
134+
default_page_config=DefaultPageConfig(
135+
height = height,
136+
width = width
137+
),
138+
)
139+
response = self.pdf_api.post_create_document(newDocumentName, document_config, **args)
140+
logging.info(f"Document #{newDocumentName} created.")
141+
return response
142+
143+
def insertPageAsImage(self, document: str, imageFileValue: str, llx: int, lly: int, tempFolder: str):
144+
if self.pdf_api:
145+
args = {
146+
"folder" : str(tempFolder)
147+
}
148+
149+
image_stamp: ImageStamp = ImageStamp(
150+
background = True,
151+
horizontal_alignment = HorizontalAlignment.NONE,
152+
vertical_alignment = VerticalAlignment.NONE,
153+
rotate = Rotation.NONE,
154+
rotate_angle = 0,
155+
opacity = 1,
156+
x_indent = -llx,
157+
y_indent = -lly,
158+
zoom = 1,
159+
file_name = os.path.join(tempFolder, imageFileValue)
160+
)
161+
162+
try:
163+
responseImageStamp: AsposeResponse = self.pdf_api.post_page_image_stamps(document, 1, [ image_stamp ], **args)
164+
if responseImageStamp.code != 200:
165+
logging.info( "Unexpected error on inserting image to the document!")
166+
else:
167+
return responseImageStamp
168+
169+
except Exception as e:
170+
logging.error(f"add_document_stamps(): Failed to insert image: {e}")
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from change_layout_helper import PdfChangeLayoutHelper, Config
2+
from rotate_documents_pages import PdfRotatePages
3+
from resize_document_all_pages import PdfResizePages
4+
from crop_document_page import PdfCropPages
5+
6+
if __name__ == "__main__":
7+
helper = PdfChangeLayoutHelper(Config.CREDENTIALS_FILE)
8+
9+
crop = PdfCropPages(helper.pdf_api, helper)
10+
crop.cropDocumentPage(Config.PDF_DOCUMENT, Config.CROP_PAGE_NUMBER, Config.CROP_LLX, Config.CROP_LLY, Config.CROP_WIDTH, Config.CROP_HEIGHT, Config.CROP_LOCAL_RESULT_DOCUMENT_NAME, Config.LOCAL_FOLDER, Config.REMOTE_FOLDER)
11+
12+
resize = PdfResizePages(helper.pdf_api, helper)
13+
resize.resizeAllPages(Config.PDF_DOCUMENT, Config.RESIZE_PDF_HTML_FILE, Config.RESIZE_NEW_PAGE_WIDTH, Config.RESIZE_NEW_PAGE_HEIGHT, Config.RESIZE_RESULT_DOCUMENT_NAME, Config.LOCAL_FOLDER, Config.REMOTE_FOLDER)
14+
15+
rotate = PdfRotatePages(helper.pdf_api, helper)
16+
rotate.rotateDocumentPages(Config.PDF_DOCUMENT, Config.PDF_OUTPUT, Config.ROTATE_PAGES_ANGLE, Config.ROTATE_PAGES)
17+
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import os
2+
import logging
3+
from pathlib import Path
4+
from asposepdfcloud import PdfApi, AsposeResponse, DocumentResponse
5+
from change_layout_helper import PdfChangeLayoutHelper, Config
6+
7+
class PdfCropPages:
8+
def __init__(self, pdf_api: PdfApi, helper: PdfChangeLayoutHelper):
9+
self.pdfApi = pdf_api
10+
self.helper = helper
11+
12+
def cropDocumentPage(self, documentName: str, pageNumber: int, llx: int, lly: int, width: int, height: int, outputDocument: str, localFolder: str, tempFolder: str):
13+
self.helper.uploadFile(documentName, localFolder, tempFolder)
14+
15+
self.helper.getPageInfo(documentName, pageNumber, tempFolder)
16+
17+
imageFile = self.helper.extractPdfPage(documentName, pageNumber, Config.CROP_PAGE_WIDTH, Config.CROP_PAGE_HEIGHT, localFolder, tempFolder)
18+
newPdf: DocumentResponse = self.helper.createDocument(outputDocument, width, height, tempFolder)
19+
if newPdf.code != 200:
20+
logging.error("cropDocumentPage(): Failed to create new PDF document!")
21+
else:
22+
response: AsposeResponse = self.helper.insertPageAsImage(outputDocument, imageFile, llx, lly, tempFolder)
23+
if response.code != 200:
24+
logging.error("cropDocumentPage(): Can't crop pdf document page!")
25+
else:
26+
logging.info("cropDocumentPage(): Page successfully cropped.")
27+
self.helper.downloadFile(outputDocument, outputDocument, localFolder, tempFolder, "cropped_")
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import os
2+
import logging
3+
from pathlib import Path
4+
from asposepdfcloud import PdfApi, AsposeResponse, HtmlDocumentType, OutputFormat
5+
from change_layout_helper import PdfChangeLayoutHelper
6+
7+
class PdfResizePages:
8+
def __init__(self, pdf_api: PdfApi, helper: PdfChangeLayoutHelper):
9+
self.pdfApi = pdf_api
10+
self.helper = helper
11+
12+
def resizeAllPages(self, documentName: str, htmlTempDoc: str, width: int, height: int, outputDocumentName: str, localFolder: Path, tempFolder: str):
13+
self.helper.uploadFile(documentName, localFolder, tempFolder)
14+
15+
htmlTempPath = os.path.join(tempFolder, htmlTempDoc)
16+
args = {
17+
"folder": tempFolder,
18+
"document_type": HtmlDocumentType.XHTML,
19+
"output_format": OutputFormat.FOLDER,
20+
}
21+
22+
response: AsposeResponse = self.pdfApi.put_pdf_in_storage_to_html(documentName, htmlTempPath, **args)
23+
if response.code != 200:
24+
logging.error("resizeAllPages(): Unexpected error in PDF to HTML conversion!")
25+
else:
26+
logging.info("resizeAllPages(): Successfully convert PDF to HTML!")
27+
28+
args2 = {
29+
"dst_folder": tempFolder,
30+
"html_file_name": htmlTempDoc,
31+
"height": height,
32+
"width": width,
33+
}
34+
35+
response: AsposeResponse = self.pdfApi.put_html_in_storage_to_pdf(outputDocumentName, htmlTempPath, **args2)
36+
if response.code != 200:
37+
logging.error("resizeAllPages(): Unexpected error in HTML to PDF conversion!")
38+
else:
39+
logging.info("resizeAllPages(): Successfully convert HTML tot PDF!")
40+
self.helper.downloadFile(outputDocumentName, outputDocumentName, localFolder, tempFolder, "resized_")
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import logging
2+
from pathlib import Path
3+
from asposepdfcloud import PdfApi, AsposeResponse
4+
from change_layout_helper import PdfChangeLayoutHelper, Config
5+
6+
class PdfRotatePages:
7+
def __init__(self, pdf_api: PdfApi, helper: PdfChangeLayoutHelper):
8+
self.pdfApi = pdf_api
9+
self.helper = helper
10+
11+
def rotateDocumentPages(self, documentName: str, outputDocumentName: str, rotateAngle: str, pages: str):
12+
self.helper.uploadFile(documentName, Config.LOCAL_FOLDER, Config.REMOTE_FOLDER)
13+
14+
args = {
15+
"folder": Config.REMOTE_FOLDER,
16+
}
17+
18+
response: AsposeResponse = self.pdfApi.post_document_pages_rotate(documentName, rotateAngle, pages, **args)
19+
20+
if response.code != 200:
21+
logging.error("rotateDocumentPages(): Unexpected error!")
22+
else:
23+
logging.info(f"rotateDocumentPages(): Pages '{pages}' successfully rotated!")
24+
self.helper.downloadFile(documentName, outputDocumentName, Config.LOCAL_FOLDER, Config.REMOTE_FOLDER, "rotated_")

0 commit comments

Comments
 (0)