@@ -262,6 +262,142 @@ void pbio_image_draw_vline(pbio_image_t *image, int x, int y, int l,
262262 }
263263}
264264
265+ /**
266+ * Draw a line with a flat slope (less or equal to 1).
267+ * @param [in,out] image Image to draw into.
268+ * @param [in] x1 X coordinate of the first end.
269+ * @param [in] y1 Y coordinate of the first end.
270+ * @param [in] x2 X coordinate of the second end.
271+ * @param [in] y2 Y coordinate of the second end.
272+ * @param [in] value Pixel value.
273+ *
274+ * This is an internal function, x2 must be greater or equal to x1.
275+ *
276+ * Clipping: drawing is clipped to image dimensions.
277+ */
278+ static void pbio_image_draw_line_flat (pbio_image_t * image , int x1 , int y1 ,
279+ int x2 , int y2 , uint8_t value ) {
280+ int dx = x2 - x1 ;
281+ int dy = y2 - y1 ;
282+ int ydir = 1 ;
283+ int x , y , err ;
284+
285+ // Fall back to horizontal line, much faster.
286+ if (dy == 0 ) {
287+ pbio_image_draw_hline (image , x1 , y1 , dx + 1 , value );
288+ return ;
289+ }
290+
291+ // Clipping, X out of image.
292+ if (x1 >= image -> width || x2 < 0 ) {
293+ return ;
294+ }
295+
296+ // Check Y direction.
297+ if (dy < 0 ) {
298+ dy = - dy ;
299+ ydir = -1 ;
300+ }
301+
302+ // Error is scaled by 2 * dx, offset with one half to look at mid point.
303+ err = - dx ;
304+ y = y1 ;
305+
306+ // Skip pixels left of image.
307+ if (x1 < 0 ) {
308+ err += - x1 * dy * 2 ;
309+ int yskip = (err + dx * 2 ) / (dx * 2 );
310+ err -= yskip * dx * 2 ;
311+ y += yskip * ydir ;
312+ x1 = 0 ;
313+ }
314+
315+ // Skip pixels right of image.
316+ if (x2 >= image -> width ) {
317+ x2 = image -> width - 1 ;
318+ }
319+
320+ // Draw.
321+ x = x1 ;
322+ do {
323+ pbio_image_draw_pixel (image , x , y , value );
324+ err += dy * 2 ;
325+ if (err >= 0 ) {
326+ err -= dx * 2 ;
327+ y += ydir ;
328+ }
329+ x ++ ;
330+ } while (x <= x2 );
331+ }
332+
333+ /**
334+ * Draw a line with a steep slope (more than 1).
335+ * @param [in,out] image Image to draw into.
336+ * @param [in] x1 X coordinate of the first end.
337+ * @param [in] y1 Y coordinate of the first end.
338+ * @param [in] x2 X coordinate of the second end.
339+ * @param [in] y2 Y coordinate of the second end.
340+ * @param [in] value Pixel value.
341+ *
342+ * This is an internal function, y2 must be greater or equal to y1.
343+ *
344+ * Clipping: drawing is clipped to image dimensions.
345+ */
346+ static void pbio_image_draw_line_steep (pbio_image_t * image , int x1 , int y1 ,
347+ int x2 , int y2 , uint8_t value ) {
348+ int dx = x2 - x1 ;
349+ int dy = y2 - y1 ;
350+ int xdir = 1 ;
351+ int x , y , err ;
352+
353+ // Fall back to vertical line, much faster.
354+ if (dx == 0 ) {
355+ pbio_image_draw_vline (image , x1 , y1 , dy + 1 , value );
356+ return ;
357+ }
358+
359+ // Clipping, Y out of image.
360+ if (y1 >= image -> height || y2 < 0 ) {
361+ return ;
362+ }
363+
364+ // Check X direction.
365+ if (dx < 0 ) {
366+ dx = - dx ;
367+ xdir = -1 ;
368+ }
369+
370+ // Error is scaled by 2 * dy, offset with one half to look at mid point.
371+ err = - dy ;
372+ x = x1 ;
373+
374+ // Skip pixels above image.
375+ if (y1 < 0 ) {
376+ err += - y1 * dx * 2 ;
377+ int xskip = (err + dy * 2 ) / (dy * 2 );
378+ err -= xskip * dy * 2 ;
379+ x += xskip * xdir ;
380+ y1 = 0 ;
381+ }
382+
383+ // Skip pixels bellow image.
384+ if (y2 >= image -> height ) {
385+ y2 = image -> height - 1 ;
386+ }
387+
388+ // Draw.
389+ y = y1 ;
390+ do {
391+ pbio_image_draw_pixel (image , x , y , value );
392+ err += dx * 2 ;
393+ if (err >= 0 ) {
394+ err -= dy * 2 ;
395+ x += xdir ;
396+ }
397+ y ++ ;
398+ } while (y <= y2 );
399+ }
400+
265401/**
266402 * Draw a line.
267403 * @param [in,out] image Image to draw into.
@@ -275,7 +411,26 @@ void pbio_image_draw_vline(pbio_image_t *image, int x, int y, int l,
275411 */
276412void pbio_image_draw_line (pbio_image_t * image , int x1 , int y1 , int x2 , int y2 ,
277413 uint8_t value ) {
278- // TODO
414+ int dx = x2 - x1 ;
415+ int dy = y2 - y1 ;
416+ int abs_dx = dx < 0 ? - dx : dx ;
417+ int abs_dy = dy < 0 ? - dy : dy ;
418+
419+ if (abs_dx >= abs_dy ) {
420+ // Flat slope, X always increasing.
421+ if (dx > 0 ) {
422+ pbio_image_draw_line_flat (image , x1 , y1 , x2 , y2 , value );
423+ } else {
424+ pbio_image_draw_line_flat (image , x2 , y2 , x1 , y1 , value );
425+ }
426+ } else {
427+ // Steep slope, Y always increasing.
428+ if (dy > 0 ) {
429+ pbio_image_draw_line_steep (image , x1 , y1 , x2 , y2 , value );
430+ } else {
431+ pbio_image_draw_line_steep (image , x2 , y2 , x1 , y1 , value );
432+ }
433+ }
279434}
280435
281436/**
@@ -289,7 +444,7 @@ void pbio_image_draw_line(pbio_image_t *image, int x1, int y1, int x2, int y2,
289444 * @param [in] value Pixel value.
290445 *
291446 * When line thickness is odd, pixels are centered on the line. When even,
292- * line is thicker on one side.
447+ * line is thicker on left side, when looking from first end to second end .
293448 *
294449 * Clipping: drawing is clipped to image dimensions.
295450 */
@@ -299,7 +454,47 @@ void pbio_image_draw_thick_line(pbio_image_t *image, int x1, int y1, int x2,
299454 if (thickness <= 0 ) {
300455 return ;
301456 }
302- // TODO
457+
458+ // Fall back to regular line.
459+ if (thickness <= 1 ) {
460+ pbio_image_draw_line (image , x1 , y1 , x2 , y2 , value );
461+ return ;
462+ }
463+
464+ int dx = x2 - x1 ;
465+ int dy = y2 - y1 ;
466+ int abs_dx = dx < 0 ? - dx : dx ;
467+ int abs_dy = dy < 0 ? - dy : dy ;
468+ int i ;
469+ int offset = thickness / 2 ;
470+
471+ if (abs_dx >= abs_dy ) {
472+ // Flat slope, X always increasing.
473+ if (dx > 0 ) {
474+ for (i = 0 ; i < thickness ; i ++ ) {
475+ pbio_image_draw_line_flat (image , x1 , y1 + i - offset ,
476+ x2 , y2 + i - offset , value );
477+ }
478+ } else {
479+ for (i = 0 ; i < thickness ; i ++ ) {
480+ pbio_image_draw_line_flat (image , x2 , y2 - i + offset ,
481+ x1 , y1 - i + offset , value );
482+ }
483+ }
484+ } else {
485+ // Steep slope, Y always increasing.
486+ if (dy > 0 ) {
487+ for (i = 0 ; i < thickness ; i ++ ) {
488+ pbio_image_draw_line_steep (image , x1 - i + offset , y1 ,
489+ x2 - i + offset , y2 , value );
490+ }
491+ } else {
492+ for (i = 0 ; i < thickness ; i ++ ) {
493+ pbio_image_draw_line_steep (image , x2 + i - offset , y2 ,
494+ x1 + i - offset , y1 , value );
495+ }
496+ }
497+ }
303498}
304499
305500/**
0 commit comments