1"use strict";(globalThis.webpackChunkopensource_contentauth_org=globalThis.webpackChunkopensource_contentauth_org||[]).push([[5415],{3072:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>c,contentTitle:()=>a,default:()=>h,frontMatter:()=>i,metadata:()=>t,toc:()=>l});const t=JSON.parse('{"id":"sdk-repos/trustmark/README","title":"TrustMark","description":"This repository contains the official, open source implementation of TrustMark watermarking for the Content Authenticity Initiative (CAI) as described in:","source":"@site/docs/sdk-repos/trustmark/README.md","sourceDirName":"sdk-repos/trustmark","slug":"/sdk-repos/trustmark/","permalink":"/docs/sdk-repos/trustmark/","draft":false,"unlisted":false,"editUrl":"https://github.com/adobe/trustmark/edit/main/README.md","tags":[],"version":"current","frontMatter":{},"sidebar":"docs","previous":{"title":"TrustMark watermarking","permalink":"/docs/durable-cr/trustmark-intro"},"next":{"title":"Configuration","permalink":"/docs/sdk-repos/trustmark/python/CONFIG"}}');var s=n(4848),o=n(8453);const i={},a="TrustMark",c={},l=[{value:"Overview",id:"overview",level:2},{value:"Installation",id:"installation",level:2},{value:"Prerequisite",id:"prerequisite",level:3},{value:"Installing from PyPI",id:"installing-from-pypi",level:3},{value:"Quickstart",id:"quickstart",level:2},{value:"Run the example",id:"run-the-example",level:3},{value:"Example script",id:"example-script",level:3},{value:"Data schema",id:"data-schema",level:2},{value:"Citation",id:"citation",level:2},{value:"License",id:"license",level:2}];function d(e){const r={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",section:"section",strong:"strong",sup:"sup",ul:"ul",...(0,o.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(r.header,{children:(0,s.jsx)(r.h1,{id:"trustmark",children:"TrustMark"})}),"\n",(0,s.jsx)(r.p,{children:"This repository contains the official, open source implementation of TrustMark watermarking for the Content Authenticity Initiative (CAI) as described in:"}),"\n",(0,s.jsxs)(r.p,{children:[(0,s.jsx)(r.a,{href:"https://arxiv.org/abs/2311.18297",children:(0,s.jsx)(r.strong,{children:"TrustMark - Universal Watermarking for Arbitrary Resolution Images"})})," (",(0,s.jsx)(r.code,{children:"arXiv:2311.18297"}),") by ",(0,s.jsx)(r.a,{href:"https://www.surrey.ac.uk/people/tu-bui",children:"Tu Bui"}),(0,s.jsx)(r.sup,{children:(0,s.jsx)(r.a,{href:"#user-content-fn-1",id:"user-content-fnref-1","data-footnote-ref":!0,"aria-describedby":"footnote-label",children:"1"})}),", ",(0,s.jsx)(r.a,{href:"https://research.adobe.com/person/shruti-agarwal/",children:"Shruti Agarwal"}),(0,s.jsx)(r.sup,{children:(0,s.jsx)(r.a,{href:"#user-content-fn-2",id:"user-content-fnref-2","data-footnote-ref":!0,"aria-describedby":"footnote-label",children:"2"})}),", and ",(0,s.jsx)(r.a,{href:"https://www.collomosse.com",children:"John Collomosse"}),(0,s.jsx)(r.sup,{children:(0,s.jsx)(r.a,{href:"#user-content-fn-1",id:"user-content-fnref-1-2","data-footnote-ref":!0,"aria-describedby":"footnote-label",children:"1"})})," ",(0,s.jsx)(r.sup,{children:(0,s.jsx)(r.a,{href:"#user-content-fn-2",id:"user-content-fnref-2-2","data-footnote-ref":!0,"aria-describedby":"footnote-label",children:"2"})}),"."]}),"\n",(0,s.jsxs)(r.p,{children:["and later published at ",(0,s.jsx)(r.a,{href:"https://iccv.thecvf.com/virtual/2025/poster/1714",children:"ICCV 2025"})," as ",(0,s.jsx)(r.a,{href:"https://collomosse.com/pubs/Bui-ICCV-2025.pdf",children:(0,s.jsx)(r.strong,{children:"TrustMark: Robust Watermarking and Watermark Removal for Arbitrary Resolution Images"})}),"."]}),"\n",(0,s.jsx)(r.h2,{id:"overview",children:"Overview"}),"\n",(0,s.jsx)(r.p,{children:"This repository contains the following directories:"}),"\n",(0,s.jsxs)(r.ul,{children:["\n",(0,s.jsxs)(r.li,{children:[(0,s.jsx)(r.code,{children:"/python"}),": Python implementation of TrustMark for encoding, decoding and removing image watermarks (using PyTorch). For information on configuring TrustMark in Python, see ",(0,s.jsx)(r.a,{href:"/docs/sdk-repos/trustmark/python/CONFIG",children:"Configuring TrustMark"}),"."]}),"\n",(0,s.jsxs)(r.li,{children:[(0,s.jsx)(r.code,{children:"/js"}),": Javascript implementation of TrustMark decoding of image watermarks (using ONNX). For more information, see ",(0,s.jsx)(r.a,{href:"/docs/sdk-repos/trustmark/js/",children:"TrustMark - JavaScript implementation"}),"."]}),"\n",(0,s.jsxs)(r.li,{children:[(0,s.jsx)(r.code,{children:"/rust"}),": Rust implementation of TrustMark. for more information, see ",(0,s.jsx)(r.a,{href:"/docs/sdk-repos/trustmark/rust/",children:"TrustMark \u2014 Rust implementation"}),"."]}),"\n",(0,s.jsxs)(r.li,{children:[(0,s.jsx)(r.code,{children:"/c2pa"}),": Python example of how to indicate the presence of a TrustMark watermark in a C2PA manifest. For more information, see ",(0,s.jsx)(r.a,{href:"/docs/sdk-repos/trustmark/c2pa/",children:"Using TrustMark with C2PA"}),"."]}),"\n"]}),"\n",(0,s.jsxs)(r.p,{children:["Model files (",(0,s.jsx)(r.strong,{children:"ckpt"}
1)," PyTorch file for Python and ",(0,s.jsx)(r.strong,{children:"onnx"})," ONNX file for JavaScript) are not packaged in this repository due to their size, but are downloaded upon first use. See the code for ",(0,s.jsx)(r.a,{href:"https://github.com/adobe/trustmark/blob/010a8f3bf885eec6f2aaa418380afc41d68bb3e5/python/trustmark/trustmark.py#L29",children:"URLs and md5 hashes"})," for a direct download link. Note that the location path was updated from Netlify to S3 in April 2026."]}),"\n",(0,s.jsx)(r.p,{children:"More information:"}),"\n",(0,s.jsxs)(r.ul,{children:["\n",(0,s.jsxs)(r.li,{children:["For answers to common questions, see the ",(0,s.jsx)(r.a,{href:"/docs/sdk-repos/trustmark/FAQ",children:"FAQ"}),"."]}),"\n",(0,s.jsxs)(r.li,{children:["For information on configuring TrustMark in Python, see ",(0,s.jsx)(r.a,{href:"/docs/sdk-repos/trustmark/python/CONFIG",children:"Configuring TrustMark"}),"."]}),"\n"]}),"\n",(0,s.jsx)(r.h2,{id:"installation",children:"Installation"}),"\n",(0,s.jsx)(r.h3,{id:"prerequisite",children:"Prerequisite"}),"\n",(0,s.jsx)(r.p,{children:"You must have Python 3.8.5 or higher to use the TrustMark Python implementation."}),"\n",(0,s.jsx)(r.h3,{id:"installing-from-pypi",children:"Installing from PyPI"}),"\n",(0,s.jsxs)(r.p,{children:["The easiest way to install TrustMark is from the ",(0,s.jsx)(r.a,{href:"https://pypi.org/project/trustmark/",children:"Python Package Index (PyPI)"})," by entering this command:"]}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{children:"pip install trustmark\n"})}),"\n",(0,s.jsxs)(r.p,{children:["Alternatively, after you've cloned the repository, you can install from the ",(0,s.jsx)(r.code,{children:"python"})," directory:"]}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{children:"cd trustmark/python\npip install .\n"})}),"\n",(0,s.jsx)(r.h2,{id:"quickstart",children:"Quickstart"}),"\n",(0,s.jsxs)(r.p,{children:["To get started quickly, run the ",(0,s.jsx)(r.code,{children:"python/test-decode.py"})," script that provides examples of watermarking several\nimage files from the ",(0,s.jsx)(r.code,{children:"images"})," directory."]}),"\n",(0,s.jsx)(r.h3,{id:"run-the-example",children:"Run the example"}),"\n",(0,s.jsx)(r.p,{children:"Run the example as follows:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-sh",children:"cd trustmark/python\npython test-decode.py\n"})}),"\n",(0,s.jsx)(r.p,{children:"You'll see output like this:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{children:"Initializing TrustMark watermarking with ECC using [cpu]\nExtracted secret: 1000000100001110000010010001011110010001011000100000100110110 (schema 1)\nPSNR = 50.357909\nNo secret after removal\n"})}),"\n",(0,s.jsx)(r.h3,{id:"example-script",children:"Example script"}),"\n",(0,s.jsxs)(r.p,{children:["The ",(0,s.jsx)(r.code,{children:"python/test-decode.py"})," script provides examples of watermarking a JPEG photo, a JPEG GenAI image, and an RGBA PNG image. The example uses TrustMark variant Q to encode the word ",(0,s.jsx)(r.code,{children:"mysecret"})," in ASCII7 encoding into the image ",(0,s.jsx)(r.code,{children:"ufo_240.jpg"})," which is then decoded, and then removed from the image."]}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-python",children:"from trustmark import TrustMark\nfrom PIL import Image\n\n# init\ntm=TrustMark(verbose=True, model_type='Q') # or try P\n\n# encoding example\ncover = Image.open('images/ufo_240.jpg').convert('RGB')\ntm.encode(cover, 'mysecret').save('ufo_240_Q.png')\n\n# decoding example\ncover = Image.open('images/ufo_240_Q.png').convert('RGB')\nwm_secret, wm_present, wm_schema = tm.decode(cover)\n\nif wm_present:\n print(f'Extracted secret: {wm_secret}')\nelse:\n print('No watermark decoded')\n\n# removal example\nstego = Image.open('images/ufo_240_Q.png').convert('RGB')\nim_recover = tm.remove_watermark(stego)\nim_recover.save('images/recovered.png')\n"})}),"\n",(0,s.jsx)(r.h2,{id:"data-schema",children:"Data schema"}),"\n",(0,s.jsx)(r.p,{children:"TrustMark encodes a payload (the watermark data embedded within the image) of 100 bits.\nYou can configure an error correction level over the raw 100 bits of payload to maintain reliability under transformations or noise."}),"\n",(0,s.jsx)(r.p,{children:"In payload encoding, the version bits comprise two reserved (unused) bits, and two bits encoding an integer value 0-3 that specifies the data schema as follows:"}),"\n",(0,s.jsxs)(r.ul,{children:["\n",(0,s.jsx)(r.li,{children:"0: BCH_SUPER"}),"\n",(0,s.jsx)(r.li,{children:"1: BCH_5"}),"\n",(0,s.jsx)(r.li,{children:"2: BCH_4"}),"\n",(0,s.jsx)(r.li,{children:"3: BCH_3"}),"\n"]}),"\n",(0,s.jsxs)(r.p,{children:["For more details and information on configuring the encoding mode in Python, see ",(0,s.jsx)(r.a,{href:"/docs/sdk-repos/trustmark/python/CONFIG",children:"Configuring TrustMark"}),"."]}),"\n",(0,s.jsx)(r.h2,{id:"citation",children:"Citation"}),"\n",(0,s.jsx)(r.p,{children:"If you find this work useful, please give us a star \u2b50 and cite the repository and/or TrustMark paper, preferrably as follows:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{children:"@inproceedings{Trustmark-ICCV-2025,\n title = {TrustMark: Robust Watermarking and Watermark Removal for Arbitrary Resolution Images},\n author={Bui, Tu and Agarwal, Shruti and Collomosse, John},\n booktitle = {IEEE International Conference on Computer Vision (ICCV)},\n year = {2025},\n month = oct\n}\n"})}),"\n",(0,s.jsx)(r.p,{children:"or cite the earlier ArXiv version:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{children:'@article{Trustmark-ArXiv-2023,\ntitle={Trustmark: Universal Watermarking for Arbitrary Resolution Images},\nauthor={Bui, Tu and Agarwal, Shruti and Collomosse, John},\njournal = {ArXiv e-prints}
1,\narchivePrefix = "arXiv",\neprint = {2311.18297},\nyear = 2023,\nmonth = nov\n}\n'})}),"\n",(0,s.jsx)(r.h2,{id:"license",children:"License"}),"\n",(0,s.jsxs)(r.p,{children:["This package is is distributed under the terms of the ",(0,s.jsx)(r.a,{href:"https://github.com/adobe/trustmark/blob/main/LICENSE",children:"MIT license"}),". The MIT license covers both the code in this repo and the model files which are downloaded upon first use."]}),"\n","\n",(0,s.jsxs)(r.section,{"data-footnotes":!0,className:"footnotes",children:[(0,s.jsx)(r.h2,{className:"sr-only",id:"footnote-label",children:"Footnotes"}),"\n",(0,s.jsxs)(r.ol,{children:["\n",(0,s.jsxs)(r.li,{id:"user-content-fn-1",children:["\n",(0,s.jsxs)(r.p,{children:[(0,s.jsx)(r.a,{href:"https://decade.ac.uk/",children:"DECaDE"})," Centre for the Decentralized Digital Economy, University of Surrey, UK. ",(0,s.jsx)(r.a,{href:"#user-content-fnref-1","data-footnote-backref":"","aria-label":"Back to reference 1",className:"data-footnote-backref",children:"\u21a9"})," ",(0,s.jsxs)(r.a,{href:"#user-content-fnref-1-2","data-footnote-backref":"","aria-label":"Back to reference 1-2",className:"data-footnote-backref",children:["\u21a9",(0,s.jsx)(r.sup,{children:"2"})]})]}),"\n"]}),"\n",(0,s.jsxs)(r.li,{id:"user-content-fn-2",children:["\n",(0,s.jsxs)(r.p,{children:[(0,s.jsx)(r.a,{href:"https://research.adobe.com/",children:"Adobe Research"}),", San Jose, CA. ",(0,s.jsx)(r.a,{href:"#user-content-fnref-2","data-footnote-backref":"","aria-label":"Back to reference 2",className:"data-footnote-backref",children:"\u21a9"})," ",(0,s.jsxs)(r.a,{href:"#user-content-fnref-2-2","data-footnote-backref":"","aria-label":"Back to reference 2-2",className:"data-footnote-backref",children:["\u21a9",(0,s.jsx)(r.sup,{children:"2"})]})]}),"\n"]}),"\n"]}),"\n"]})]})}function h(e={}){const{wrapper:r}={...(0,o.R)(),...e.components};return r?(0,s.jsx)(r,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,r,n)=>{n.d(r,{R:()=>i,x:()=>a});var t=n(6540);const s={},o=t.createContext(s);function i(e){const r=t.useContext(o);return t.useMemo(function(){return"function"==typeof e?e(r):{...r,...e}},[r,e])}function a(e){let r;return r=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),t.createElement(o.Provider,{value:r},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.