Skip to content

Commit d663eec

Browse files
fix: added the fix for rotated pages (#90)
Signed-off-by: Peter Staar <[email protected]>
1 parent c8d224c commit d663eec

16 files changed

+10140
-2
lines changed

src/v2/pdf_decoders/page.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ namespace pdflib
4242

4343
void decode_annots();
4444

45+
void rotate_contents();
46+
4547
void sanitise_contents(std::string page_boundary);
4648

4749
private:
@@ -155,6 +157,8 @@ namespace pdflib
155157
decode_contents();
156158

157159
decode_annots();
160+
161+
rotate_contents();
158162

159163
sanitise_contents(page_boundary);
160164

@@ -429,6 +433,31 @@ namespace pdflib
429433
timings[__FUNCTION__] = timer.get_time();
430434
}
431435

436+
void pdf_decoder<PAGE>::rotate_contents()
437+
{
438+
LOG_S(INFO) << __FUNCTION__;
439+
440+
if(page_dimension.get_angle()==0)
441+
{
442+
return;
443+
}
444+
445+
int angle = page_dimension.get_angle();
446+
447+
if((angle%90)!=0)
448+
{
449+
LOG_S(ERROR) << "the /Rotate angle should be a multiple of 90 ...";
450+
}
451+
452+
// see Table 30
453+
LOG_S(WARNING) << "rotating contents clock-wise with angle: " << angle;
454+
455+
std::pair<double, double> delta = page_dimension.rotate(angle);
456+
page_cells.rotate(angle, delta);
457+
page_lines.rotate(angle, delta);
458+
page_images.rotate(angle, delta);
459+
}
460+
432461
void pdf_decoder<PAGE>::sanitise_contents(std::string page_boundary)
433462
{
434463
LOG_S(INFO) << __FUNCTION__;

src/v2/pdf_resources/page_cell.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ namespace pdflib
1717
nlohmann::json get();
1818
bool init_from(nlohmann::json& data);
1919

20+
void rotate(int angle, std::pair<double, double> delta);
21+
2022
public:
2123

2224
static std::vector<std::string> header;
@@ -119,6 +121,25 @@ namespace pdflib
119121
"widget"
120122
};
121123

124+
void pdf_resource<PAGE_CELL>::rotate(int angle, std::pair<double, double> delta)
125+
{
126+
utils::values::rotate_inplace(angle, x0, y0);
127+
utils::values::rotate_inplace(angle, x1, y1);
128+
129+
utils::values::rotate_inplace(angle, r_x0, r_y0);
130+
utils::values::rotate_inplace(angle, r_x1, r_y1);
131+
utils::values::rotate_inplace(angle, r_x2, r_y2);
132+
utils::values::rotate_inplace(angle, r_x3, r_y3);
133+
134+
utils::values::translate_inplace(delta, x0, y0);
135+
utils::values::translate_inplace(delta, x1, y1);
136+
137+
utils::values::translate_inplace(delta, r_x0, r_y0);
138+
utils::values::translate_inplace(delta, r_x1, r_y1);
139+
utils::values::translate_inplace(delta, r_x2, r_y2);
140+
utils::values::translate_inplace(delta, r_x3, r_y3);
141+
}
142+
122143
nlohmann::json pdf_resource<PAGE_CELL>::get()
123144
{
124145
nlohmann::json cell;

src/v2/pdf_resources/page_cells.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ namespace pdflib
1818

1919
nlohmann::json get();
2020
bool init_from(nlohmann::json& data);
21+
22+
void rotate(int angle, std::pair<double, double> delta);
2123

2224
pdf_resource<PAGE_CELL>& operator[](size_t i);
2325

@@ -61,6 +63,16 @@ namespace pdflib
6163
return result;
6264
}
6365

66+
void pdf_resource<PAGE_CELLS>::rotate(int angle, std::pair<double, double> delta)
67+
{
68+
LOG_S(INFO) << __FUNCTION__;
69+
70+
for(auto& cell:cells)
71+
{
72+
cell.rotate(angle, delta);
73+
}
74+
}
75+
6476
bool pdf_resource<PAGE_CELLS>::init_from(nlohmann::json& data)
6577
{
6678
LOG_S(INFO) << __FUNCTION__;

src/v2/pdf_resources/page_dimension.h

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@ namespace pdflib
1919
nlohmann::json get();
2020
bool init_from(nlohmann::json& data);
2121

22-
double get_angle() { return angle; }
22+
int get_angle() { return angle; }
2323

2424
std::array<double, 4> get_crop_bbox() { return crop_bbox; }
2525
std::array<double, 4> get_media_bbox() { return media_bbox; }
2626

2727
void execute(nlohmann::json& json_resources,
2828
QPDFObjectHandle qpdf_resources);
29+
30+
std::pair<double, double> rotate(int angle);
2931

3032
private:
3133

@@ -103,6 +105,56 @@ namespace pdflib
103105
return result;
104106
}
105107

108+
std::pair<double, double> pdf_resource<PAGE_DIMENSION>::rotate(int my_angle)
109+
{
110+
angle -= my_angle;
111+
112+
utils::values::rotate_inplace(my_angle, media_bbox);
113+
LOG_S(INFO) << "media: "
114+
<< media_bbox[0] << ", "
115+
<< media_bbox[1] << ", "
116+
<< media_bbox[2] << ", "
117+
<< media_bbox[3];
118+
119+
utils::values::rotate_inplace(my_angle, crop_bbox);
120+
121+
LOG_S(INFO) << "crop: "
122+
<< crop_bbox[0] << ", "
123+
<< crop_bbox[1] << ", "
124+
<< crop_bbox[2] << ", "
125+
<< crop_bbox[3];
126+
127+
utils::values::rotate_inplace(my_angle, bleed_bbox);
128+
utils::values::rotate_inplace(my_angle, trim_bbox);
129+
utils::values::rotate_inplace(my_angle, art_bbox);
130+
131+
utils::values::rotate_inplace(my_angle, bbox);
132+
133+
std::pair<double, double> delta = {0.0, std::abs(media_bbox[3])};
134+
135+
media_bbox[3] += 2*delta.second;
136+
crop_bbox[3] += 2*delta.second;
137+
bleed_bbox[3] += 2*delta.second;
138+
trim_bbox[3] += 2*delta.second;
139+
art_bbox[3] += 2*delta.second;
140+
141+
bbox[3] += 2*delta.second;
142+
143+
LOG_S(INFO) << "crop: "
144+
<< crop_bbox[0] << ", "
145+
<< crop_bbox[1] << ", "
146+
<< crop_bbox[2] << ", "
147+
<< crop_bbox[3];
148+
149+
LOG_S(INFO) << "crop: "
150+
<< bbox[0] << ", "
151+
<< bbox[1] << ", "
152+
<< bbox[2] << ", "
153+
<< bbox[3];
154+
155+
return delta;
156+
}
157+
106158
bool pdf_resource<PAGE_DIMENSION>::init_from(nlohmann::json& data)
107159
{
108160
//LOG_S(INFO) << "reading: " << data.dump(2);

src/v2/pdf_resources/page_image.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ namespace pdflib
1616

1717
nlohmann::json get();
1818

19+
void rotate(int angle, std::pair<double, double> delta);
20+
1921
public:
2022

2123
static std::vector<std::string> header;
@@ -54,6 +56,21 @@ namespace pdflib
5456
return image;
5557
}
5658

59+
void pdf_resource<PAGE_IMAGE>::rotate(int angle, std::pair<double, double> delta)
60+
{
61+
utils::values::rotate_inplace(angle, x0, y0);
62+
utils::values::rotate_inplace(angle, x1, y1);
63+
64+
utils::values::translate_inplace(delta, x0, y0);
65+
utils::values::translate_inplace(delta, x1, y1);
66+
67+
double y_min = std::min(y0, y1);
68+
double y_max = std::max(y0, y1);
69+
70+
y0 = y_min;
71+
y1 = y_max;
72+
}
73+
5774
}
5875

5976
#endif

src/v2/pdf_resources/page_images.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ namespace pdflib
1818

1919
nlohmann::json get();
2020

21+
void rotate(int angle, std::pair<double, double> delta);
22+
2123
pdf_resource<PAGE_IMAGE>& operator[](size_t i);
2224

2325
void clear();
@@ -58,6 +60,16 @@ namespace pdflib
5860
return result;
5961
}
6062

63+
void pdf_resource<PAGE_IMAGES>::rotate(int angle, std::pair<double, double> delta)
64+
{
65+
LOG_S(INFO) << __FUNCTION__;
66+
67+
for(auto& image:images)
68+
{
69+
image.rotate(angle, delta);
70+
}
71+
}
72+
6173
pdf_resource<PAGE_IMAGE>& pdf_resource<PAGE_IMAGES>::operator[](size_t i)
6274
{
6375
return images.at(i);

src/v2/pdf_resources/page_line.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ namespace pdflib
1616

1717
nlohmann::json get();
1818
bool init_from(nlohmann::json& data);
19-
19+
20+
void rotate(int angle, std::pair<double, double> delta);
21+
2022
std::vector<int>& get_i() { return i; }
2123

2224
std::vector<double>& get_x() { return x; }
@@ -87,6 +89,15 @@ namespace pdflib
8789

8890
return false;
8991
}
92+
93+
void pdf_resource<PAGE_LINE>::rotate(int angle, std::pair<double, double> delta)
94+
{
95+
for(int l=0; l<x.size(); l++)
96+
{
97+
utils::values::rotate_inplace(angle, x.at(l), y.at(l));
98+
utils::values::translate_inplace(delta, x.at(l), y.at(l));
99+
}
100+
}
90101

91102
void pdf_resource<PAGE_LINE>::append(double x_, double y_)
92103
{

src/v2/pdf_resources/page_lines.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ namespace pdflib
1919
nlohmann::json get();
2020
bool init_from(nlohmann::json& data);
2121

22+
void rotate(int angle, std::pair<double, double> delta);
23+
2224
pdf_resource<PAGE_LINE>& operator[](size_t i);
2325

2426
void clear();
@@ -87,6 +89,15 @@ namespace pdflib
8789
return result;
8890
}
8991

92+
void pdf_resource<PAGE_LINES>::rotate(int angle, std::pair<double, double> delta)
93+
{
94+
LOG_S(INFO) << __FUNCTION__;
95+
96+
for(auto& line:lines)
97+
{
98+
line.rotate(angle, delta);
99+
}
100+
}
90101

91102
pdf_resource<PAGE_LINE>& pdf_resource<PAGE_LINES>::operator[](size_t i)
92103
{

src/v2/utils/values.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,35 @@ namespace utils
6969
return (area_union > 0) ? (area_inter / area_union) : 0.0;
7070
}
7171

72+
void rotate_inplace(int angle, double& x0, double& y0)
73+
{
74+
double phi = -3.141592*angle/180.0;
75+
76+
double x1 = x0, y1 = y0;
77+
78+
x0 = std::cos(phi)*x1 - std::sin(phi)*y1;
79+
y0 = std::sin(phi)*x1 + std::cos(phi)*y1;
80+
}
81+
82+
void translate_inplace(std::pair<double, double> delta, double& x0, double& y0)
83+
{
84+
x0 += delta.first;
85+
y0 += delta.second;
86+
}
87+
88+
void rotate_inplace(int angle, std::array<double, 4>& bbox)
89+
{
90+
double phi = -3.141592*angle/180.0;
91+
92+
std::array<double, 4> tmp = bbox;
93+
94+
bbox[0] = std::cos(phi)*tmp[0] - std::sin(phi)*tmp[1];
95+
bbox[1] = std::sin(phi)*tmp[0] + std::cos(phi)*tmp[1];
96+
97+
bbox[2] = std::cos(phi)*tmp[2] - std::sin(phi)*tmp[3];
98+
bbox[3] = std::sin(phi)*tmp[2] + std::cos(phi)*tmp[3];
99+
}
100+
72101
}
73102

74103
}

0 commit comments

Comments
 (0)