Hi Brandon,
There are many ways of doing watermarking and which one works for you will actually depend on how much code and how you want to solve the issue with real-time performance/caching/where-you-want-to-water-mark (many layers). This is the most simple tut I could find for you
http://www.rainbodesign.com/pub/watermark/ (forget the CSS one, too simple+bad)
This (our own) forum is actually an invaluable source of information (so many years). Look at this one
(2012!!)
Well: the way i would do it:
1.- In my own module: create a new/replacement callback datastream view access that targets specificly JP2 and/or OBJ. The idea here is to override islandora's default datastream provider with some extra logic but without the need to change every other module (or even djatoka) that are tied to being able to read JP2/OBJ datastreams. The override should do the following:
a) if the user is logged in, just bypass your logic and call the original menu router callback. So user asks OBJ, gets OBJ
b) if the user is anonymous, check if your object has a datastream called "WM" or any other name you want to use to store your watermarked image(which you don't have yet). You could also check for the existence of a CDN file that matches (or a file stored in drupal's tmp or public folder ) e.g.{$PID}_watermark.jp2. In case the DS or the file actually exist you serve that one, if not, well you can then generate dynamically via GD/imagemagic a watermark and populate that "WM" DS or the temporary file. If you want to go "pro" you can of course query all large image objects and pre-generate those and even add in your own module a derivative that creates the watermarked image based on that JP2.So user or djatoka asks for OBJ or JP2, gets WM
Whatever you do, the key is creating your own menu router that deals with OBJ and JP2 for anonymous, making the access to either the full image or the watermarked completely transparent to other modules
Hope this helps, just some ideas
D