Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ENH: Add color parameter to AnnotationBuilder.rectangle #1723

Closed
wants to merge 1 commit into from

Conversation

hirenpopat67
Copy link

…ectangle function

@codecov
Copy link

codecov bot commented Mar 17, 2023

Codecov Report

Patch coverage has no change and project coverage change: -0.03 ⚠️

Comparison is base (1e4086e) 92.49% compared to head (fde732f) 92.47%.

❗ Current head fde732f differs from pull request most recent head 599b6bb. Consider uploading reports for the commit 599b6bb to get more accurate results

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1723      +/-   ##
==========================================
- Coverage   92.49%   92.47%   -0.03%     
==========================================
  Files          34       34              
  Lines        6533     6514      -19     
  Branches     1292     1288       -4     
==========================================
- Hits         6043     6024      -19     
+ Misses        318      317       -1     
- Partials      172      173       +1     
Impacted Files Coverage Δ
pypdf/generic/_annotations.py 93.47% <0.00%> (-2.61%) ⬇️

... and 4 files with indirect coverage changes

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

☔ View full report in Codecov by Sentry.
📢 Do you have feedback about the report comment? Let us know in this issue.

@hirenpopat67
Copy link
Author

I have added colour variable while draw rectangle on pdf change _annotations.py file rectangle function

@hirenpopat67
Copy link
Author

Codecov Report

Patch coverage has no change and project coverage change: -0.03 warning

Comparison is base (9878034) 92.50% compared to head (684e2ff) 92.47%.

Additional details and impacted files
umbrella View full report in Codecov by Sentry. loudspeaker Do you have feedback about the report comment? Let us know in this issue.

I have added colour variable while draw rectangle on pdf change _annotations.py file rectangle function

@MartinThoma MartinThoma changed the title add color functionality when draw a box in the pdf _annotation.py's r… ENH: Add color parameter to AnnotationBuilder.rectangle Mar 17, 2023
@MartinThoma
Copy link
Member

Thank you for the PR 🙏

Should we rather call it border_color?

Also, new parameters need to be added to the end for backwards compatibility. And I think we should start using keyword-only parameters, e.g.:

    @staticmethod
    def rectangle(
        rect: Union[RectangleObject, Tuple[float, float, float, float]],
        interiour_color: Optional[str] = None,
        *,  # This makes it keyword-only, see https://peps.python.org/pep-3102/
        rectangle_color: Optional[str] = None,  # I guess it's the border_color, but I didn't check.
    ) -> DictionaryObject:

@pubpub-zz
Copy link
Collaborator

As an alternative, as "/C" is used on many annotations I propose to add a function applicable to all annotations. example :

annotation = AnnotationBuilder.rectangle(rect=(50, 550, 200, 650)).set_border_color([255,0,0])

it would be great if the color could be either an arrayobject, a standard array or tuple of ints, and maybe an string from PIL.ImageColor.

@MartinThoma / @hirenpopat67 your opinion ?

@MartinThoma
Copy link
Member

MartinThoma commented Mar 18, 2023

@pubpub-zz What would be the advantage of a method set_border_color vs a keyword-parameter border_color?

@MartinThoma
Copy link
Member

it would be great if the color could be either an arrayobject, a standard array or tuple of ints, and maybe an string from PIL.ImageColor

Sounds good - but we should do it consistently for all color parameters in pypdf

@pubpub-zz
Copy link
Collaborator

pubpub-zz commented Mar 18, 2023

@pubpub-zz What would be the advantage of a method set_border_color vs a keyword-parameter border_color?

the advantage would be to be able to have this solution for all annotations (circle, line,...)

also it will be a good approach later to add other fields/properties

@MartinThoma MartinThoma self-requested a review March 18, 2023 15:49
Copy link
Member

@MartinThoma MartinThoma left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Ensure backwards compatibility by making it a keyword-only argument
  2. Use a name that is more telling than rectangle_color, e.g border_color

@hirenpopat67
Copy link
Author

hirenpopat67 commented Mar 18, 2023 via email

@MartinThoma
Copy link
Member

the advantage [of a method .set_border_color in contrast to a keyword-argument] would be to be able to have this solution for all annotations (circle, line,...)

You mean as a way to avoid code duplication?

The current annotation builder methods return DictionaryObjects. How would we change it so that this method can be added?

@pubpub-zz
Copy link
Collaborator

the advantage [of a method .set_border_color in contrast to a keyword-argument] would be to be able to have this solution for all annotations (circle, line,...)

You mean as a way to avoid code duplication?

The current annotation builder methods return DictionaryObjects. How would we change it so that this method can be added?

I would propose the AnnotationBuilder functions to create AnnotationDictionaryObject on which class the functions set_border_color() and later some other ones such as annotation_name("/NM"), border_type("/Border"),...

@hirenpopat67
Copy link
Author

hirenpopat67 commented Mar 20, 2023 via email

@hirenpopat67
Copy link
Author

As discussed i have created set_border_color function to avoid duplication

@pubpub-zz
Copy link
Collaborator

pubpub-zz commented Mar 20, 2023

@hirenpopat67
I've pushed a PR (hirenpopat67#1) on your branch to show what I had in mind. What do you think of it ?

@hirenpopat67
Copy link
Author

@hirenpopat67 I've pushed a PR (hirenpopat67#1) on your branch to show what I had in mind. What do you think of it ?

Great ,I have reviewed code its working fine.

Thank you for your time and consideration..

@hirenpopat67
Copy link
Author

hirenpopat67 commented Mar 21, 2023 via email

@pubpub-zz
Copy link
Collaborator

@hirenpopat67 , can you complete test_generic.py in order to cover the new function

@MartinThoma
Copy link
Member

I'm still not sure if the AnnotationObject / set_border_color really is a good solution. Do all annotations have a border. I know that /Rectangle is required, but for border I'm less certain.

Are there any other attributes that all annotations have?

@pubpub-zz
Copy link
Collaborator

from pdf 1.7 spec,
image

but it applicable to circle (border) strike out color, ...

maybe set_color() could be better...

Copy link
Collaborator

@pubpub-zz pubpub-zz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to fix mypy and also to cope with RGB on 0-255 ranges

try:
from PIL import ImageColor as ImageColorLoaded
except ImportError:
ImageColorLoaded = None
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to fix mypy

Suggested change
ImageColorLoaded = None
ImageColorLoaded = None # type: ignore

if isinstance(border_color, str):
if ImageColorLoaded is None:
raise ImportError("PIL required but not installed")
border_color = ImageColorLoaded.getrgb(border_color)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
border_color = ImageColorLoaded.getrgb(border_color)
border_color = (x/255.0 for x in ImageColorLoaded.getrgb(border_color)[:3])

for mypy

raise ImportError("PIL required but not installed")
border_color = ImageColorLoaded.getrgb(border_color)
if isinstance(border_color, (list, tuple)):
border_color = ArrayObject([FloatObject(n) for n in border_color[:3]])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
border_color = ArrayObject([FloatObject(n) for n in border_color[:3]])
border_color = ArrayObject([FloatObject(n if n<=1.0 else n/255.0) for n in border_color[:3]])

if the array provided is an array of RGB color

@hirenpopat67
Copy link
Author

I am writing to suggest a small improvement to the existing implementation of the rectangle function.

Currently, the function allows users to draw a rectangle on a PDF and specify the interior color of the rectangle using the interior_color argument. However, there is no option to specify the fill color of the rectangle.

Rather than create set_border_colour function we can create colour color keyword argument to the rectangle function
to make the function more user-friendly , I would like to suggest adding a "color" keyword argument to the rectangle function. This would allow users to specify both the border and fill color of the rectangle using a single function call.

Here is an example of the updated function signature:

@staticmethod
def rectangle(
rect: Union[RectangleObject, Tuple[float, float, float, float]],
interior_color: Optional[str] = None,
color: Optional[str] = None,
) -> AnnotationObject:

I believe that this change would make the function more intuitive and user-friendly. Please let me know if you have any questions or concerns regarding this suggestion.

Thank you for considering my suggestion.

Best regards,
Hiren Popat

Software Engineer (Python Developer)

@pubpub-zz
Copy link
Collaborator

I am writing to suggest a small improvement to the existing implementation of the rectangle function.

Currently, the function allows users to draw a rectangle on a PDF and specify the interior color of the rectangle using the interior_color argument. However, there is no option to specify the fill color of the rectangle.

Rather than create set_border_colour function we can create colour color keyword argument to the rectangle function to make the function more user-friendly , I would like to suggest adding a "color" keyword argument to the rectangle function. This would allow users to specify both the border and fill color of the rectangle using a single function call.

the approach I've proposed will be very efficient in this case adding the new function we will get:

AnnotationBuilder.rectangle((100,200,300,400),
     ).set_border_color("red",
     ).set_interior_color("yellow")

but without extra mods

AnnotationBuilder.ellipse((100,200,300,400),
     ).set_border_color("red",
     ).set_interior_color("yellow")

Do you agree ?

@hirenpopat67
Copy link
Author

@pubpub-zz Yes, I agree. Your proposed approach of using the AnnotationBuilder class to create annotations,while setting the border and interior colors, is efficient and should work well in this case. The method chaining syntax you've used makes the code concise and easy to read.

@pubpub-zz
Copy link
Collaborator

based on #1740, I recommend set_color()

@MartinThoma
Copy link
Member

I think we are now having a way more complicated discussion within this PR. Let's move that to #1741 :-)

@MartinThoma MartinThoma marked this pull request as draft March 26, 2023 09:50
@MartinThoma
Copy link
Member

Please wait with this PR until we come to a conclusion with #1741

It might be #1745 - let's wait another week for opinions on that :-) (please also share your opinion about the #1745

@hirenpopat67
Copy link
Author

hirenpopat67 commented Mar 26, 2023

Please wait with this PR until we come to a conclusion with #1741

It might be #1745 - let's wait another week for opinions on that :-) (please also share your opinion about the #1745

@MartinThoma
Thanks for asking my opinion i have shared #1741

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants