6 lines
6.4 KiB
JavaScript
6 lines
6.4 KiB
JavaScript
/**
|
|
* @monogrid/gainmap-js v3.4.0
|
|
* With ❤️, by MONOGRID <gainmap@monogrid.com>
|
|
*/
|
|
const t=216,e=225,n=226,a=218,r={SIGNATURE:new Uint8Array([77,80,70,0]),BIG_ENDIAN:new Uint8Array([77,77]),TIFF_MAGIC:42,NUM_PICTURES:2,TAG_COUNT:3,TAG_SIZE:12,MP_ENTRY_SIZE:16},s=45056,i=45057,p=45058,o=7,h=4,g=0,m=536870912,c=new Uint8Array([48,49,48,48]);function d(){return r.SIGNATURE.length+2+2+4+2+r.TAG_COUNT*r.TAG_SIZE+4+r.NUM_PICTURES*r.MP_ENTRY_SIZE}const u="Primary",f="GainMap",M="image/jpeg";function l(t){return String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function U(t,e,n,a){const r=new DataView(t.buffer,t.byteOffset,t.byteLength);if(r.setUint8(e++,255),r.setUint8(e++,n),a&&a.length>0){const n=a.length+2;r.setUint16(e,n,!1),e+=2,t.set(a,e),e+=a.length}return e}function x(x){const{sdr:y,gainMap:w,metadata:T,exif:I,icc:A}=x;if("image/jpeg"!==y.mimeType)throw new Error("SDR image must be JPEG format");if("image/jpeg"!==w.mimeType)throw new Error("Gain map image must be JPEG format");const E=function(n){const r=new DataView(n.buffer,n.byteOffset,n.byteLength);if(255!==r.getUint8(0)||r.getUint8(1)!==t)return null;let s=2;const i="Exif\0\0";for(;s<n.length-1&&255===r.getUint8(s);){const t=r.getUint8(s+1);if(t===a)break;if(t===e){const t=r.getUint16(s+2,!1),e=s+4;let a=!0;for(let t=0;t<6;t++)if(e+t>=n.length||n[e+t]!==i.charCodeAt(t)){a=!1;break}if(a){const a=t-2;return{data:n.slice(e,e+a),pos:s,size:t+2}}}s+=2+r.getUint16(s+2,!1)}return null}(y.data);if(E&&I)throw new Error("Primary image already contains EXIF data, cannot add external EXIF");let C=y.data,S=I;E&&(C=function(t,e,n){const a=t.length-n,r=new Uint8Array(a);return r.set(t.subarray(0,e),0),r.set(t.subarray(e+n),e),r}(y.data,E.pos,E.size),S=E.data);const R=function(t){const e=[],n=t.hdrCapacityMin,a=t.hdrCapacityMax,r=t=>Array.isArray(t)?t.reduce((t,e)=>t+e,0)/t.length:t,s=r(t.gainMapMin),i=r(t.gainMapMax),p=r(t.gamma),o=r(t.offsetSdr),h=r(t.offsetHdr);return e.push('<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>'),e.push('<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.1.2">'),e.push(' <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">'),e.push(" <rdf:Description"),e.push(' xmlns:hdrgm="http://ns.adobe.com/hdr-gain-map/1.0/"'),e.push(` hdrgm:Version="${l(t.version)}"`),e.push(` hdrgm:GainMapMin="${l(s)}"`),e.push(` hdrgm:GainMapMax="${l(i)}"`),e.push(` hdrgm:Gamma="${l(p)}"`),e.push(` hdrgm:OffsetSDR="${l(o)}"`),e.push(` hdrgm:OffsetHDR="${l(h)}"`),e.push(` hdrgm:HDRCapacityMin="${l(n)}"`),e.push(` hdrgm:HDRCapacityMax="${l(a)}"`),e.push(' hdrgm:BaseRenditionIsHDR="False"'),e.push(' rdf:about=""/>'),e.push(" </rdf:RDF>"),e.push("</x:xmpmeta>"),e.push('<?xpacket end="w"?>'),e.join("\n")}(T),b=(new TextEncoder).encode(R),G=(new TextEncoder).encode("http://ns.adobe.com/xap/1.0/\0"),D=6+G.length+b.length+(w.data.length-2),N=function(t,e){const n=[];return n.push('<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>'),n.push('<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.1.2">'),n.push(' <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">'),n.push(" <rdf:Description"),n.push(' xmlns:Container="http://ns.google.com/photos/1.0/container/"'),n.push(' xmlns:Item="http://ns.google.com/photos/1.0/container/item/"'),n.push(' xmlns:hdrgm="http://ns.adobe.com/hdr-gain-map/1.0/"'),n.push(` hdrgm:Version="${l(e.version)}"`),n.push(' rdf:about="">'),n.push(" <Container:Directory>"),n.push(" <rdf:Seq>"),n.push(' <rdf:li rdf:parseType="Resource">'),n.push(" <Container:Item"),n.push(` Item:Semantic="${u}"`),n.push(` Item:Mime="${M}"/>`),n.push(" </rdf:li>"),n.push(' <rdf:li rdf:parseType="Resource">'),n.push(" <Container:Item"),n.push(` Item:Semantic="${f}"`),n.push(` Item:Mime="${M}"`),n.push(` Item:Length="${t}"/>`),n.push(" </rdf:li>"),n.push(" </rdf:Seq>"),n.push(" </Container:Directory>"),n.push(" </rdf:Description>"),n.push(" </rdf:RDF>"),n.push("</x:xmpmeta>"),n.push('<?xpacket end="w"?>'),n.join("\n")}(D,T),_=(new TextEncoder).encode(N),$=new Uint8Array(G.length+_.length);$.set(G,0),$.set(_,G.length);const P=d();let F=2;S&&(F+=4+S.length),F+=4+$.length,A&&(F+=4+A.length),F+=4+P,F+=C.length-2,F+=D;const k=F-D,j=function(t,e,n,a){const u=d(),f=new ArrayBuffer(u),M=new DataView(f),l=new Uint8Array(f);let U=0;l.set(r.SIGNATURE,U),U+=r.SIGNATURE.length,l.set(r.BIG_ENDIAN,U);const x=!1;U+=2,M.setUint16(U,r.TIFF_MAGIC,x),U+=2,M.setUint32(U,8,x),U+=4,M.setUint16(U,r.TAG_COUNT,x),U+=2,M.setUint16(U,s,x),U+=2,M.setUint16(U,o,x),U+=2,M.setUint32(U,c.length,x),U+=4,l.set(c,U),U+=4,M.setUint16(U,i,x),U+=2,M.setUint16(U,h,x),U+=2,M.setUint32(U,1,x),U+=4,M.setUint32(U,r.NUM_PICTURES,x),U+=4,M.setUint16(U,p,x),U+=2,M.setUint16(U,o,x),U+=2,M.setUint32(U,r.MP_ENTRY_SIZE*r.NUM_PICTURES,x),U+=4;const y=U-r.SIGNATURE.length+4+4;return M.setUint32(U,y,x),U+=4,M.setUint32(U,0,x),U+=4,M.setUint32(U,g|m,x),U+=4,M.setUint32(U,t,x),U+=4,M.setUint32(U,e,x),U+=4,M.setUint16(U,0,x),U+=2,M.setUint16(U,0,x),U+=2,M.setUint32(U,g,x),U+=4,M.setUint32(U,n,x),U+=4,M.setUint32(U,a,x),U+=4,M.setUint16(U,0,x),U+=2,M.setUint16(U,0,x),l}(k,0,D,k-(2+(S?4+S.length:0)+2+2+$.length+(A?4+A.length:0)+2+2+4)),H=new Uint8Array(F);let z=0;z=U(H,z,t),S&&(z=U(H,z,e,S)),z=U(H,z,e,$),A&&(z=U(H,z,n,A)),z=U(H,z,n,j),H.set(C.subarray(2),z),z+=C.length-2,z=U(H,z,t);const O=new Uint8Array(G.length+b.length);return O.set(G,0),O.set(b,G.length),z=U(H,z,e,O),H.set(w.data.subarray(2),z),H}const y=t=>{if("image/jpeg"!==t.sdr.mimeType)throw new Error("This function expects an SDR image compressed in jpeg");if("image/jpeg"!==t.gainMap.mimeType)throw new Error("This function expects a GainMap image compressed in jpeg");const e={version:"1.0",gainMapMin:t.gainMapMin,gainMapMax:t.gainMapMax,gamma:t.gamma,offsetSdr:t.offsetSdr,offsetHdr:t.offsetHdr,hdrCapacityMin:t.hdrCapacityMin,hdrCapacityMax:t.hdrCapacityMax,minContentBoost:Array.isArray(t.gainMapMin)?Math.pow(2,t.gainMapMin.reduce((t,e)=>t+e,0)/t.gainMapMin.length):Math.pow(2,t.gainMapMin),maxContentBoost:Array.isArray(t.gainMapMax)?Math.pow(2,t.gainMapMax.reduce((t,e)=>t+e,0)/t.gainMapMax.length):Math.pow(2,t.gainMapMax)};return x({sdr:t.sdr,gainMap:t.gainMap,metadata:e})};export{y as encodeJPEGMetadata};
|