1From 0ab805f46f68500da3b49d6f89380bab169bf6bb Mon Sep 17 00:00:00 2001
2From: Su Laus <sulau@freenet.de>
3Date: Tue, 10 May 2022 20:03:17 +0000
4Subject: [PATCH] tiffcrop: Fix issue #330 and some more from 320 to 349
5
6Upstream-Status: Backport
7Signed-off-by: Zheng Qiu <zheng.qiu@windriver.com>
8---
9 tools/tiffcrop.c | 282 +++++++++++++++++++++++++++++++++++------------
10 1 file changed, 210 insertions(+), 72 deletions(-)
11
12diff --git a/tools/tiffcrop.c b/tools/tiffcrop.c
13index 99e4208..b596f9e 100644
14--- a/tools/tiffcrop.c
15+++ b/tools/tiffcrop.c
16@@ -63,20 +63,24 @@
17  *                units when sectioning image into columns x rows
18  *                using the -S cols:rows option.
19  * -X #           Horizontal dimension of region to extract expressed in current
20- *                units
21+ *                units, relative to the specified origin reference 'edge' left (default for X) or right.
22  * -Y #           Vertical dimension of region to extract expressed in current
23- *                units
24+ *                units, relative to the specified origin reference 'edge' top (default for Y) or bottom.
25  * -O orient      Orientation for output image, portrait, landscape, auto
26  * -P page        Page size for output image segments, eg letter, legal, tabloid,
27  *                etc.
28  * -S cols:rows   Divide the image into equal sized segments using cols across
29  *                and rows down
30- * -E t|l|r|b     Edge to use as origin
31+ * -E t|l|r|b     Edge to use as origin (i.e. 'side' of the image not 'corner')
32+ *                  top    = width from left, zones from top to bottom (default)
33+ *                  bottom = width from left, zones from bottom to top
34+ *                  left   = zones from left to right, length from top
35+ *                  right  = zones from right to left, length from top
36  * -m #,#,#,#     Margins from edges for selection: top, left, bottom, right
37  *                (commas separated)
38  * -Z #:#,#:#     Zones of the image designated as zone X of Y,
39  *                eg 1:3 would be first of three equal portions measured
40- *                from reference edge
41+ *                from reference edge (i.e. 'side' not corner)
42  * -N odd|even|#,#-#,#|last
43  *                Select sequences and/or ranges of images within file
44  *                to process. The words odd or even may be used to specify
45@@ -103,10 +107,13 @@
46  *                selects which functions dump data, with higher numbers selecting
47  *                lower level, scanline level routines. Debug reports a limited set
48  *                of messages to monitor progress without enabling dump logs.
49+ *
50+ * Note:    The (-X|-Y), -Z and -z options are mutually exclusive.
51+ *          In no case should the options be applied to a given selection successively.
52  */
53
54-static   char tiffcrop_version_id[] = "2.4.1";
55-static   char tiffcrop_rev_date[] = "03-03-2010";
56+static   char tiffcrop_version_id[] = "2.5";
57+static   char tiffcrop_rev_date[] = "02-09-2022";
58
59 #include "tif_config.h"
60 #include "libport.h"
61@@ -774,6 +781,9 @@ static const char usage_info[] =
62 "             The four debug/dump options are independent, though it makes little sense to\n"
63 "             specify a dump file without specifying a detail level.\n"
64 "\n"
65+"Note:        The (-X|-Y), -Z and -z options are mutually exclusive.\n"
66+"             In no case should the options be applied to a given selection successively.\n"
67+"\n"
68 ;
69
70 /* This function could be modified to pass starting sample offset
71@@ -2123,6 +2133,15 @@ void  process_command_opts (int argc, char *argv[], char *mp, char *mode, uint32
72 		/*NOTREACHED*/
73       }
74     }
75+    /*-- Check for not allowed combinations (e.g. -X, -Y and -Z and -z are mutually exclusive) --*/
76+    char XY, Z, R;
77+    XY = ((crop_data->crop_mode & CROP_WIDTH) || (crop_data->crop_mode & CROP_LENGTH));
78+    Z = (crop_data->crop_mode & CROP_ZONES);
79+    R = (crop_data->crop_mode & CROP_REGIONS);
80+    if ((XY && Z) || (XY && R) || (Z && R)) {
81+        TIFFError("tiffcrop input error", "The crop options(-X|-Y), -Z and -z are mutually exclusive.->Exit");
82+        exit(EXIT_FAILURE);
83+    }
84   }  /* end process_command_opts */
85
86 /* Start a new output file if one has not been previously opened or
87@@ -2748,7 +2767,7 @@ extractContigSamplesBytes (uint8_t *in, uint8_t *out, uint32_t cols,
88                            tsample_t count, uint32_t start, uint32_t end)
89   {
90   int i, bytes_per_sample, sindex;
91-  uint32_t col, dst_rowsize, bit_offset;
92+  uint32_t col, dst_rowsize, bit_offset, numcols;
93   uint32_t src_byte /*, src_bit */;
94   uint8_t *src = in;
95   uint8_t *dst = out;
96@@ -2759,6 +2778,10 @@ extractContigSamplesBytes (uint8_t *in, uint8_t *out, uint32_t cols,
97     return (1);
98     }
99
100+  /* Number of extracted columns shall be kept as (end-start + 1). Otherwise buffer-overflow might occur.
101+   * 'start' and 'col' count from 0 to (cols-1)  but 'end' is to be set one after the index of the last column to be copied!
102+   */
103+  numcols = abs(end - start);
104   if ((start > end) || (start > cols))
105     {
106     TIFFError ("extractContigSamplesBytes",
107@@ -2771,6 +2794,9 @@ extractContigSamplesBytes (uint8_t *in, uint8_t *out, uint32_t cols,
108                "Invalid end column value %"PRIu32" ignored", end);
109     end = cols;
110     }
111+  if (abs(end - start) > numcols) {
112+      end = start + numcols;
113+  }
114
115   dst_rowsize = (bps * (end - start) * count) / 8;
116
117@@ -2814,7 +2840,7 @@ extractContigSamples8bits (uint8_t *in, uint8_t *out, uint32_t cols,
118                            tsample_t count, uint32_t start, uint32_t end)
119   {
120   int    ready_bits = 0, sindex = 0;
121-  uint32_t col, src_byte, src_bit, bit_offset;
122+  uint32_t col, src_byte, src_bit, bit_offset, numcols;
123   uint8_t  maskbits = 0, matchbits = 0;
124   uint8_t  buff1 = 0, buff2 = 0;
125   uint8_t *src = in;
126@@ -2826,6 +2852,10 @@ extractContigSamples8bits (uint8_t *in, uint8_t *out, uint32_t cols,
127     return (1);
128     }
129
130+  /* Number of extracted columns shall be kept as (end-start + 1). Otherwise buffer-overflow might occur.
131+   * 'start' and 'col' count from 0 to (cols-1)  but 'end' is to be set one after the index of the last column to be copied!
132+   */
133+  numcols = abs(end - start);
134   if ((start > end) || (start > cols))
135     {
136     TIFFError ("extractContigSamples8bits",
137@@ -2838,7 +2868,10 @@ extractContigSamples8bits (uint8_t *in, uint8_t *out, uint32_t cols,
138                "Invalid end column value %"PRIu32" ignored", end);
139     end = cols;
140     }
141-
142+  if (abs(end - start) > numcols) {
143+      end = start + numcols;
144+  }
145+
146   ready_bits = 0;
147   maskbits =  (uint8_t)-1 >> (8 - bps);
148   buff1 = buff2 = 0;
149@@ -2891,7 +2924,7 @@ extractContigSamples16bits (uint8_t *in, uint8_t *out, uint32_t cols,
150                             tsample_t count, uint32_t start, uint32_t end)
151   {
152   int    ready_bits = 0, sindex = 0;
153-  uint32_t col, src_byte, src_bit, bit_offset;
154+  uint32_t col, src_byte, src_bit, bit_offset, numcols;
155   uint16_t maskbits = 0, matchbits = 0;
156   uint16_t buff1 = 0, buff2 = 0;
157   uint8_t  bytebuff = 0;
158@@ -2904,6 +2937,10 @@ extractContigSamples16bits (uint8_t *in, uint8_t *out, uint32_t cols,
159     return (1);
160     }
161
162+  /* Number of extracted columns shall be kept as (end-start + 1). Otherwise buffer-overflow might occur.
163+   * 'start' and 'col' count from 0 to (cols-1)  but 'end' is to be set one after the index of the last column to be copied!
164+   */
165+  numcols = abs(end - start);
166   if ((start > end) || (start > cols))
167     {
168     TIFFError ("extractContigSamples16bits",
169@@ -2916,6 +2953,9 @@ extractContigSamples16bits (uint8_t *in, uint8_t *out, uint32_t cols,
170                "Invalid end column value %"PRIu32" ignored", end);
171     end = cols;
172     }
173+  if (abs(end - start) > numcols) {
174+      end = start + numcols;
175+  }
176
177   ready_bits = 0;
178   maskbits = (uint16_t)-1 >> (16 - bps);
179@@ -2980,7 +3020,7 @@ extractContigSamples24bits (uint8_t *in, uint8_t *out, uint32_t cols,
180                             tsample_t count, uint32_t start, uint32_t end)
181   {
182   int    ready_bits = 0, sindex = 0;
183-  uint32_t col, src_byte, src_bit, bit_offset;
184+  uint32_t col, src_byte, src_bit, bit_offset, numcols;
185   uint32_t maskbits = 0, matchbits = 0;
186   uint32_t buff1 = 0, buff2 = 0;
187   uint8_t  bytebuff1 = 0, bytebuff2 = 0;
188@@ -2993,6 +3033,10 @@ extractContigSamples24bits (uint8_t *in, uint8_t *out, uint32_t cols,
189     return (1);
190     }
191
192+  /* Number of extracted columns shall be kept as (end-start + 1). Otherwise buffer-overflow might occur.
193+   * 'start' and 'col' count from 0 to (cols-1)  but 'end' is to be set one after the index of the last column to be copied!
194+   */
195+  numcols = abs(end - start);
196   if ((start > end) || (start > cols))
197     {
198     TIFFError ("extractContigSamples24bits",
199@@ -3005,6 +3049,9 @@ extractContigSamples24bits (uint8_t *in, uint8_t *out, uint32_t cols,
200                "Invalid end column value %"PRIu32" ignored", end);
201     end = cols;
202     }
203+  if (abs(end - start) > numcols) {
204+      end = start + numcols;
205+  }
206
207   ready_bits = 0;
208   maskbits =  (uint32_t)-1 >> (32 - bps);
209@@ -3089,7 +3136,7 @@ extractContigSamples32bits (uint8_t *in, uint8_t *out, uint32_t cols,
210                             tsample_t count, uint32_t start, uint32_t end)
211   {
212   int    ready_bits = 0, sindex = 0 /*, shift_width = 0 */;
213-  uint32_t col, src_byte, src_bit, bit_offset;
214+  uint32_t col, src_byte, src_bit, bit_offset, numcols;
215   uint32_t longbuff1 = 0, longbuff2 = 0;
216   uint64_t maskbits = 0, matchbits = 0;
217   uint64_t buff1 = 0, buff2 = 0, buff3 = 0;
218@@ -3104,6 +3151,10 @@ extractContigSamples32bits (uint8_t *in, uint8_t *out, uint32_t cols,
219     }
220
221
222+  /* Number of extracted columns shall be kept as (end-start + 1). Otherwise buffer-overflow might occur.
223+   * 'start' and 'col' count from 0 to (cols-1)  but 'end' is to be set one after the index of the last column to be copied!
224+   */
225+  numcols = abs(end - start);
226   if ((start > end) || (start > cols))
227     {
228     TIFFError ("extractContigSamples32bits",
229@@ -3116,6 +3167,9 @@ extractContigSamples32bits (uint8_t *in, uint8_t *out, uint32_t cols,
230                "Invalid end column value %"PRIu32" ignored", end);
231     end = cols;
232     }
233+  if (abs(end - start) > numcols) {
234+      end = start + numcols;
235+  }
236
237   /* shift_width = ((bps + 7) / 8) + 1; */
238   ready_bits = 0;
239@@ -3195,7 +3249,7 @@ extractContigSamplesShifted8bits (uint8_t *in, uint8_t *out, uint32_t cols,
240                                   int shift)
241   {
242   int    ready_bits = 0, sindex = 0;
243-  uint32_t col, src_byte, src_bit, bit_offset;
244+  uint32_t col, src_byte, src_bit, bit_offset, numcols;
245   uint8_t  maskbits = 0, matchbits = 0;
246   uint8_t  buff1 = 0, buff2 = 0;
247   uint8_t *src = in;
248@@ -3207,6 +3261,10 @@ extractContigSamplesShifted8bits (uint8_t *in, uint8_t *out, uint32_t cols,
249     return (1);
250     }
251
252+  /* Number of extracted columns shall be kept as (end-start + 1). Otherwise buffer-overflow might occur.
253+   * 'start' and 'col' count from 0 to (cols-1)  but 'end' is to be set one after the index of the last column to be copied!
254+   */
255+  numcols = abs(end - start);
256   if ((start > end) || (start > cols))
257     {
258     TIFFError ("extractContigSamplesShifted8bits",
259@@ -3219,6 +3277,9 @@ extractContigSamplesShifted8bits (uint8_t *in, uint8_t *out, uint32_t cols,
260                "Invalid end column value %"PRIu32" ignored", end);
261     end = cols;
262     }
263+  if (abs(end - start) > numcols) {
264+      end = start + numcols;
265+  }
266
267   ready_bits = shift;
268   maskbits =  (uint8_t)-1 >> (8 - bps);
269@@ -3275,7 +3336,7 @@ extractContigSamplesShifted16bits (uint8_t *in, uint8_t *out, uint32_t cols,
270                                    int shift)
271   {
272   int    ready_bits = 0, sindex = 0;
273-  uint32_t col, src_byte, src_bit, bit_offset;
274+  uint32_t col, src_byte, src_bit, bit_offset, numcols;
275   uint16_t maskbits = 0, matchbits = 0;
276   uint16_t buff1 = 0, buff2 = 0;
277   uint8_t  bytebuff = 0;
278@@ -3288,6 +3349,10 @@ extractContigSamplesShifted16bits (uint8_t *in, uint8_t *out, uint32_t cols,
279     return (1);
280     }
281
282+  /* Number of extracted columns shall be kept as (end-start + 1). Otherwise buffer-overflow might occur.
283+   * 'start' and 'col' count from 0 to (cols-1)  but 'end' is to be set one after the index of the last column to be copied!
284+   */
285+  numcols = abs(end - start);
286   if ((start > end) || (start > cols))
287     {
288     TIFFError ("extractContigSamplesShifted16bits",
289@@ -3300,6 +3365,9 @@ extractContigSamplesShifted16bits (uint8_t *in, uint8_t *out, uint32_t cols,
290                "Invalid end column value %"PRIu32" ignored", end);
291     end = cols;
292     }
293+  if (abs(end - start) > numcols) {
294+      end = start + numcols;
295+  }
296
297   ready_bits = shift;
298   maskbits = (uint16_t)-1 >> (16 - bps);
299@@ -3365,7 +3433,7 @@ extractContigSamplesShifted24bits (uint8_t *in, uint8_t *out, uint32_t cols,
300                                    int shift)
301   {
302   int    ready_bits = 0, sindex = 0;
303-  uint32_t col, src_byte, src_bit, bit_offset;
304+  uint32_t col, src_byte, src_bit, bit_offset, numcols;
305   uint32_t maskbits = 0, matchbits = 0;
306   uint32_t buff1 = 0, buff2 = 0;
307   uint8_t  bytebuff1 = 0, bytebuff2 = 0;
308@@ -3378,6 +3446,16 @@ extractContigSamplesShifted24bits (uint8_t *in, uint8_t *out, uint32_t cols,
309     return (1);
310     }
311
312+  /* Number of extracted columns shall be kept as (end-start + 1). Otherwise buffer-overflow might occur.
313+   * 'start' and 'col' count from 0 to (cols-1)  but 'end' is to be set one after the index of the last column to be copied!
314+   */
315+  /*--- Remark, which is true for all those functions extractCongigSamplesXXX() --
316+  *  The mitigation of the start/end test does not allways make sense, because the function is often called with e.g.:
317+  *  start = 31; end = 32; cols = 32  to extract the last column in a 32x32 sample image.
318+  *  If then, a worng parameter (e.g. cols = 10) is provided, the mitigated settings would be start=0; end=1.
319+  *  Therefore, an error message and no copy action might be the better reaction to wrong parameter configurations.
320+   */
321+  numcols = abs(end - start);
322   if ((start > end) || (start > cols))
323     {
324     TIFFError ("extractContigSamplesShifted24bits",
325@@ -3390,6 +3468,9 @@ extractContigSamplesShifted24bits (uint8_t *in, uint8_t *out, uint32_t cols,
326                "Invalid end column value %"PRIu32" ignored", end);
327     end = cols;
328     }
329+  if (abs(end - start) > numcols) {
330+      end = start + numcols;
331+  }
332
333   ready_bits = shift;
334   maskbits =  (uint32_t)-1 >> (32 - bps);
335@@ -3451,7 +3532,7 @@ extractContigSamplesShifted24bits (uint8_t *in, uint8_t *out, uint32_t cols,
336     buff2 = (buff2 << 8);
337     bytebuff2 = bytebuff1;
338     ready_bits -= 8;
339-    }
340+  }
341
342   return (0);
343   } /* end extractContigSamplesShifted24bits */
344@@ -3463,7 +3544,7 @@ extractContigSamplesShifted32bits (uint8_t *in, uint8_t *out, uint32_t cols,
345                                    int shift)
346   {
347   int    ready_bits = 0, sindex = 0 /*, shift_width = 0 */;
348-  uint32_t col, src_byte, src_bit, bit_offset;
349+  uint32_t col, src_byte, src_bit, bit_offset, numcols;
350   uint32_t longbuff1 = 0, longbuff2 = 0;
351   uint64_t maskbits = 0, matchbits = 0;
352   uint64_t buff1 = 0, buff2 = 0, buff3 = 0;
353@@ -3478,6 +3559,10 @@ extractContigSamplesShifted32bits (uint8_t *in, uint8_t *out, uint32_t cols,
354     }
355
356
357+  /* Number of extracted columns shall be kept as (end-start + 1). Otherwise buffer-overflow might occur.
358+   * 'start' and 'col' count from 0 to (cols-1)  but 'end' is to be set one after the index of the last column to be copied!
359+   */
360+  numcols = abs(end - start);
361   if ((start > end) || (start > cols))
362     {
363     TIFFError ("extractContigSamplesShifted32bits",
364@@ -3490,6 +3575,9 @@ extractContigSamplesShifted32bits (uint8_t *in, uint8_t *out, uint32_t cols,
365                "Invalid end column value %"PRIu32" ignored", end);
366     end = cols;
367     }
368+  if (abs(end - start) > numcols) {
369+      end = start + numcols;
370+  }
371
372   /* shift_width = ((bps + 7) / 8) + 1; */
373   ready_bits = shift;
374@@ -5431,7 +5519,7 @@ getCropOffsets(struct image_data *image, struct crop_mask *crop, struct dump_opt
375   {
376   struct offset offsets;
377   int    i;
378-  int32_t  test;
379+  uint32_t uaux;
380   uint32_t seg, total, need_buff = 0;
381   uint32_t buffsize;
382   uint32_t zwidth, zlength;
383@@ -5512,8 +5600,13 @@ getCropOffsets(struct image_data *image, struct crop_mask *crop, struct dump_opt
384     seg = crop->zonelist[j].position;
385     total = crop->zonelist[j].total;
386
387-    /* check for not allowed zone cases like 0:0; 4:3; etc. and skip that input */
388+    /* check for not allowed zone cases like 0:0; 4:3; or negative ones etc. and skip that input */
389+    if (crop->zonelist[j].position < 0 || crop->zonelist[j].total < 0) {
390+        TIFFError("getCropOffsets", "Negative crop zone values %d:%d are not allowed, thus skipped.", crop->zonelist[j].position, crop->zonelist[j].total);
391+        continue;
392+    }
393     if (seg == 0 || total == 0 || seg > total) {
394+        TIFFError("getCropOffsets", "Crop zone %d:%d is out of specification, thus skipped.", seg, total);
395         continue;
396     }
397
398@@ -5526,17 +5619,23 @@ getCropOffsets(struct image_data *image, struct crop_mask *crop, struct dump_opt
399
400            crop->regionlist[i].x1 = offsets.startx +
401                                   (uint32_t)(offsets.crop_width * 1.0 * (seg - 1) / total);
402-           test = (int32_t)offsets.startx +
403-                  (int32_t)(offsets.crop_width * 1.0 * seg / total);
404-           if (test < 1 )
405-             crop->regionlist[i].x2 = 0;
406-           else
407-	     {
408-	     if (test > (int32_t)(image->width - 1))
409+           /* FAULT: IMHO in the old code here, the calculation of x2 was based on wrong assumtions. The whole image was assumed and 'endy' and 'starty' are not respected anymore!*/
410+           /* NEW PROPOSED Code: Assumption: offsets are within image with top left corner as origin (0,0) and 'start' <= 'end'. */
411+           if (crop->regionlist[i].x1 > offsets.endx) {
412+                crop->regionlist[i].x1 = offsets.endx;
413+           } else if (crop->regionlist[i].x1 >= image->width) {
414+               crop->regionlist[i].x1 = image->width - 1;
415+           }
416+
417+           crop->regionlist[i].x2 = offsets.startx + (uint32_t)(offsets.crop_width * 1.0 * seg / total);
418+           if (crop->regionlist[i].x2 > 0) crop->regionlist[i].x2 = crop->regionlist[i].x2 - 1;
419+           if (crop->regionlist[i].x2 < crop->regionlist[i].x1) {
420+               crop->regionlist[i].x2 = crop->regionlist[i].x1;
421+           } else if (crop->regionlist[i].x2 > offsets.endx) {
422+               crop->regionlist[i].x2 = offsets.endx;
423+           } else if (crop->regionlist[i].x2 >= image->width) {
424                crop->regionlist[i].x2 = image->width - 1;
425-             else
426-	       crop->regionlist[i].x2 = test - 1;
427-             }
428+           }
429            zwidth = crop->regionlist[i].x2 - crop->regionlist[i].x1  + 1;
430
431 	   /* This is passed to extractCropZone or extractCompositeZones */
432@@ -5551,22 +5650,27 @@ getCropOffsets(struct image_data *image, struct crop_mask *crop, struct dump_opt
433 	   crop->regionlist[i].x1 = offsets.startx;
434            crop->regionlist[i].x2 = offsets.endx;
435
436-           test = offsets.endy - (uint32_t)(offsets.crop_length * 1.0 * seg / total);
437-           if (test < 1 )
438-	     crop->regionlist[i].y1 = 0;
439-           else
440-	     crop->regionlist[i].y1 = test + 1;
441+           /* FAULT: IMHO in the old code here, the calculation of y1/y2 was based on wrong assumtions. The whole image was assumed and 'endy' and 'starty' are not respected anymore!*/
442+           /* NEW PROPOSED Code: Assumption: offsets are within image with top left corner as origin (0,0) and 'start' <= 'end'. */
443+           uaux = (uint32_t)(offsets.crop_length * 1.0 * seg / total);
444+           if (uaux <= offsets.endy + 1) {
445+               crop->regionlist[i].y1 = offsets.endy - uaux + 1;
446+           } else {
447+               crop->regionlist[i].y1 = 0;
448+           }
449+           if (crop->regionlist[i].y1 < offsets.starty) {
450+               crop->regionlist[i].y1 = offsets.starty;
451+           }
452
453-           test = offsets.endy - (offsets.crop_length * 1.0 * (seg - 1) / total);
454-           if (test < 1 )
455-             crop->regionlist[i].y2 = 0;
456-           else
457-	     {
458-             if (test > (int32_t)(image->length - 1))
459-               crop->regionlist[i].y2 = image->length - 1;
460-             else
461-               crop->regionlist[i].y2 = test;
462-	     }
463+           uaux = (uint32_t)(offsets.crop_length * 1.0 * (seg - 1) / total);
464+           if (uaux <= offsets.endy) {
465+               crop->regionlist[i].y2 = offsets.endy - uaux;
466+           } else {
467+               crop->regionlist[i].y2 = 0;
468+           }
469+           if (crop->regionlist[i].y2 < offsets.starty) {
470+               crop->regionlist[i].y2 = offsets.starty;
471+           }
472            zlength = crop->regionlist[i].y2 - crop->regionlist[i].y1 + 1;
473
474 	   /* This is passed to extractCropZone or extractCompositeZones */
475@@ -5577,32 +5681,42 @@ getCropOffsets(struct image_data *image, struct crop_mask *crop, struct dump_opt
476            crop->combined_width = (uint32_t)zwidth;
477            break;
478       case EDGE_RIGHT: /* zones from right to left, length from top */
479-           zlength = offsets.crop_length;
480-	   crop->regionlist[i].y1 = offsets.starty;
481-           crop->regionlist[i].y2 = offsets.endy;
482-
483-           crop->regionlist[i].x1 = offsets.startx +
484-                                  (uint32_t)(offsets.crop_width * (total - seg) * 1.0 / total);
485-           test = offsets.startx +
486-	          (offsets.crop_width * (total - seg + 1) * 1.0 / total);
487-           if (test < 1 )
488-             crop->regionlist[i].x2 = 0;
489-           else
490-	     {
491-	     if (test > (int32_t)(image->width - 1))
492-               crop->regionlist[i].x2 = image->width - 1;
493-             else
494-               crop->regionlist[i].x2 = test - 1;
495-             }
496-           zwidth = crop->regionlist[i].x2 - crop->regionlist[i].x1  + 1;
497+		  zlength = offsets.crop_length;
498+		  crop->regionlist[i].y1 = offsets.starty;
499+		  crop->regionlist[i].y2 = offsets.endy;
500+
501+		  crop->regionlist[i].x1 = offsets.startx +
502+			  (uint32_t)(offsets.crop_width * (total - seg) * 1.0 / total);
503+          /* FAULT: IMHO from here on, the calculation of y2 are based on wrong assumtions. The whole image is assumed and 'endy' and 'starty' are not respected anymore!*/
504+          /* NEW PROPOSED Code: Assumption: offsets are within image with top left corner as origin (0,0) and 'start' <= 'end'. */
505+          uaux = (uint32_t)(offsets.crop_width * 1.0 * seg / total);
506+          if (uaux <= offsets.endx + 1) {
507+              crop->regionlist[i].x1 = offsets.endx - uaux + 1;
508+          } else {
509+              crop->regionlist[i].x1 = 0;
510+          }
511+          if (crop->regionlist[i].x1 < offsets.startx) {
512+              crop->regionlist[i].x1 = offsets.startx;
513+          }
514
515-	   /* This is passed to extractCropZone or extractCompositeZones */
516-           crop->combined_length = (uint32_t)zlength;
517-           if (crop->exp_mode == COMPOSITE_IMAGES)
518-             crop->combined_width += (uint32_t)zwidth;
519-           else
520-             crop->combined_width = (uint32_t)zwidth;
521-           break;
522+          uaux = (uint32_t)(offsets.crop_width * 1.0 * (seg - 1) / total);
523+          if (uaux <= offsets.endx) {
524+              crop->regionlist[i].x2 = offsets.endx - uaux;
525+          } else {
526+              crop->regionlist[i].x2 = 0;
527+          }
528+          if (crop->regionlist[i].x2 < offsets.startx) {
529+              crop->regionlist[i].x2 = offsets.startx;
530+          }
531+          zwidth = crop->regionlist[i].x2 - crop->regionlist[i].x1 + 1;
532+
533+		  /* This is passed to extractCropZone or extractCompositeZones */
534+		  crop->combined_length = (uint32_t)zlength;
535+		  if (crop->exp_mode == COMPOSITE_IMAGES)
536+			  crop->combined_width += (uint32_t)zwidth;
537+		  else
538+			  crop->combined_width = (uint32_t)zwidth;
539+		  break;
540       case EDGE_TOP: /* width from left, zones from top to bottom */
541       default:
542            zwidth = offsets.crop_width;
543@@ -5610,6 +5724,14 @@ getCropOffsets(struct image_data *image, struct crop_mask *crop, struct dump_opt
544            crop->regionlist[i].x2 = offsets.endx;
545
546            crop->regionlist[i].y1 = offsets.starty + (uint32_t)(offsets.crop_length * 1.0 * (seg - 1) / total);
547+           if (crop->regionlist[i].y1 > offsets.endy) {
548+               crop->regionlist[i].y1 = offsets.endy;
549+           } else if (crop->regionlist[i].y1 >= image->length) {
550+               crop->regionlist[i].y1 = image->length - 1;
551+           }
552+
553+           /* FAULT: IMHO from here on, the calculation of y2 are based on wrong assumtions. The whole image is assumed and 'endy' and 'starty' are not respected anymore!*/
554+           /* OLD Code:
555            test = offsets.starty + (uint32_t)(offsets.crop_length * 1.0 * seg / total);
556            if (test < 1 )
557              crop->regionlist[i].y2 = 0;
558@@ -5620,6 +5742,18 @@ getCropOffsets(struct image_data *image, struct crop_mask *crop, struct dump_opt
559              else
560 	       crop->regionlist[i].y2 = test - 1;
561 	     }
562+           */
563+		   /* NEW PROPOSED Code: Assumption: offsets are within image with top left corner as origin (0,0) and 'start' <= 'end'. */
564+		   crop->regionlist[i].y2 = offsets.starty + (uint32_t)(offsets.crop_length * 1.0 * seg / total);
565+           if (crop->regionlist[i].y2 > 0)crop->regionlist[i].y2 = crop->regionlist[i].y2 - 1;
566+		   if (crop->regionlist[i].y2 < crop->regionlist[i].y1) {
567+			   crop->regionlist[i].y2 = crop->regionlist[i].y1;
568+		   } else if (crop->regionlist[i].y2 > offsets.endy) {
569+			   crop->regionlist[i].y2 = offsets.endy;
570+		   } else if (crop->regionlist[i].y2 >= image->length) {
571+			   crop->regionlist[i].y2 = image->length - 1;
572+		   }
573+
574            zlength = crop->regionlist[i].y2 - crop->regionlist[i].y1 + 1;
575
576 	   /* This is passed to extractCropZone or extractCompositeZones */
577@@ -7543,7 +7677,8 @@ processCropSelections(struct image_data *image, struct crop_mask *crop,
578     total_width = total_length = 0;
579     for (i = 0; i < crop->selections; i++)
580       {
581-      cropsize = crop->bufftotal;
582+
583+        cropsize = crop->bufftotal;
584       crop_buff = seg_buffs[i].buffer;
585       if (!crop_buff)
586         crop_buff = (unsigned char *)limitMalloc(cropsize);
587@@ -7632,6 +7767,9 @@ processCropSelections(struct image_data *image, struct crop_mask *crop,
588
589       if (crop->crop_mode & CROP_ROTATE) /* rotate should be last as it can reallocate the buffer */
590         {
591+          /* rotateImage() changes image->width, ->length, ->xres and ->yres, what it schouldn't do here, when more than one section is processed.
592+           * ToDo: Therefore rotateImage() and its usage has to be reworked (e.g. like mirrorImage()) !!
593+           */
594 	if (rotateImage(crop->rotation, image, &crop->regionlist[i].width,
595 			&crop->regionlist[i].length, &crop_buff))
596           {
597@@ -7647,8 +7785,8 @@ processCropSelections(struct image_data *image, struct crop_mask *crop,
598         seg_buffs[i].size = (((crop->regionlist[i].width * image->bps + 7 ) / 8)
599                                * image->spp) * crop->regionlist[i].length;
600         }
601-      }
602-    }
603+      }  /* for crop->selections loop */
604+    }  /* Separated Images (else case) */
605   return (0);
606   } /* end processCropSelections */
607
608