@photivra/engine 2.8.1 → 2.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +60 -1
- package/CITATION.cff +1 -1
- package/README.md +8 -6
- package/SECURITY.md +1 -1
- package/dist/capture/export-jpeg.d.ts +19 -0
- package/dist/capture/export-jpeg.js +190 -108
- package/dist/capture/export-jpeg.js.map +1 -1
- package/dist/capture/native-environment-lean.js +19 -9
- package/dist/capture/native-environment-lean.js.map +1 -1
- package/dist/core/version.d.ts +1 -1
- package/dist/core/version.js +1 -1
- package/dist/core/version.js.map +1 -1
- package/dist/facade/expected-signal.d.ts +4 -1
- package/dist/facade/expected-signal.js +151 -31
- package/dist/facade/expected-signal.js.map +1 -1
- package/dist/facade/scene-radiance.d.ts +4 -1
- package/dist/facade/scene-radiance.js +4 -4
- package/dist/facade/scene-radiance.js.map +1 -1
- package/dist/facade/simulate-capture.d.ts +26 -1
- package/dist/facade/simulate-capture.js +102 -9
- package/dist/facade/simulate-capture.js.map +1 -1
- package/dist/facade/simulate-display-view.js +2 -1
- package/dist/facade/simulate-display-view.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/optics/diffraction-psf-profile.d.ts +19 -17
- package/dist/optics/diffraction-psf-profile.js +49 -18
- package/dist/optics/diffraction-psf-profile.js.map +1 -1
- package/dist/output/print-jpeg.d.ts +28 -1
- package/dist/output/print-jpeg.js +79 -7
- package/dist/output/print-jpeg.js.map +1 -1
- package/dist/sensor/stochastic-seed.d.ts +12 -0
- package/dist/sensor/stochastic-seed.js +25 -0
- package/dist/sensor/stochastic-seed.js.map +1 -1
- package/docs/API_REFERENCE.md +8 -1
- package/docs/QUICK_START.md +59 -0
- package/docs/api/capture-export-jpeg.md +10 -0
- package/docs/api/core-version.md +1 -1
- package/docs/api/exports.json +37 -2
- package/docs/api/facade-scene-radiance.md +2 -1
- package/docs/api/facade-simulate-capture.md +28 -0
- package/docs/api/optics-diffraction-psf-profile.md +1 -1
- package/docs/api/output-print-jpeg.md +41 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"print-jpeg.js","sourceRoot":"","sources":["../../src/output/print-jpeg.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Print JPEG export: downsamples an SDR image by exact area averaging, then writes a baseline JPEG\n * with an ICC colour profile. Bounded in size; the encoder is written for this project.\n */\nimport { createExportJpegEncoder, EXPORT_JPEG_ENCODER_ID } from \"../capture/export-jpeg.js\";\nimport { packExportJpegExif, exportTiffNumbers, exportTiffAscii, exportTiffRationals, type ExportTiffTag } from \"../capture/export-tiff.js\";\nimport { createSrgbIccProfile, SRGB_ICC_PROFILE_VERSION } from \"../color/srgb-icc.js\";\nimport { decodeSrgbComponent, encodeSrgbComponent } from \"../color/srgb-transfer.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { requireAllowlistedRecord, requirePublicOpaqueId } from \"../core/record-validation.js\";\nimport { freezeOwnedData } from \"../core/owned-data.js\";\nimport { FULL_RESOLUTION_CEILING_PIXELS, resolveRaisedLimit, scaleBudgetCeiling } from \"../core/pixel-limits.js\";\nimport type { NativeRawTaskState } from \"../capture/native-raw.js\";\nimport type { RasterRect } from \"./capture-geometry.js\";\nexport const PRINT_JPEG_SCHEMA_VERSION=\"0.2.0\" as const;\n/**\n * Admission limits. `maximumPixels` is the default source limit; a request may raise it with its own\n * `maximumPixels`, up to `ceilingPixels`. A raised limit raises the `maximumEncodedBytes` ceiling in proportion\n * (256 000 000 bytes per 24 000 000 source pixels).\n */\nexport const PRINT_JPEG_LIMITS=Object.freeze({maximumPixels:24_000_000,ceilingPixels:FULL_RESOLUTION_CEILING_PIXELS,maximumDimension:16_384,\n maximumEncodedBytes:256_000_000,maximumProviderReads:1_000_000});\nlet srgbDecode:Float64Array|undefined;\n/** decodeSrgbComponent(v/255) for every 8-bit code v, computed once with the same function (identical values). */\nfunction srgbDecodeTable():Float64Array{return srgbDecode??=Float64Array.from({length:256},(_,v)=>decodeSrgbComponent(v/255));}\nexport interface PrintJpegSource {\n captureId:string;imageStateId:string;artifactId:string;sha256:string;\n width:number;height:number;\n encoding:\"encoded-srgb-8-rgb\";\n}\nexport interface PrintJpegInput {\n source:PrintJpegSource;\n /** Integer crop in the oriented output source image, not in sensor or CFA (colour filter array) coordinates. */\n crop:RasterRect;\n outputWidth:number;outputHeight:number;\n quantizationStep:number;\n maximumEncodedBytes:number;\n /**\n * Maximum provider `readTile` calls. The task reads each crop pixel exactly once, in tiles of at most\n * 256 x 32 pixels aligned to the crop origin, so it needs ceil(crop.height/32) x ceil(crop.width/256)\n * reads; a smaller budget fails before the first read.\n */\n maximumProviderReads:number;\n /**\n * Optional physical print density in pixels per inch (1..65535) from the caller's print plan. When present,\n * EXIF IFD0 records XResolution = YResolution = this value as a RATIONAL with ResolutionUnit = 2 (inches),\n * and JFIF APP0 records units = 1 with the nearest integer density (JFIF density fields are uint16).\n * When omitted no physical size is claimed: JFIF keeps units = 0 with a 1:1 aspect ratio. Exif 2.32 makes\n * the IFD0 resolution tags mandatory and says an unknown resolution \"shall\" be recorded as 72 dpi, so IFD0\n * carries 72/1 with ResolutionUnit = 2; that is the standard's unknown-resolution marker, not a print size.\n */\n pixelsPerInch?:number;\n /**\n * Optional opt-in source pixel limit for large images: an integer from 1 to `PRINT_JPEG_LIMITS.ceilingPixels`.\n * Default `PRINT_JPEG_LIMITS.maximumPixels` (24 000 000). When given it is recorded in the XMP export plan, like the\n * other admission budgets; the image data are unchanged.\n */\n maximumPixels?:number;\n}\nexport interface PrintJpegTileRequest {source:PrintJpegSource;x:number;y:number;width:number;height:number}\nexport interface PrintJpegTile extends PrintJpegTileRequest {samples:Uint8Array}\nexport interface PrintJpegProvider {\n readTile(request:Readonly<PrintJpegTileRequest>,signal:AbortSignal):Promise<PrintJpegTile>;\n yieldControl(signal:AbortSignal):Promise<void>;\n}\nexport interface PrintJpegOutput {\n schemaVersion:typeof PRINT_JPEG_SCHEMA_VERSION;\n input:PrintJpegInput;\n mediaType:\"image/jpeg\";\n bytes:Uint8Array;\n iccProfileVersion:typeof SRGB_ICC_PROFILE_VERSION;\n width:number;height:number;\n resampling:\"exact-area-average-in-decoded-linear-light\";\n sourceStage:\"post-SDR-8-bit-quantization\";\n digitalUpscalingApplied:false;\n sourceBytesVerified:false;\n /** Provider calls made: ceil(crop.height/32) x ceil(crop.width/256) tiles, each crop pixel read once. */\n providerReads:number;\n /** Byte behaviour of the baseline encoder that produced `bytes`. */\n encoderId:typeof EXPORT_JPEG_ENCODER_ID;\n}\nexport interface PrintJpegTask {\n readonly state:NativeRawTaskState;\n run():Promise<void>;cancel():void;dispose():void;takeOutput():PrintJpegOutput;\n}\n/** Exactly n/1 for a whole-number density; otherwise the shared bounded decimal-fraction approximation. */\nfunction resolutionRational(id:number,ppi:number):ExportTiffTag {\n if(!Number.isSafeInteger(ppi))return exportTiffRationals(id,false,[ppi]);\n const data=new Uint8Array(8),view=new DataView(data.buffer);view.setUint32(0,ppi,true);view.setUint32(4,1,true);\n return {id,type:5,count:1,data};\n}\n/**\n * Exif 2.32 APP1 for a compressed primary image with every mandatory tag (CIPA DC-008-2019 Tables 17-18):\n * IFD0 Orientation, X/YResolution + ResolutionUnit, Software, YCbCrPositioning; Exif IFD ExifVersion \"0232\",\n * ComponentsConfiguration, FlashpixVersion \"0100\", ColorSpace sRGB, PixelX/YDimension. Without a planned\n * density the resolution tags carry the standard's \"unknown resolution\" value of 72 dpi.\n */\nfunction printExif(plan:PrintJpegInput):Uint8Array {\n const ppi=plan.pixelsPerInch;\n const resolution=ppi===undefined ? [] : [resolutionRational(282,ppi),resolutionRational(283,ppi),exportTiffNumbers(296,3,[2])];\n return packExportJpegExif([exportTiffNumbers(274,3,[1]),...resolution,exportTiffAscii(305,\"Photivra Print JPEG\")],\n [exportTiffNumbers(40961,3,[1])],{pixelWidth:plan.outputWidth,pixelHeight:plan.outputHeight});\n}\nfunction integer(v:unknown,min=1):number {\n if(typeof v!==\"number\"||!Number.isSafeInteger(v)||v<min)throw new InvalidConfigurationError(\"Print raster/budgets require safe integers.\");return v;\n}\n/** Validates the input only. Source detail, perception and printer suitability are checked by separate APIs. */\nexport function parsePrintJpegInput(input:PrintJpegInput):PrintJpegInput {\n const r=requireAllowlistedRecord(input,[\"source\",\"crop\",\"outputWidth\",\"outputHeight\",\"quantizationStep\",\"maximumEncodedBytes\",\"maximumProviderReads\",\"pixelsPerInch\",\"maximumPixels\"],\"Invalid Print JPEG input.\");\n const s=requireAllowlistedRecord(r.source,[\"captureId\",\"imageStateId\",\"artifactId\",\"sha256\",\"width\",\"height\",\"encoding\"],\"Invalid Print source.\");\n if(typeof s.sha256!==\"string\"||!/^[a-f0-9]{64}$/.test(s.sha256)||s.encoding!==\"encoded-srgb-8-rgb\")throw new InvalidConfigurationError(\"Print requires identified encoded sRGB source bytes.\");\n const source:PrintJpegSource={captureId:requirePublicOpaqueId(s.captureId,\"Invalid capture ID.\"),imageStateId:requirePublicOpaqueId(s.imageStateId,\"Invalid image state ID.\"),artifactId:requirePublicOpaqueId(s.artifactId,\"Invalid artifact ID.\"),sha256:s.sha256,width:integer(s.width),height:integer(s.height),encoding:s.encoding};\n const c=requireAllowlistedRecord(r.crop,[\"x\",\"y\",\"width\",\"height\"],\"Invalid Print crop.\"),crop={x:integer(c.x,0),y:integer(c.y,0),width:integer(c.width),height:integer(c.height)};\n const outputWidth=integer(r.outputWidth),outputHeight=integer(r.outputHeight),quantizationStep=integer(r.quantizationStep),maximumEncodedBytes=integer(r.maximumEncodedBytes),maximumProviderReads=integer(r.maximumProviderReads);\n const L=PRINT_JPEG_LIMITS,maximumPixels=resolveRaisedLimit(r.maximumPixels,L.maximumPixels,L.ceilingPixels,\"Print maximumPixels must be an integer from 1 to \"+L.ceilingPixels+\".\");\n const encodedBytesCeiling=r.maximumPixels===undefined?L.maximumEncodedBytes:scaleBudgetCeiling(L.maximumEncodedBytes,maximumPixels);\n if(source.width>L.maximumDimension||source.height>L.maximumDimension||source.width*source.height>maximumPixels||crop.x+crop.width>source.width||crop.y+crop.height>source.height||\n outputWidth>crop.width||outputHeight>crop.height||quantizationStep>255||maximumEncodedBytes>encodedBytesCeiling||maximumProviderReads>L.maximumProviderReads||\n Math.abs(outputWidth*crop.height-outputHeight*crop.width)>.5*(crop.width+crop.height))throw new InvalidConfigurationError(\"Print requires bounded native/downsampled aspect-preserving crop output.\");\n const ppi=r.pixelsPerInch;\n if(ppi!==undefined&&(typeof ppi!==\"number\"||!Number.isFinite(ppi)||ppi<1||ppi>65535))throw new InvalidConfigurationError(\"Print density requires finite pixels per inch from 1 to 65535.\");\n return freezeOwnedData({source,crop,outputWidth,outputHeight,quantizationStep,maximumEncodedBytes,maximumProviderReads,...(ppi===undefined ? {} : {pixelsPerInch:ppi}),\n ...(r.maximumPixels===undefined ? {} : {maximumPixels})});\n}\n/** Creates the export task. Filtering weights each source pixel by its exact area overlap, after decoding the declared 8-bit SDR source. */\nexport function createPrintJpegTask(input:PrintJpegInput,provider:PrintJpegProvider):PrintJpegTask {\n const plan=parsePrintJpegInput(input);\n if(!provider||typeof provider.readTile!==\"function\"||typeof provider.yieldControl!==\"function\")throw new InvalidConfigurationError(\"Print export requires source reader and host yields.\");\n const read=provider.readTile.bind(provider),yieldControl=provider.yieldControl.bind(provider),abort=new AbortController();\n let state:NativeRawTaskState=\"ready\",output:PrintJpegOutput|null=null,encoder:ReturnType<typeof createExportJpegEncoder>|undefined;\n function check():void{if(abort.signal.aborted)throw new InvalidConfigurationError(\"Print export aborted.\");}\n function release():void{encoder?.dispose();encoder=undefined;output?.bytes.fill(0);output=null;}\n return {get state():NativeRawTaskState{return state;},\n async run():Promise<void>{\n if(state!==\"ready\")throw new InvalidConfigurationError(\"Print export is single-use.\");state=\"running\";\n try{\n const exif=printExif(plan);\n const escaped=JSON.stringify(plan).replaceAll(\"&\",\"&\").replaceAll('\"',\""\").replaceAll(\"<\",\"<\").replaceAll(\">\",\">\");\n const xmp=new TextEncoder().encode('<x:xmpmeta xmlns:x=\"adobe:ns:meta/\"><rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"><rdf:Description rdf:about=\"\" xmlns:photivra=\"https://photivra.com/ns/simulation/1.0/\" photivra:PrintExportPlan=\"'+escaped+'\" photivra:SourceBytesVerified=\"False\"/></rdf:RDF></x:xmpmeta>');\n encoder=createExportJpegEncoder({width:plan.outputWidth,height:plan.outputHeight,quantizationStep:plan.quantizationStep,maximumOutputBytes:plan.maximumEncodedBytes,icc:createSrgbIccProfile(),exif,xmp,\n ...(plan.pixelsPerInch===undefined ? {} : {densityDotsPerInch:Math.round(plan.pixelsPerInch)})});\n const scaleX=plan.crop.width/plan.outputWidth,scaleY=plan.crop.height/plan.outputHeight,area=scaleX*scaleY;\n const cropRight=plan.crop.x+plan.crop.width,cropBottom=plan.crop.y+plan.crop.height,rowBytes=plan.crop.width*3;\n // Every crop pixel is read exactly once, in tiles of at most 256 x 32 aligned to the crop origin.\n const tilesPerBand=Math.ceil(plan.crop.width/256),requiredReads=Math.ceil(plan.crop.height/32)*tilesPerBand;\n if(requiredReads>plan.maximumProviderReads)throw new InvalidConfigurationError(\"Print source exceeds provider-read budget.\");\n // Rolling cache of whole crop-width source rows [cacheTop, cacheBottom): at most 63 rows are retained.\n const cache=new Uint8Array(Math.min(64,plan.crop.height)*rowBytes),lut=srgbDecodeTable();\n let reads=0,blocks=0,cacheTop=plan.crop.y,cacheBottom=plan.crop.y;\n const ensureRows=async(firstRow:number,rowCount:number):Promise<void>=>{\n const keepFrom=Math.min(Math.max(cacheTop,firstRow),cacheBottom);\n if(keepFrom>cacheTop){cache.copyWithin(0,(keepFrom-cacheTop)*rowBytes,(cacheBottom-cacheTop)*rowBytes);cacheTop=keepFrom;}\n while(cacheBottom<firstRow+rowCount){\n const bandHeight=Math.min(32,cropBottom-cacheBottom);\n if((cacheBottom+bandHeight-cacheTop)*rowBytes>cache.length)throw new InvalidConfigurationError(\"Print source traversal is not monotonic.\");\n for(let sx=plan.crop.x;sx<cropRight;sx+=256){\n check();++reads;\n const request=Object.freeze({source:plan.source,x:sx,y:cacheBottom,width:Math.min(256,cropRight-sx),height:bandHeight});\n const supplied=await read(request,abort.signal);check();\n const tile=requireAllowlistedRecord(supplied,[\"source\",\"x\",\"y\",\"width\",\"height\",\"samples\"],\"Invalid Print source tile.\");\n const source=requireAllowlistedRecord(tile.source,[\"captureId\",\"imageStateId\",\"artifactId\",\"sha256\",\"width\",\"height\",\"encoding\"],\"Invalid Print tile source.\");\n for(const key of Object.keys(plan.source) as (keyof PrintJpegSource)[])if(source[key]!==plan.source[key])throw new InvalidConfigurationError(\"Print source identity mismatch.\");\n for(const key of [\"x\",\"y\",\"width\",\"height\"] as const)if(tile[key]!==request[key])throw new InvalidConfigurationError(\"Print source rectangle mismatch.\");\n const samples=tile.samples;if(!(samples instanceof Uint8Array)||!(samples.buffer instanceof ArrayBuffer)||samples.length!==request.width*request.height*3||samples.buffer.byteLength!==samples.byteLength)throw new InvalidConfigurationError(\"Print source requires exact owned bounded RGB tile storage.\");\n for(let iy=0;iy<bandHeight;iy++)cache.set(samples.subarray(iy*request.width*3,(iy+1)*request.width*3),(cacheBottom-cacheTop+iy)*rowBytes+(sx-plan.crop.x)*3);\n // One output block can cover a megapixel of source, so also yield to the host while reading the source.\n if(reads%32===0){await yieldControl(abort.signal);check();}\n }\n cacheBottom+=bandHeight;\n }\n };\n const blocksX=Math.ceil(plan.outputWidth/8),sums=new Float64Array(blocksX*192);\n // At 1:1 every output pixel is one source pixel with weight exactly 1, so its sum is exactly lut[code] and its\n // sample is a function of the code alone: the same bytes from a 256-entry table, without the accumulation.\n const identity=scaleX===1&&scaleY===1;\n const direct=identity?Uint8Array.from(lut,(value)=>Math.min(255,Math.max(0,Math.round(encodeSrgbComponent(value)*255)))):undefined;\n if(direct)for(let by=0;by<plan.outputHeight;by+=8){\n check();\n const height=Math.min(8,plan.outputHeight-by);await ensureRows(plan.crop.y+by,height);check();\n for(let bx=0;bx<plan.outputWidth;bx+=8){\n const width=Math.min(8,plan.outputWidth-bx),samples:number[]=[];\n for(let y=0;y<8;y++){\n const row=(plan.crop.y+by+Math.min(y,height-1)-cacheTop)*rowBytes+bx*3;\n for(let x=0;x<8;x++){const index=row+Math.min(x,width-1)*3;samples.push(direct[cache[index]!]!,direct[cache[index+1]!]!,direct[cache[index+2]!]!);}\n }\n check();encoder.writeRgbBlock(samples);if(++blocks%32===0){await yieldControl(abort.signal);check();}\n }\n }\n else for(let by=0;by<plan.outputHeight;by+=8){\n check();sums.fill(0);\n const height=Math.min(8,plan.outputHeight-by),top=plan.crop.y+by*scaleY,bottom=by+height===plan.outputHeight?cropBottom:plan.crop.y+(by+height)*scaleY;\n // Accumulation order per output pixel is unchanged from the per-block reader: 32-row bands from\n // floor(top), then 256-column chunks from floor(left), then rows, then columns. Identical IEEE sums.\n for(let sy=Math.floor(top);sy<Math.ceil(bottom);sy+=32){\n const bandHeight=Math.min(32,Math.ceil(bottom)-sy);await ensureRows(sy,bandHeight);check();\n for(let bx=0,block=0;bx<plan.outputWidth;bx+=8,block++){\n const width=Math.min(8,plan.outputWidth-bx),left=plan.crop.x+bx*scaleX,right=bx+width===plan.outputWidth?cropRight:plan.crop.x+(bx+width)*scaleX,base=block*192;\n for(let sx=Math.floor(left);sx<Math.ceil(right);sx+=256){\n const chunkWidth=Math.min(256,Math.ceil(right)-sx);\n for(let iy=0;iy<bandHeight;iy++)for(let ix=0;ix<chunkWidth;ix++){\n const px=sx+ix,py=sy+iy;\n const firstX=Math.max(0,Math.floor((px-plan.crop.x)/scaleX)-bx),lastX=Math.min(width-1,Math.ceil((px+1-plan.crop.x)/scaleX)-bx-1);\n const firstY=Math.max(0,Math.floor((py-plan.crop.y)/scaleY)-by),lastY=Math.min(height-1,Math.ceil((py+1-plan.crop.y)/scaleY)-by-1);\n const index=(py-cacheTop)*rowBytes+(px-plan.crop.x)*3,r=lut[cache[index]!]!,g=lut[cache[index+1]!]!,b=lut[cache[index+2]!]!;\n for(let oy=firstY;oy<=lastY;oy++)for(let ox=firstX;ox<=lastX;ox++){\n const x0=plan.crop.x+(bx+ox)*scaleX,y0=plan.crop.y+(by+oy)*scaleY;\n const weight=Math.max(0,Math.min(px+1,x0+scaleX)-Math.max(px,x0))*Math.max(0,Math.min(py+1,y0+scaleY)-Math.max(py,y0))/area;\n const i=base+(oy*8+ox)*3;sums[i]=sums[i]!+r*weight;sums[i+1]=sums[i+1]!+g*weight;sums[i+2]=sums[i+2]!+b*weight;\n }\n }\n }\n }\n }\n for(let bx=0,block=0;bx<plan.outputWidth;bx+=8,block++){\n const width=Math.min(8,plan.outputWidth-bx),base=block*192,samples:number[]=[];\n for(let y=0;y<8;y++)for(let x=0;x<8;x++)for(let c=0;c<3;c++){\n const value=sums[base+(Math.min(y,height-1)*8+Math.min(x,width-1))*3+c]!;\n // Nearest code, ties up. Math.round is used because floor(x+0.5) wrongly rounds 0.49999999999999994 up.\n samples.push(Math.min(255,Math.max(0,Math.round(encodeSrgbComponent(value)*255))));\n }\n check();encoder.writeRgbBlock(samples);if(++blocks%32===0){await yieldControl(abort.signal);check();}\n }\n }\n await yieldControl(abort.signal);check();const bytes=encoder.finish();encoder=undefined;\n output={schemaVersion:PRINT_JPEG_SCHEMA_VERSION,input:plan,mediaType:\"image/jpeg\",bytes,iccProfileVersion:SRGB_ICC_PROFILE_VERSION,width:plan.outputWidth,height:plan.outputHeight,resampling:\"exact-area-average-in-decoded-linear-light\",sourceStage:\"post-SDR-8-bit-quantization\",digitalUpscalingApplied:false,sourceBytesVerified:false,providerReads:reads,encoderId:EXPORT_JPEG_ENCODER_ID};state=\"completed\";\n }catch(error){release();if(!abort.signal.aborted){state=\"failed\";abort.abort();}throw error;}\n },cancel():void{if(state===\"ready\"||state===\"running\"||state===\"completed\"){state=\"cancelled\";abort.abort();release();}},\n dispose():void{if(state!==\"transferred\"){state=\"disposed\";abort.abort();release();}},\n takeOutput():PrintJpegOutput{if(state!==\"completed\"||!output)throw new InvalidConfigurationError(\"Print JPEG unavailable.\");const value=output;output=null;state=\"transferred\";return value;}\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"print-jpeg.js","sourceRoot":"","sources":["../../src/output/print-jpeg.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Print JPEG export: downsamples an SDR image by exact area averaging, then writes a baseline JPEG\n * with an ICC colour profile. Bounded in size; the encoder is written for this project.\n */\nimport { createExportJpegEncoder, encodeJpegStrip, EXPORT_JPEG_ENCODER_ID, type JpegStripBits } from \"../capture/export-jpeg.js\";\nimport { packExportJpegExif, exportTiffNumbers, exportTiffAscii, exportTiffRationals, type ExportTiffTag } from \"../capture/export-tiff.js\";\nimport { createSrgbIccProfile, SRGB_ICC_PROFILE_VERSION } from \"../color/srgb-icc.js\";\nimport { decodeSrgbComponent, encodeSrgbComponent } from \"../color/srgb-transfer.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { requireAllowlistedRecord, requirePublicOpaqueId } from \"../core/record-validation.js\";\nimport { freezeOwnedData } from \"../core/owned-data.js\";\nimport { FULL_RESOLUTION_CEILING_PIXELS, resolveRaisedLimit, scaleBudgetCeiling } from \"../core/pixel-limits.js\";\nimport type { NativeRawTaskState } from \"../capture/native-raw.js\";\nimport type { RasterRect } from \"./capture-geometry.js\";\nexport const PRINT_JPEG_SCHEMA_VERSION=\"0.2.0\" as const;\n/**\n * Admission limits. `maximumPixels` is the default source limit; a request may raise it with its own\n * `maximumPixels`, up to `ceilingPixels`. A raised limit raises the `maximumEncodedBytes` ceiling in proportion\n * (256 000 000 bytes per 24 000 000 source pixels).\n */\nexport const PRINT_JPEG_LIMITS=Object.freeze({maximumPixels:24_000_000,ceilingPixels:FULL_RESOLUTION_CEILING_PIXELS,maximumDimension:16_384,\n maximumEncodedBytes:256_000_000,maximumProviderReads:1_000_000});\nlet srgbDecode:Float64Array|undefined;\n/** decodeSrgbComponent(v/255) for every 8-bit code v, computed once with the same function (identical values). */\nfunction srgbDecodeTable():Float64Array{return srgbDecode??=Float64Array.from({length:256},(_,v)=>decodeSrgbComponent(v/255));}\nexport interface PrintJpegSource {\n captureId:string;imageStateId:string;artifactId:string;sha256:string;\n width:number;height:number;\n encoding:\"encoded-srgb-8-rgb\";\n}\nexport interface PrintJpegInput {\n source:PrintJpegSource;\n /** Integer crop in the oriented output source image, not in sensor or CFA (colour filter array) coordinates. */\n crop:RasterRect;\n outputWidth:number;outputHeight:number;\n quantizationStep:number;\n maximumEncodedBytes:number;\n /**\n * Maximum provider `readTile` calls. The task reads each crop pixel exactly once, in tiles of at most\n * 256 x 32 pixels aligned to the crop origin, so it needs ceil(crop.height/32) x ceil(crop.width/256)\n * reads; a smaller budget fails before the first read.\n */\n maximumProviderReads:number;\n /**\n * Optional physical print density in pixels per inch (1..65535) from the caller's print plan. When present,\n * EXIF IFD0 records XResolution = YResolution = this value as a RATIONAL with ResolutionUnit = 2 (inches),\n * and JFIF APP0 records units = 1 with the nearest integer density (JFIF density fields are uint16).\n * When omitted no physical size is claimed: JFIF keeps units = 0 with a 1:1 aspect ratio. Exif 2.32 makes\n * the IFD0 resolution tags mandatory and says an unknown resolution \"shall\" be recorded as 72 dpi, so IFD0\n * carries 72/1 with ResolutionUnit = 2; that is the standard's unknown-resolution marker, not a print size.\n */\n pixelsPerInch?:number;\n /**\n * Optional opt-in source pixel limit for large images: an integer from 1 to `PRINT_JPEG_LIMITS.ceilingPixels`.\n * Default `PRINT_JPEG_LIMITS.maximumPixels` (24 000 000). When given it is recorded in the XMP export plan, like the\n * other admission budgets; the image data are unchanged.\n */\n maximumPixels?:number;\n}\nexport interface PrintJpegTileRequest {source:PrintJpegSource;x:number;y:number;width:number;height:number}\nexport interface PrintJpegTile extends PrintJpegTileRequest {samples:Uint8Array}\nexport interface PrintJpegProvider {\n readTile(request:Readonly<PrintJpegTileRequest>,signal:AbortSignal):Promise<PrintJpegTile>;\n yieldControl(signal:AbortSignal):Promise<void>;\n}\nexport interface PrintJpegOutput {\n schemaVersion:typeof PRINT_JPEG_SCHEMA_VERSION;\n input:PrintJpegInput;\n mediaType:\"image/jpeg\";\n bytes:Uint8Array;\n iccProfileVersion:typeof SRGB_ICC_PROFILE_VERSION;\n width:number;height:number;\n resampling:\"exact-area-average-in-decoded-linear-light\";\n sourceStage:\"post-SDR-8-bit-quantization\";\n digitalUpscalingApplied:false;\n sourceBytesVerified:false;\n /** Provider calls made: ceil(crop.height/32) x ceil(crop.width/256) tiles, each crop pixel read once. */\n providerReads:number;\n /** Byte behaviour of the baseline encoder that produced `bytes`. */\n encoderId:typeof EXPORT_JPEG_ENCODER_ID;\n}\nexport interface PrintJpegTask {\n readonly state:NativeRawTaskState;\n run():Promise<void>;cancel():void;dispose():void;takeOutput():PrintJpegOutput;\n}\n/** Exactly n/1 for a whole-number density; otherwise the shared bounded decimal-fraction approximation. */\nfunction resolutionRational(id:number,ppi:number):ExportTiffTag {\n if(!Number.isSafeInteger(ppi))return exportTiffRationals(id,false,[ppi]);\n const data=new Uint8Array(8),view=new DataView(data.buffer);view.setUint32(0,ppi,true);view.setUint32(4,1,true);\n return {id,type:5,count:1,data};\n}\n/**\n * Exif 2.32 APP1 for a compressed primary image with every mandatory tag (CIPA DC-008-2019 Tables 17-18):\n * IFD0 Orientation, X/YResolution + ResolutionUnit, Software, YCbCrPositioning; Exif IFD ExifVersion \"0232\",\n * ComponentsConfiguration, FlashpixVersion \"0100\", ColorSpace sRGB, PixelX/YDimension. Without a planned\n * density the resolution tags carry the standard's \"unknown resolution\" value of 72 dpi.\n */\nfunction printExif(plan:PrintJpegInput):Uint8Array {\n const ppi=plan.pixelsPerInch;\n const resolution=ppi===undefined ? [] : [resolutionRational(282,ppi),resolutionRational(283,ppi),exportTiffNumbers(296,3,[2])];\n return packExportJpegExif([exportTiffNumbers(274,3,[1]),...resolution,exportTiffAscii(305,\"Photivra Print JPEG\")],\n [exportTiffNumbers(40961,3,[1])],{pixelWidth:plan.outputWidth,pixelHeight:plan.outputHeight});\n}\nfunction integer(v:unknown,min=1):number {\n if(typeof v!==\"number\"||!Number.isSafeInteger(v)||v<min)throw new InvalidConfigurationError(\"Print raster/budgets require safe integers.\");return v;\n}\n/** Validates the input only. Source detail, perception and printer suitability are checked by separate APIs. */\nexport function parsePrintJpegInput(input:PrintJpegInput):PrintJpegInput {\n const r=requireAllowlistedRecord(input,[\"source\",\"crop\",\"outputWidth\",\"outputHeight\",\"quantizationStep\",\"maximumEncodedBytes\",\"maximumProviderReads\",\"pixelsPerInch\",\"maximumPixels\"],\"Invalid Print JPEG input.\");\n const s=requireAllowlistedRecord(r.source,[\"captureId\",\"imageStateId\",\"artifactId\",\"sha256\",\"width\",\"height\",\"encoding\"],\"Invalid Print source.\");\n if(typeof s.sha256!==\"string\"||!/^[a-f0-9]{64}$/.test(s.sha256)||s.encoding!==\"encoded-srgb-8-rgb\")throw new InvalidConfigurationError(\"Print requires identified encoded sRGB source bytes.\");\n const source:PrintJpegSource={captureId:requirePublicOpaqueId(s.captureId,\"Invalid capture ID.\"),imageStateId:requirePublicOpaqueId(s.imageStateId,\"Invalid image state ID.\"),artifactId:requirePublicOpaqueId(s.artifactId,\"Invalid artifact ID.\"),sha256:s.sha256,width:integer(s.width),height:integer(s.height),encoding:s.encoding};\n const c=requireAllowlistedRecord(r.crop,[\"x\",\"y\",\"width\",\"height\"],\"Invalid Print crop.\"),crop={x:integer(c.x,0),y:integer(c.y,0),width:integer(c.width),height:integer(c.height)};\n const outputWidth=integer(r.outputWidth),outputHeight=integer(r.outputHeight),quantizationStep=integer(r.quantizationStep),maximumEncodedBytes=integer(r.maximumEncodedBytes),maximumProviderReads=integer(r.maximumProviderReads);\n const L=PRINT_JPEG_LIMITS,maximumPixels=resolveRaisedLimit(r.maximumPixels,L.maximumPixels,L.ceilingPixels,\"Print maximumPixels must be an integer from 1 to \"+L.ceilingPixels+\".\");\n const encodedBytesCeiling=r.maximumPixels===undefined?L.maximumEncodedBytes:scaleBudgetCeiling(L.maximumEncodedBytes,maximumPixels);\n if(source.width>L.maximumDimension||source.height>L.maximumDimension||source.width*source.height>maximumPixels||crop.x+crop.width>source.width||crop.y+crop.height>source.height||\n outputWidth>crop.width||outputHeight>crop.height||quantizationStep>255||maximumEncodedBytes>encodedBytesCeiling||maximumProviderReads>L.maximumProviderReads||\n Math.abs(outputWidth*crop.height-outputHeight*crop.width)>.5*(crop.width+crop.height))throw new InvalidConfigurationError(\"Print requires bounded native/downsampled aspect-preserving crop output.\");\n const ppi=r.pixelsPerInch;\n if(ppi!==undefined&&(typeof ppi!==\"number\"||!Number.isFinite(ppi)||ppi<1||ppi>65535))throw new InvalidConfigurationError(\"Print density requires finite pixels per inch from 1 to 65535.\");\n return freezeOwnedData({source,crop,outputWidth,outputHeight,quantizationStep,maximumEncodedBytes,maximumProviderReads,...(ppi===undefined ? {} : {pixelsPerInch:ppi}),\n ...(r.maximumPixels===undefined ? {} : {maximumPixels})});\n}\n/** The JPEG writer of a Print plan: its size, quantization, budget, ICC profile, EXIF, XMP plan record and density. */\nfunction printEncoder(plan:PrintJpegInput):ReturnType<typeof createExportJpegEncoder> {\n const exif=printExif(plan);\n const escaped=JSON.stringify(plan).replaceAll(\"&\",\"&\").replaceAll('\"',\""\").replaceAll(\"<\",\"<\").replaceAll(\">\",\">\");\n const xmp=new TextEncoder().encode('<x:xmpmeta xmlns:x=\"adobe:ns:meta/\"><rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"><rdf:Description rdf:about=\"\" xmlns:photivra=\"https://photivra.com/ns/simulation/1.0/\" photivra:PrintExportPlan=\"'+escaped+'\" photivra:SourceBytesVerified=\"False\"/></rdf:RDF></x:xmpmeta>');\n return createExportJpegEncoder({width:plan.outputWidth,height:plan.outputHeight,quantizationStep:plan.quantizationStep,maximumOutputBytes:plan.maximumEncodedBytes,icc:createSrgbIccProfile(),exif,xmp,\n ...(plan.pixelsPerInch===undefined ? {} : {densityDotsPerInch:Math.round(plan.pixelsPerInch)})});\n}\n/** At 1:1, the output code of each source code (its decoded value re-encoded and rounded). */\nfunction directCodes():Uint8Array {\n return Uint8Array.from(srgbDecodeTable(),(value)=>Math.min(255,Math.max(0,Math.round(encodeSrgbComponent(value)*255))));\n}\n/** Rows of a 1:1 Print JPEG for `createPrintJpegStrip`: crop rows `y` to `y + height` (relative to the crop), crop-wide RGB. */\nexport interface PrintJpegStripInput {y:number;height:number;samples:Uint8Array}\n/** A strip of a 1:1 Print JPEG's coded blocks (`createPrintJpegStrip`), for `composePrintJpegStrips`. */\nexport interface PrintJpegStrip {readonly y:number;readonly height:number;readonly width:number;readonly quantizationStep:number;readonly bits:JpegStripBits}\nfunction requireIdentity(plan:PrintJpegInput):void {\n if(plan.outputWidth!==plan.crop.width||plan.outputHeight!==plan.crop.height)throw new InvalidConfigurationError(\"Print JPEG strips require a 1:1 plan (output size equal to the crop).\");\n}\n/**\n * Codes rows of a 1:1 Print JPEG (output size equal to the crop) apart from the rows before them, so a large file's strips\n * can be written on separate workers. `strip.y` is a multiple of 8 and `strip.height` a multiple of 8 unless the strip ends at\n * the image's bottom; `strip.samples` are those crop rows' 8-bit sRGB RGB, crop-wide. `composePrintJpegStrips` joins strips that\n * cover the image, in order, into the bytes `createPrintJpegTask` writes for the same plan and source pixels.\n */\nexport function createPrintJpegStrip(input:PrintJpegInput,strip:PrintJpegStripInput):PrintJpegStrip {\n const plan=parsePrintJpegInput(input);requireIdentity(plan);\n const r=requireAllowlistedRecord(strip,[\"y\",\"height\",\"samples\"],\"Invalid Print JPEG strip.\");\n const y=integer(r.y,0),height=integer(r.height),width=plan.outputWidth,samples=r.samples;\n if(y%8!==0||y+height>plan.outputHeight||(height%8!==0&&y+height!==plan.outputHeight))throw new InvalidConfigurationError(\"Print JPEG strips start on a block row and cover whole block rows.\");\n if(!(samples instanceof Uint8Array)||samples.length!==width*height*3)throw new InvalidConfigurationError(\"Print JPEG strip requires the crop rows' RGB samples.\");\n const direct=directCodes(),blocksX=Math.ceil(width/8),rowBytes=width*3;\n // The same block samples as createPrintJpegTask's 1:1 path: each block's edge pixels repeated into a partial block.\n const bits=encodeJpegStrip(plan.quantizationStep,blocksX*Math.ceil(height/8),(index,out)=>{\n const bx=(index%blocksX)*8,by=Math.floor(index/blocksX)*8,bw=Math.min(8,width-bx),bh=Math.min(8,plan.outputHeight-y-by);\n for(let yy=0,o=0;yy<8;yy++){\n const row=(by+Math.min(yy,bh-1))*rowBytes+bx*3;\n for(let x=0;x<8;x++,o+=3){const i=row+Math.min(x,bw-1)*3;out[o]=direct[samples[i]!]!;out[o+1]=direct[samples[i+1]!]!;out[o+2]=direct[samples[i+2]!]!;}\n }\n });\n return Object.freeze({y,height,width,quantizationStep:plan.quantizationStep,bits});\n}\n/**\n * Joins the strips of a 1:1 Print JPEG (`createPrintJpegStrip`), covering the image top to bottom in order, into its file:\n * the same bytes `createPrintJpegTask` writes for the plan and the same source pixels. No source is read, so the output's\n * `providerReads` is 0.\n */\nexport function composePrintJpegStrips(input:PrintJpegInput,strips:readonly PrintJpegStrip[]):PrintJpegOutput {\n const plan=parsePrintJpegInput(input);requireIdentity(plan);\n if(!Array.isArray(strips)||strips.length<1)throw new InvalidConfigurationError(\"Print JPEG assembly requires strips.\");\n const encoder=printEncoder(plan);\n try{\n let next=0;\n for(const strip of strips){\n if(strip.y!==next||strip.width!==plan.outputWidth||strip.quantizationStep!==plan.quantizationStep)throw new InvalidConfigurationError(\"Print JPEG strips must cover the plan's image in order.\");\n encoder.appendStrip(strip.bits);next+=strip.height;\n }\n if(next!==plan.outputHeight)throw new InvalidConfigurationError(\"Print JPEG strips must cover the plan's image in order.\");\n const bytes=encoder.finish();\n return {schemaVersion:PRINT_JPEG_SCHEMA_VERSION,input:plan,mediaType:\"image/jpeg\",bytes,iccProfileVersion:SRGB_ICC_PROFILE_VERSION,width:plan.outputWidth,height:plan.outputHeight,resampling:\"exact-area-average-in-decoded-linear-light\",sourceStage:\"post-SDR-8-bit-quantization\",digitalUpscalingApplied:false,sourceBytesVerified:false,providerReads:0,encoderId:EXPORT_JPEG_ENCODER_ID};\n }catch(error){encoder.dispose();throw error;}\n}\n/** Creates the export task. Filtering weights each source pixel by its exact area overlap, after decoding the declared 8-bit SDR source. */\nexport function createPrintJpegTask(input:PrintJpegInput,provider:PrintJpegProvider):PrintJpegTask {\n const plan=parsePrintJpegInput(input);\n if(!provider||typeof provider.readTile!==\"function\"||typeof provider.yieldControl!==\"function\")throw new InvalidConfigurationError(\"Print export requires source reader and host yields.\");\n const read=provider.readTile.bind(provider),yieldControl=provider.yieldControl.bind(provider),abort=new AbortController();\n let state:NativeRawTaskState=\"ready\",output:PrintJpegOutput|null=null,encoder:ReturnType<typeof createExportJpegEncoder>|undefined;\n function check():void{if(abort.signal.aborted)throw new InvalidConfigurationError(\"Print export aborted.\");}\n function release():void{encoder?.dispose();encoder=undefined;output?.bytes.fill(0);output=null;}\n return {get state():NativeRawTaskState{return state;},\n async run():Promise<void>{\n if(state!==\"ready\")throw new InvalidConfigurationError(\"Print export is single-use.\");state=\"running\";\n try{\n encoder=printEncoder(plan);\n const scaleX=plan.crop.width/plan.outputWidth,scaleY=plan.crop.height/plan.outputHeight,area=scaleX*scaleY;\n const cropRight=plan.crop.x+plan.crop.width,cropBottom=plan.crop.y+plan.crop.height,rowBytes=plan.crop.width*3;\n // Every crop pixel is read exactly once, in tiles of at most 256 x 32 aligned to the crop origin.\n const tilesPerBand=Math.ceil(plan.crop.width/256),requiredReads=Math.ceil(plan.crop.height/32)*tilesPerBand;\n if(requiredReads>plan.maximumProviderReads)throw new InvalidConfigurationError(\"Print source exceeds provider-read budget.\");\n // Rolling cache of whole crop-width source rows [cacheTop, cacheBottom): at most 63 rows are retained.\n const cache=new Uint8Array(Math.min(64,plan.crop.height)*rowBytes),lut=srgbDecodeTable();\n let reads=0,blocks=0,cacheTop=plan.crop.y,cacheBottom=plan.crop.y;\n const ensureRows=async(firstRow:number,rowCount:number):Promise<void>=>{\n const keepFrom=Math.min(Math.max(cacheTop,firstRow),cacheBottom);\n if(keepFrom>cacheTop){cache.copyWithin(0,(keepFrom-cacheTop)*rowBytes,(cacheBottom-cacheTop)*rowBytes);cacheTop=keepFrom;}\n while(cacheBottom<firstRow+rowCount){\n const bandHeight=Math.min(32,cropBottom-cacheBottom);\n if((cacheBottom+bandHeight-cacheTop)*rowBytes>cache.length)throw new InvalidConfigurationError(\"Print source traversal is not monotonic.\");\n for(let sx=plan.crop.x;sx<cropRight;sx+=256){\n check();++reads;\n const request=Object.freeze({source:plan.source,x:sx,y:cacheBottom,width:Math.min(256,cropRight-sx),height:bandHeight});\n const supplied=await read(request,abort.signal);check();\n const tile=requireAllowlistedRecord(supplied,[\"source\",\"x\",\"y\",\"width\",\"height\",\"samples\"],\"Invalid Print source tile.\");\n const source=requireAllowlistedRecord(tile.source,[\"captureId\",\"imageStateId\",\"artifactId\",\"sha256\",\"width\",\"height\",\"encoding\"],\"Invalid Print tile source.\");\n for(const key of Object.keys(plan.source) as (keyof PrintJpegSource)[])if(source[key]!==plan.source[key])throw new InvalidConfigurationError(\"Print source identity mismatch.\");\n for(const key of [\"x\",\"y\",\"width\",\"height\"] as const)if(tile[key]!==request[key])throw new InvalidConfigurationError(\"Print source rectangle mismatch.\");\n const samples=tile.samples;if(!(samples instanceof Uint8Array)||!(samples.buffer instanceof ArrayBuffer)||samples.length!==request.width*request.height*3||samples.buffer.byteLength!==samples.byteLength)throw new InvalidConfigurationError(\"Print source requires exact owned bounded RGB tile storage.\");\n for(let iy=0;iy<bandHeight;iy++)cache.set(samples.subarray(iy*request.width*3,(iy+1)*request.width*3),(cacheBottom-cacheTop+iy)*rowBytes+(sx-plan.crop.x)*3);\n // One output block can cover a megapixel of source, so also yield to the host while reading the source.\n if(reads%32===0){await yieldControl(abort.signal);check();}\n }\n cacheBottom+=bandHeight;\n }\n };\n const blocksX=Math.ceil(plan.outputWidth/8),sums=new Float64Array(blocksX*192);\n // At 1:1 every output pixel is one source pixel with weight exactly 1, so its sum is exactly lut[code] and its\n // sample is a function of the code alone: the same bytes from a 256-entry table, without the accumulation.\n const identity=scaleX===1&&scaleY===1;\n const direct=identity?directCodes():undefined;\n if(direct)for(let by=0;by<plan.outputHeight;by+=8){\n check();\n const height=Math.min(8,plan.outputHeight-by);await ensureRows(plan.crop.y+by,height);check();\n for(let bx=0;bx<plan.outputWidth;bx+=8){\n const width=Math.min(8,plan.outputWidth-bx),samples:number[]=[];\n for(let y=0;y<8;y++){\n const row=(plan.crop.y+by+Math.min(y,height-1)-cacheTop)*rowBytes+bx*3;\n for(let x=0;x<8;x++){const index=row+Math.min(x,width-1)*3;samples.push(direct[cache[index]!]!,direct[cache[index+1]!]!,direct[cache[index+2]!]!);}\n }\n check();encoder.writeRgbBlock(samples);if(++blocks%32===0){await yieldControl(abort.signal);check();}\n }\n }\n else for(let by=0;by<plan.outputHeight;by+=8){\n check();sums.fill(0);\n const height=Math.min(8,plan.outputHeight-by),top=plan.crop.y+by*scaleY,bottom=by+height===plan.outputHeight?cropBottom:plan.crop.y+(by+height)*scaleY;\n // Accumulation order per output pixel is unchanged from the per-block reader: 32-row bands from\n // floor(top), then 256-column chunks from floor(left), then rows, then columns. Identical IEEE sums.\n for(let sy=Math.floor(top);sy<Math.ceil(bottom);sy+=32){\n const bandHeight=Math.min(32,Math.ceil(bottom)-sy);await ensureRows(sy,bandHeight);check();\n for(let bx=0,block=0;bx<plan.outputWidth;bx+=8,block++){\n const width=Math.min(8,plan.outputWidth-bx),left=plan.crop.x+bx*scaleX,right=bx+width===plan.outputWidth?cropRight:plan.crop.x+(bx+width)*scaleX,base=block*192;\n for(let sx=Math.floor(left);sx<Math.ceil(right);sx+=256){\n const chunkWidth=Math.min(256,Math.ceil(right)-sx);\n for(let iy=0;iy<bandHeight;iy++)for(let ix=0;ix<chunkWidth;ix++){\n const px=sx+ix,py=sy+iy;\n const firstX=Math.max(0,Math.floor((px-plan.crop.x)/scaleX)-bx),lastX=Math.min(width-1,Math.ceil((px+1-plan.crop.x)/scaleX)-bx-1);\n const firstY=Math.max(0,Math.floor((py-plan.crop.y)/scaleY)-by),lastY=Math.min(height-1,Math.ceil((py+1-plan.crop.y)/scaleY)-by-1);\n const index=(py-cacheTop)*rowBytes+(px-plan.crop.x)*3,r=lut[cache[index]!]!,g=lut[cache[index+1]!]!,b=lut[cache[index+2]!]!;\n for(let oy=firstY;oy<=lastY;oy++)for(let ox=firstX;ox<=lastX;ox++){\n const x0=plan.crop.x+(bx+ox)*scaleX,y0=plan.crop.y+(by+oy)*scaleY;\n const weight=Math.max(0,Math.min(px+1,x0+scaleX)-Math.max(px,x0))*Math.max(0,Math.min(py+1,y0+scaleY)-Math.max(py,y0))/area;\n const i=base+(oy*8+ox)*3;sums[i]=sums[i]!+r*weight;sums[i+1]=sums[i+1]!+g*weight;sums[i+2]=sums[i+2]!+b*weight;\n }\n }\n }\n }\n }\n for(let bx=0,block=0;bx<plan.outputWidth;bx+=8,block++){\n const width=Math.min(8,plan.outputWidth-bx),base=block*192,samples:number[]=[];\n for(let y=0;y<8;y++)for(let x=0;x<8;x++)for(let c=0;c<3;c++){\n const value=sums[base+(Math.min(y,height-1)*8+Math.min(x,width-1))*3+c]!;\n // Nearest code, ties up. Math.round is used because floor(x+0.5) wrongly rounds 0.49999999999999994 up.\n samples.push(Math.min(255,Math.max(0,Math.round(encodeSrgbComponent(value)*255))));\n }\n check();encoder.writeRgbBlock(samples);if(++blocks%32===0){await yieldControl(abort.signal);check();}\n }\n }\n await yieldControl(abort.signal);check();const bytes=encoder.finish();encoder=undefined;\n output={schemaVersion:PRINT_JPEG_SCHEMA_VERSION,input:plan,mediaType:\"image/jpeg\",bytes,iccProfileVersion:SRGB_ICC_PROFILE_VERSION,width:plan.outputWidth,height:plan.outputHeight,resampling:\"exact-area-average-in-decoded-linear-light\",sourceStage:\"post-SDR-8-bit-quantization\",digitalUpscalingApplied:false,sourceBytesVerified:false,providerReads:reads,encoderId:EXPORT_JPEG_ENCODER_ID};state=\"completed\";\n }catch(error){release();if(!abort.signal.aborted){state=\"failed\";abort.abort();}throw error;}\n },cancel():void{if(state===\"ready\"||state===\"running\"||state===\"completed\"){state=\"cancelled\";abort.abort();release();}},\n dispose():void{if(state!==\"transferred\"){state=\"disposed\";abort.abort();release();}},\n takeOutput():PrintJpegOutput{if(state!==\"completed\"||!output)throw new InvalidConfigurationError(\"Print JPEG unavailable.\");const value=output;output=null;state=\"transferred\";return value;}\n };\n}\n"]}
|
|
@@ -25,6 +25,18 @@ export interface DeterministicUniformStream {
|
|
|
25
25
|
* Changing any of this changes simulated RAW output and needs a model and replay review.
|
|
26
26
|
*/
|
|
27
27
|
export declare function createDeterministicUniformStream(seedUint32: number): DeterministicUniformStream;
|
|
28
|
+
/** A uniform stream reseeded in place (internal, #418). */
|
|
29
|
+
export interface ResettableUniformStream extends DeterministicUniformStream {
|
|
30
|
+
/** Sets the state createDeterministicUniformStream(seedUint32) starts from, so the draws that follow are that stream's. */
|
|
31
|
+
reset(seedUint32: number): void;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The stream of createDeterministicUniformStream, reseeded in place instead of created anew (internal, #418). The seeding and
|
|
35
|
+
* the xorshift32 step are the same statements, so after `reset(seed)` every draw equals that of
|
|
36
|
+
* `createDeterministicUniformStream(seed)`. It saves a typed array and a closure per stream where a hot loop needs two
|
|
37
|
+
* fresh streams per site.
|
|
38
|
+
*/
|
|
39
|
+
export declare function createResettableUniformStream(): ResettableUniformStream;
|
|
28
40
|
/**
|
|
29
41
|
* Box–Muller transform of two uniform values in (0,1) (Box & Muller 1958). Each call uses two values
|
|
30
42
|
* and returns one standard normal sample. The second possible sample is not cached, so the order of
|
|
@@ -88,6 +88,31 @@ export function createDeterministicUniformStream(seedUint32) {
|
|
|
88
88
|
}
|
|
89
89
|
};
|
|
90
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* The stream of createDeterministicUniformStream, reseeded in place instead of created anew (internal, #418). The seeding and
|
|
93
|
+
* the xorshift32 step are the same statements, so after `reset(seed)` every draw equals that of
|
|
94
|
+
* `createDeterministicUniformStream(seed)`. It saves a typed array and a closure per stream where a hot loop needs two
|
|
95
|
+
* fresh streams per site.
|
|
96
|
+
*/
|
|
97
|
+
export function createResettableUniformStream() {
|
|
98
|
+
const state = new Uint32Array(1);
|
|
99
|
+
return {
|
|
100
|
+
reset(seedUint32) {
|
|
101
|
+
state[0] = fmix32((seedUint32 ^ 0x9e3779b9) >>> 0);
|
|
102
|
+
if (state[0] === 0) {
|
|
103
|
+
state[0] = 0x6d2b79f5;
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
next() {
|
|
107
|
+
let x = state[0];
|
|
108
|
+
x ^= x << 13;
|
|
109
|
+
x ^= x >>> 17;
|
|
110
|
+
x ^= x << 5;
|
|
111
|
+
state[0] = x;
|
|
112
|
+
return (state[0] + 0.5) / 0x1_0000_0000;
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
}
|
|
91
116
|
/**
|
|
92
117
|
* Box–Muller transform of two uniform values in (0,1) (Box & Muller 1958). Each call uses two values
|
|
93
118
|
* and returns one standard normal sample. The second possible sample is not cached, so the order of
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stochastic-seed.js","sourceRoot":"","sources":["../../src/sensor/stochastic-seed.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Seeds for the random-number streams behind simulated sensor noise. The same inputs always give\n * the same noise.\n *\n * Each per-site stream seed is a strong 32-bit hash of the capture seed, the absolute native\n * row-major site index and a fixed stream ID. The hash is MurmurHash3_x86_32 (Austin Appleby,\n * placed in the public domain) of the 12-byte little-endian message `[captureSeed, siteIndex,\n * streamId]` with hash seed 0. Its avalanche finalizer (`fmix32`) makes a one-bit input change flip\n * each output bit with probability close to 1/2. So neighbouring sites, the two streams of one site\n * and captures with nearby seeds get unrelated seeds. A linear schedule such as `seed + 2*index` fed\n * into a linear generator (xorshift) lacks this property, and produced correlated noise with too\n * little variance (issue #270).\n *\n * This is deterministic and not cryptographic; it does not claim unpredictability. The moment and\n * correlation tests, not this hash alone, show that the resulting noise is statistically acceptable.\n */\n\nimport { InvalidScientificInputError } from \"../core/validation.js\";\nimport { portableCosTwoPi, portableLog, portableSinTwoPi } from \"../core/portable-math.js\";\n\n/** Stream IDs. Changing them changes every simulated RAW code. */\nexport const NATIVE_SITE_CHARGE_STREAM_ID = 0 as const;\nexport const NATIVE_SITE_READ_NOISE_STREAM_ID = 1 as const;\n\nconst MURMUR3_C1 = 0xcc9e2d51;\nconst MURMUR3_C2 = 0x1b873593;\n\n/** MurmurHash3 32-bit avalanche finalizer; a bijection on uint32 with fmix32(0) = 0. */\nexport function fmix32(value: number): number {\n let h = value >>> 0;\n h ^= h >>> 16;\n h = Math.imul(h, 0x85ebca6b);\n h ^= h >>> 13;\n h = Math.imul(h, 0xc2b2ae35);\n h ^= h >>> 16;\n return h >>> 0;\n}\n\nfunction mixBlock(hash: number, block: number): number {\n let k = Math.imul(block >>> 0, MURMUR3_C1);\n k = (k << 15) | (k >>> 17);\n k = Math.imul(k, MURMUR3_C2);\n let h = (hash ^ k) >>> 0;\n h = (h << 13) | (h >>> 19);\n return (Math.imul(h, 5) + 0xe6546b64) >>> 0;\n}\n\nfunction isUint32(value: number): boolean {\n return Number.isInteger(value) && value >= 0 && value <= 0xffffffff;\n}\n\n/**\n * Returns the uint32 seed of one random stream for one absolute native site.\n * All inputs must be uint32 integers. The site index is the full-frame native row-major\n * index, never relative to a tile or chunk, so how the work is split cannot change it.\n */\nexport function deriveNativeSiteStreamSeedUint32(\n captureSeedUint32: number,\n nativeSiteIndex: number,\n streamId: number\n): number {\n if (!isUint32(captureSeedUint32) || !isUint32(nativeSiteIndex) || !isUint32(streamId)) {\n throw new InvalidScientificInputError(\"Stochastic stream seed inputs must be uint32 integers.\");\n }\n let h = 0;\n h = mixBlock(h, captureSeedUint32);\n h = mixBlock(h, nativeSiteIndex);\n h = mixBlock(h, streamId);\n return fmix32(h ^ 12);\n}\n\n/** One deterministic stream of uniforms strictly inside (0,1). */\nexport interface DeterministicUniformStream {\n next(): number;\n}\n\n/**\n * Creates the deterministic, non-cryptographic xorshift32 random stream for one charge, read-noise\n * or fixed-pattern identity.\n *\n * The seed is first scrambled by the MurmurHash3 `fmix32` avalanche finalizer. xorshift32 is linear\n * over GF(2), so an unscrambled seed would give nearby seeds almost identical first draws, and noise\n * that is correlated across the sensor with too little variance (issue #270). The nonzero fallback\n * avoids the zero state, which xorshift can never leave. Adding 0.5 before dividing gives values\n * strictly inside (0,1), so the logarithms in the Poisson and normal transforms never see 0 or 1.\n * Changing any of this changes simulated RAW output and needs a model and replay review.\n */\nexport function createDeterministicUniformStream(seedUint32: number): DeterministicUniformStream {\n // The state lives in a Uint32Array: storing the int32 result there is the same `>>> 0` reduction, and a uint32 above\n // 2^30 kept in a closure variable would be boxed on every step (half the speed). The draws are unchanged.\n const state = new Uint32Array(1);\n state[0] = fmix32((seedUint32 ^ 0x9e3779b9) >>> 0);\n if (state[0] === 0) {\n state[0] = 0x6d2b79f5;\n }\n return {\n next(): number {\n let x = state[0]!;\n x ^= x << 13;\n x ^= x >>> 17;\n x ^= x << 5;\n state[0] = x;\n return (state[0] + 0.5) / 0x1_0000_0000;\n }\n };\n}\n\n/**\n * Box–Muller transform of two uniform values in (0,1) (Box & Muller 1958). Each call uses two values\n * and returns one standard normal sample. The second possible sample is not cached, so the order of\n * draws from the stream never shifts.\n */\nexport function sampleDeterministicStandardNormal(random: DeterministicUniformStream): number {\n const u1 = random.next();\n const u2 = random.next();\n return Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2);\n}\n\n/**\n * The same Box–Muller draw (same two uniforms, same order) with the engine's portable logarithm and cosine\n * (`portableLog`, `portableCosTwoPi`), so the sample has the same bits in every JavaScript engine. Used by the\n * display view; the native noise keeps `sampleDeterministicStandardNormal`.\n */\nexport function samplePortableStandardNormal(random: DeterministicUniformStream): number {\n const u1 = random.next();\n const u2 = random.next();\n return Math.sqrt(-2 * portableLog(u1)) * portableCosTwoPi(u2);\n}\n\n/**\n * Standard normal samples from one stream, two per pair of uniforms: both Box–Muller outputs, r·cos(2πu₂) and then\n * r·sin(2πu₂) with r = √(−2 ln u₁) (Box & Muller 1958; the two are independent standard normals), with the portable\n * functions. Each call returns the next sample; the stream advances by two uniforms on every other call. Used by the\n * display view's AHD correction states, which draw many normals from one stream.\n */\nexport function createPortableStandardNormalPairs(random: DeterministicUniformStream): () => number {\n let spare = 0, hasSpare = false;\n return () => {\n if (hasSpare) { hasSpare = false; return spare; }\n const u1 = random.next(), u2 = random.next(), r = Math.sqrt(-2 * portableLog(u1));\n spare = r * portableSinTwoPi(u2); hasSpare = true;\n return r * portableCosTwoPi(u2);\n };\n}\n\n/**\n * Fixed-pattern stream IDs. They seed spatial patterns that belong to one physical sensor, never\n * per-capture noise, and are hashed with the sensor-instance seed instead of the capture seed.\n */\nexport const SENSOR_FIXED_PATTERN_PRNU_STREAM_ID = 16 as const;\nexport const SENSOR_FIXED_PATTERN_DSNU_STREAM_ID = 17 as const;\nexport const SENSOR_FIXED_PATTERN_HOT_PIXEL_STREAM_ID = 18 as const;\nexport const SENSOR_FIXED_PATTERN_ROW_STREAM_ID = 19 as const;\nexport const SENSOR_FIXED_PATTERN_COLUMN_STREAM_ID = 20 as const;\n\n/**\n * Returns the uint32 seed of one fixed-pattern stream for one physical colour-sampling site: the\n * MurmurHash3_x86_32 hash (hash seed 0) of the 16-byte little-endian message\n * `[sensorInstanceSeed, siteX, siteY, streamId]`. Site coordinates are absolute indices in the\n * colour-sampling grid, so the pattern belongs to the physical sensor and does not change with crop,\n * tiling or the per-capture seed. Deterministic and not cryptographic.\n */\nexport function deriveSensorFixedPatternSeedUint32(\n sensorInstanceSeedUint32: number,\n siteX: number,\n siteY: number,\n streamId: number\n): number {\n if (!isUint32(sensorInstanceSeedUint32) || !isUint32(siteX) || !isUint32(siteY) || !isUint32(streamId)) {\n throw new InvalidScientificInputError(\"Fixed-pattern seed inputs must be uint32 integers.\");\n }\n let h = 0;\n h = mixBlock(h, sensorInstanceSeedUint32);\n h = mixBlock(h, siteX);\n h = mixBlock(h, siteY);\n h = mixBlock(h, streamId);\n return fmix32(h ^ 16);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"stochastic-seed.js","sourceRoot":"","sources":["../../src/sensor/stochastic-seed.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Seeds for the random-number streams behind simulated sensor noise. The same inputs always give\n * the same noise.\n *\n * Each per-site stream seed is a strong 32-bit hash of the capture seed, the absolute native\n * row-major site index and a fixed stream ID. The hash is MurmurHash3_x86_32 (Austin Appleby,\n * placed in the public domain) of the 12-byte little-endian message `[captureSeed, siteIndex,\n * streamId]` with hash seed 0. Its avalanche finalizer (`fmix32`) makes a one-bit input change flip\n * each output bit with probability close to 1/2. So neighbouring sites, the two streams of one site\n * and captures with nearby seeds get unrelated seeds. A linear schedule such as `seed + 2*index` fed\n * into a linear generator (xorshift) lacks this property, and produced correlated noise with too\n * little variance (issue #270).\n *\n * This is deterministic and not cryptographic; it does not claim unpredictability. The moment and\n * correlation tests, not this hash alone, show that the resulting noise is statistically acceptable.\n */\n\nimport { InvalidScientificInputError } from \"../core/validation.js\";\nimport { portableCosTwoPi, portableLog, portableSinTwoPi } from \"../core/portable-math.js\";\n\n/** Stream IDs. Changing them changes every simulated RAW code. */\nexport const NATIVE_SITE_CHARGE_STREAM_ID = 0 as const;\nexport const NATIVE_SITE_READ_NOISE_STREAM_ID = 1 as const;\n\nconst MURMUR3_C1 = 0xcc9e2d51;\nconst MURMUR3_C2 = 0x1b873593;\n\n/** MurmurHash3 32-bit avalanche finalizer; a bijection on uint32 with fmix32(0) = 0. */\nexport function fmix32(value: number): number {\n let h = value >>> 0;\n h ^= h >>> 16;\n h = Math.imul(h, 0x85ebca6b);\n h ^= h >>> 13;\n h = Math.imul(h, 0xc2b2ae35);\n h ^= h >>> 16;\n return h >>> 0;\n}\n\nfunction mixBlock(hash: number, block: number): number {\n let k = Math.imul(block >>> 0, MURMUR3_C1);\n k = (k << 15) | (k >>> 17);\n k = Math.imul(k, MURMUR3_C2);\n let h = (hash ^ k) >>> 0;\n h = (h << 13) | (h >>> 19);\n return (Math.imul(h, 5) + 0xe6546b64) >>> 0;\n}\n\nfunction isUint32(value: number): boolean {\n return Number.isInteger(value) && value >= 0 && value <= 0xffffffff;\n}\n\n/**\n * Returns the uint32 seed of one random stream for one absolute native site.\n * All inputs must be uint32 integers. The site index is the full-frame native row-major\n * index, never relative to a tile or chunk, so how the work is split cannot change it.\n */\nexport function deriveNativeSiteStreamSeedUint32(\n captureSeedUint32: number,\n nativeSiteIndex: number,\n streamId: number\n): number {\n if (!isUint32(captureSeedUint32) || !isUint32(nativeSiteIndex) || !isUint32(streamId)) {\n throw new InvalidScientificInputError(\"Stochastic stream seed inputs must be uint32 integers.\");\n }\n let h = 0;\n h = mixBlock(h, captureSeedUint32);\n h = mixBlock(h, nativeSiteIndex);\n h = mixBlock(h, streamId);\n return fmix32(h ^ 12);\n}\n\n/** One deterministic stream of uniforms strictly inside (0,1). */\nexport interface DeterministicUniformStream {\n next(): number;\n}\n\n/**\n * Creates the deterministic, non-cryptographic xorshift32 random stream for one charge, read-noise\n * or fixed-pattern identity.\n *\n * The seed is first scrambled by the MurmurHash3 `fmix32` avalanche finalizer. xorshift32 is linear\n * over GF(2), so an unscrambled seed would give nearby seeds almost identical first draws, and noise\n * that is correlated across the sensor with too little variance (issue #270). The nonzero fallback\n * avoids the zero state, which xorshift can never leave. Adding 0.5 before dividing gives values\n * strictly inside (0,1), so the logarithms in the Poisson and normal transforms never see 0 or 1.\n * Changing any of this changes simulated RAW output and needs a model and replay review.\n */\nexport function createDeterministicUniformStream(seedUint32: number): DeterministicUniformStream {\n // The state lives in a Uint32Array: storing the int32 result there is the same `>>> 0` reduction, and a uint32 above\n // 2^30 kept in a closure variable would be boxed on every step (half the speed). The draws are unchanged.\n const state = new Uint32Array(1);\n state[0] = fmix32((seedUint32 ^ 0x9e3779b9) >>> 0);\n if (state[0] === 0) {\n state[0] = 0x6d2b79f5;\n }\n return {\n next(): number {\n let x = state[0]!;\n x ^= x << 13;\n x ^= x >>> 17;\n x ^= x << 5;\n state[0] = x;\n return (state[0] + 0.5) / 0x1_0000_0000;\n }\n };\n}\n\n/** A uniform stream reseeded in place (internal, #418). */\nexport interface ResettableUniformStream extends DeterministicUniformStream {\n /** Sets the state createDeterministicUniformStream(seedUint32) starts from, so the draws that follow are that stream's. */\n reset(seedUint32: number): void;\n}\n\n/**\n * The stream of createDeterministicUniformStream, reseeded in place instead of created anew (internal, #418). The seeding and\n * the xorshift32 step are the same statements, so after `reset(seed)` every draw equals that of\n * `createDeterministicUniformStream(seed)`. It saves a typed array and a closure per stream where a hot loop needs two\n * fresh streams per site.\n */\nexport function createResettableUniformStream(): ResettableUniformStream {\n const state = new Uint32Array(1);\n return {\n reset(seedUint32: number): void {\n state[0] = fmix32((seedUint32 ^ 0x9e3779b9) >>> 0);\n if (state[0] === 0) {\n state[0] = 0x6d2b79f5;\n }\n },\n next(): number {\n let x = state[0]!;\n x ^= x << 13;\n x ^= x >>> 17;\n x ^= x << 5;\n state[0] = x;\n return (state[0] + 0.5) / 0x1_0000_0000;\n }\n };\n}\n\n/**\n * Box–Muller transform of two uniform values in (0,1) (Box & Muller 1958). Each call uses two values\n * and returns one standard normal sample. The second possible sample is not cached, so the order of\n * draws from the stream never shifts.\n */\nexport function sampleDeterministicStandardNormal(random: DeterministicUniformStream): number {\n const u1 = random.next();\n const u2 = random.next();\n return Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2);\n}\n\n/**\n * The same Box–Muller draw (same two uniforms, same order) with the engine's portable logarithm and cosine\n * (`portableLog`, `portableCosTwoPi`), so the sample has the same bits in every JavaScript engine. Used by the\n * display view; the native noise keeps `sampleDeterministicStandardNormal`.\n */\nexport function samplePortableStandardNormal(random: DeterministicUniformStream): number {\n const u1 = random.next();\n const u2 = random.next();\n return Math.sqrt(-2 * portableLog(u1)) * portableCosTwoPi(u2);\n}\n\n/**\n * Standard normal samples from one stream, two per pair of uniforms: both Box–Muller outputs, r·cos(2πu₂) and then\n * r·sin(2πu₂) with r = √(−2 ln u₁) (Box & Muller 1958; the two are independent standard normals), with the portable\n * functions. Each call returns the next sample; the stream advances by two uniforms on every other call. Used by the\n * display view's AHD correction states, which draw many normals from one stream.\n */\nexport function createPortableStandardNormalPairs(random: DeterministicUniformStream): () => number {\n let spare = 0, hasSpare = false;\n return () => {\n if (hasSpare) { hasSpare = false; return spare; }\n const u1 = random.next(), u2 = random.next(), r = Math.sqrt(-2 * portableLog(u1));\n spare = r * portableSinTwoPi(u2); hasSpare = true;\n return r * portableCosTwoPi(u2);\n };\n}\n\n/**\n * Fixed-pattern stream IDs. They seed spatial patterns that belong to one physical sensor, never\n * per-capture noise, and are hashed with the sensor-instance seed instead of the capture seed.\n */\nexport const SENSOR_FIXED_PATTERN_PRNU_STREAM_ID = 16 as const;\nexport const SENSOR_FIXED_PATTERN_DSNU_STREAM_ID = 17 as const;\nexport const SENSOR_FIXED_PATTERN_HOT_PIXEL_STREAM_ID = 18 as const;\nexport const SENSOR_FIXED_PATTERN_ROW_STREAM_ID = 19 as const;\nexport const SENSOR_FIXED_PATTERN_COLUMN_STREAM_ID = 20 as const;\n\n/**\n * Returns the uint32 seed of one fixed-pattern stream for one physical colour-sampling site: the\n * MurmurHash3_x86_32 hash (hash seed 0) of the 16-byte little-endian message\n * `[sensorInstanceSeed, siteX, siteY, streamId]`. Site coordinates are absolute indices in the\n * colour-sampling grid, so the pattern belongs to the physical sensor and does not change with crop,\n * tiling or the per-capture seed. Deterministic and not cryptographic.\n */\nexport function deriveSensorFixedPatternSeedUint32(\n sensorInstanceSeedUint32: number,\n siteX: number,\n siteY: number,\n streamId: number\n): number {\n if (!isUint32(sensorInstanceSeedUint32) || !isUint32(siteX) || !isUint32(siteY) || !isUint32(streamId)) {\n throw new InvalidScientificInputError(\"Fixed-pattern seed inputs must be uint32 integers.\");\n }\n let h = 0;\n h = mixBlock(h, sensorInstanceSeedUint32);\n h = mixBlock(h, siteX);\n h = mixBlock(h, siteY);\n h = mixBlock(h, streamId);\n return fmix32(h ^ 16);\n}\n"]}
|
package/docs/API_REFERENCE.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Public API reference
|
|
2
2
|
|
|
3
|
-
Generated from the exact root exports for **@photivra/engine 2.
|
|
3
|
+
Generated from the exact root exports for **@photivra/engine 2.9.0 / root contract 2.9.0** by `node scripts/generate-api-reference.mjs`. No module deep import is supported.
|
|
4
4
|
|
|
5
5
|
Use [the developer guide](https://github.com/Photivra/photivra/blob/main/docs/DEVELOPERS.md) for executable paths and scientific boundaries. Types are contracts, not runtime validation: parse untrusted data, preserve units/reference frames, read assessment blockers, and retain evidence/limitations. Optional properties do not imply a universal default. Model/schema IDs remain independent of the distribution.
|
|
6
6
|
|
|
@@ -126,6 +126,7 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
|
|
|
126
126
|
| Export | Kind |
|
|
127
127
|
| --- | --- |
|
|
128
128
|
| [`EXPORT_JPEG_ENCODER_ID`](api/capture-export-jpeg.md#export_jpeg_encoder_id) | Runtime |
|
|
129
|
+
| [`JpegStripBits`](api/capture-export-jpeg.md#jpegstripbits) | Type |
|
|
129
130
|
|
|
130
131
|
## capture/focus-control.ts
|
|
131
132
|
|
|
@@ -1185,6 +1186,7 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
|
|
|
1185
1186
|
| --- | --- |
|
|
1186
1187
|
| [`DisplayViewResult`](api/facade-simulate-capture.md#displayviewresult) | Type |
|
|
1187
1188
|
| [`IdealReferenceResult`](api/facade-simulate-capture.md#idealreferenceresult) | Type |
|
|
1189
|
+
| [`serializeSimulatedCaptureDngFromParts`](api/facade-simulate-capture.md#serializesimulatedcapturedngfromparts) | Runtime |
|
|
1188
1190
|
| [`SIMULATE_CAPTURE_BOX_APERTURE_DEFAULT_SAMPLES`](api/facade-simulate-capture.md#simulate_capture_box_aperture_default_samples) | Runtime |
|
|
1189
1191
|
| [`SIMULATE_CAPTURE_COST_OPTIONS`](api/facade-simulate-capture.md#simulate_capture_cost_options) | Runtime |
|
|
1190
1192
|
| [`SIMULATE_CAPTURE_DEFAULT_ILLUMINANCE_LUX`](api/facade-simulate-capture.md#simulate_capture_default_illuminance_lux) | Runtime |
|
|
@@ -1196,6 +1198,7 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
|
|
|
1196
1198
|
| [`SimulateCaptureColorEncoding`](api/facade-simulate-capture.md#simulatecapturecolorencoding) | Type |
|
|
1197
1199
|
| [`SimulateCaptureCostOption`](api/facade-simulate-capture.md#simulatecapturecostoption) | Type |
|
|
1198
1200
|
| [`SimulateCaptureDemosaic`](api/facade-simulate-capture.md#simulatecapturedemosaic) | Type |
|
|
1201
|
+
| [`SimulateCaptureDngPart`](api/facade-simulate-capture.md#simulatecapturedngpart) | Type |
|
|
1199
1202
|
| [`SimulateCaptureExposureMode`](api/facade-simulate-capture.md#simulatecaptureexposuremode) | Type |
|
|
1200
1203
|
| [`SimulateCaptureLensDistortion`](api/facade-simulate-capture.md#simulatecapturelensdistortion) | Type |
|
|
1201
1204
|
| [`SimulateCaptureMotion`](api/facade-simulate-capture.md#simulatecapturemotion) | Type |
|
|
@@ -2020,6 +2023,8 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
|
|
|
2020
2023
|
|
|
2021
2024
|
| Export | Kind |
|
|
2022
2025
|
| --- | --- |
|
|
2026
|
+
| [`composePrintJpegStrips`](api/output-print-jpeg.md#composeprintjpegstrips) | Runtime |
|
|
2027
|
+
| [`createPrintJpegStrip`](api/output-print-jpeg.md#createprintjpegstrip) | Runtime |
|
|
2023
2028
|
| [`createPrintJpegTask`](api/output-print-jpeg.md#createprintjpegtask) | Runtime |
|
|
2024
2029
|
| [`parsePrintJpegInput`](api/output-print-jpeg.md#parseprintjpeginput) | Runtime |
|
|
2025
2030
|
| [`PRINT_JPEG_LIMITS`](api/output-print-jpeg.md#print_jpeg_limits) | Runtime |
|
|
@@ -2028,6 +2033,8 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
|
|
|
2028
2033
|
| [`PrintJpegOutput`](api/output-print-jpeg.md#printjpegoutput) | Type |
|
|
2029
2034
|
| [`PrintJpegProvider`](api/output-print-jpeg.md#printjpegprovider) | Type |
|
|
2030
2035
|
| [`PrintJpegSource`](api/output-print-jpeg.md#printjpegsource) | Type |
|
|
2036
|
+
| [`PrintJpegStrip`](api/output-print-jpeg.md#printjpegstrip) | Type |
|
|
2037
|
+
| [`PrintJpegStripInput`](api/output-print-jpeg.md#printjpegstripinput) | Type |
|
|
2031
2038
|
| [`PrintJpegTask`](api/output-print-jpeg.md#printjpegtask) | Type |
|
|
2032
2039
|
| [`PrintJpegTile`](api/output-print-jpeg.md#printjpegtile) | Type |
|
|
2033
2040
|
| [`PrintJpegTileRequest`](api/output-print-jpeg.md#printjpegtilerequest) | Type |
|
package/docs/QUICK_START.md
CHANGED
|
@@ -1151,6 +1151,65 @@ strips.forEach((strip, i) => stitched.set(strip.image.samples as Uint8Array, i *
|
|
|
1151
1151
|
console.log(strips[0]!.region, stitched.length);
|
|
1152
1152
|
```
|
|
1153
1153
|
|
|
1154
|
+
### A whole-frame DNG from parts
|
|
1155
|
+
|
|
1156
|
+
`serializeSimulatedCaptureDngFromParts(options, parts)` writes the whole-frame DNG of `options` (`output.format: "dng"`,
|
|
1157
|
+
no `output.region`) from region renders of the same request, so a large DNG's RAW can render in parallel like a JPEG or PNG.
|
|
1158
|
+
Each part is a region result's `raw` and `region` (any region format; `result.raw` holds the region's native sites,
|
|
1159
|
+
`result.region.nativeRect` where they lie). A region's sites are the whole render's sites, so the joined RAW is the whole
|
|
1160
|
+
render's RAW; the function then resolves the request and writes the DNG exactly as `simulateCapture` does, and the bytes
|
|
1161
|
+
are the same. The parts must cover the frame's native raster; where they overlap (the demosaic margin) their sites must
|
|
1162
|
+
agree, and a part from another request is refused. Render the parts with a fixed white balance and without `output.dng`
|
|
1163
|
+
(a region takes neither; the RAW codes do not depend on the white-balance intent): auto white balance and the capture time
|
|
1164
|
+
apply to the DNG options passed here, and auto white balance is measured over the joined frame.
|
|
1165
|
+
|
|
1166
|
+
Tests compare the joined DNG byte for byte with the whole-frame DNG for bilinear and AHD, diffraction with the four-spot
|
|
1167
|
+
filter and the 2 × 2 box, auto white balance with a capture time, a reflectance-function scene and the environment path.
|
|
1168
|
+
On the Photivra app's 24 MP request (6000 × 4000 at 6 µm, 24 parts of about 1024 pixels; Node, one thread) the DNG was
|
|
1169
|
+
the same bytes both ways; the parts took 58.1 s of CPU against 50.6 s for one whole render (Quality options: 119.3 s against
|
|
1170
|
+
113.6 s) and the join 2.6 s, so on four workers the wall time is roughly a quarter of the whole render's.
|
|
1171
|
+
|
|
1172
|
+
```ts
|
|
1173
|
+
import { serializeSimulatedCaptureDngFromParts, simulateCapture, type SimulateCaptureDngPart, type SimulateCaptureOptions } from "@photivra/engine";
|
|
1174
|
+
|
|
1175
|
+
const dngFrame: SimulateCaptureOptions = { scene: { preset: "siemens-star" }, output: { width: 96, height: 64, format: "dng" } };
|
|
1176
|
+
// Two strips rendered as sRGB regions (in an application, in separate Web Workers), then one DNG of the whole frame.
|
|
1177
|
+
const parts: SimulateCaptureDngPart[] = await Promise.all([0, 32].map(async (y) => {
|
|
1178
|
+
const part = await simulateCapture({ ...dngFrame, output: { width: 96, height: 64, region: { x: 0, y, width: 96, height: 32 } } });
|
|
1179
|
+
return { raw: part.raw, region: part.region! };
|
|
1180
|
+
}));
|
|
1181
|
+
const dng = await serializeSimulatedCaptureDngFromParts(dngFrame, parts);
|
|
1182
|
+
console.log(dng.bytes.length);
|
|
1183
|
+
```
|
|
1184
|
+
|
|
1185
|
+
### A Print JPEG written in strips
|
|
1186
|
+
|
|
1187
|
+
At 1:1 (output size equal to the crop), a Print JPEG's rows can be coded on separate workers.
|
|
1188
|
+
`createPrintJpegStrip(input, { y, height, samples })` codes crop rows `y` to `y + height` (8-bit sRGB RGB, crop-wide;
|
|
1189
|
+
`y` a multiple of 8, and `height` too unless the strip ends at the image's bottom) apart from the rows before them.
|
|
1190
|
+
`composePrintJpegStrips(input, strips)` joins strips that cover the image, top to bottom, into the file
|
|
1191
|
+
`createPrintJpegTask` writes for the same plan and source pixels: the same bytes. Only the first block of each strip
|
|
1192
|
+
depends on the strip before it (its DC differences), so the join codes that block and copies the rest of the strip's
|
|
1193
|
+
bits. The output's `providerReads` is 0, because no source is read.
|
|
1194
|
+
|
|
1195
|
+
Tests compare the joined file with the task's file byte for byte, for several splits, crops, quantization steps and a
|
|
1196
|
+
density. For a 24 MP file (Node, one thread), the whole task took 8.1 s; four strips took 1.9 s each, and the join took
|
|
1197
|
+
1.1 s (a 64 MB file). In the Photivra app (Chromium, four workers), writing a 24 MP JPEG takes about 3 s instead of 9–12 s.
|
|
1198
|
+
|
|
1199
|
+
```ts
|
|
1200
|
+
import { composePrintJpegStrips, createPrintJpegStrip, type PrintJpegInput } from "@photivra/engine";
|
|
1201
|
+
|
|
1202
|
+
const width = 64, height = 40, pixels = new Uint8Array(width * height * 3).fill(120);
|
|
1203
|
+
const jpegPlan: PrintJpegInput = {
|
|
1204
|
+
source: { captureId: "capture", imageStateId: "sdr", artifactId: "pixels", sha256: "0".repeat(64), width, height, encoding: "encoded-srgb-8-rgb" },
|
|
1205
|
+
crop: { x: 0, y: 0, width, height }, outputWidth: width, outputHeight: height, quantizationStep: 2, maximumEncodedBytes: 1_000_000, maximumProviderReads: 16
|
|
1206
|
+
};
|
|
1207
|
+
// Two strips (in an application, coded in separate Web Workers), then the file.
|
|
1208
|
+
const strips = [[0, 24], [24, 16]].map(([y, rows]) => createPrintJpegStrip(jpegPlan, { y: y!, height: rows!, samples: pixels.slice(y! * width * 3, (y! + rows!) * width * 3) }));
|
|
1209
|
+
const jpeg = composePrintJpegStrips(jpegPlan, strips);
|
|
1210
|
+
console.log(jpeg.bytes.length);
|
|
1211
|
+
```
|
|
1212
|
+
|
|
1154
1213
|
## Ideal reference (2.3)
|
|
1155
1214
|
|
|
1156
1215
|
`simulateIdealReference(options)` takes the same options as `simulateCapture` and returns what the camera
|
|
@@ -14,3 +14,13 @@ was exactly a negative half-integer. The repository's test images are unchanged.
|
|
|
14
14
|
```ts
|
|
15
15
|
EXPORT_JPEG_ENCODER_ID = "photivra-baseline-jpeg-444-v2" as const
|
|
16
16
|
```
|
|
17
|
+
|
|
18
|
+
## JpegStripBits
|
|
19
|
+
|
|
20
|
+
The entropy-coded bits of consecutive blocks of one image, coded apart from the blocks before them (`encodeJpegStrip`):
|
|
21
|
+
the first block's quantized coefficients (3 × 64, natural order), whose DC differences need the block before; the other
|
|
22
|
+
blocks' bits, unstuffed, most-significant first; and the last block's DC values, which the next strip's first block needs.
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
export interface JpegStripBits { first: Float64Array; bits: Uint8Array; bitLength: number; blockCount: number; lastDc: Float64Array }
|
|
26
|
+
```
|
package/docs/api/core-version.md
CHANGED
|
@@ -11,5 +11,5 @@ version they were made with. Proof-of-concept (POC), schema and model contracts
|
|
|
11
11
|
own versions. Release checks confirm it matches package.json and the packed package.
|
|
12
12
|
|
|
13
13
|
```ts
|
|
14
|
-
ENGINE_API_VERSION = "2.
|
|
14
|
+
ENGINE_API_VERSION = "2.9.0" as const
|
|
15
15
|
```
|
package/docs/api/exports.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"packageVersion": "2.
|
|
3
|
-
"engineApiVersion": "2.
|
|
2
|
+
"packageVersion": "2.9.0",
|
|
3
|
+
"engineApiVersion": "2.9.0",
|
|
4
4
|
"exports": [
|
|
5
5
|
{
|
|
6
6
|
"name": "AbsoluteUncertaintyEstimate",
|
|
@@ -2097,6 +2097,11 @@
|
|
|
2097
2097
|
"source": "src/capture/native-environment-raw.ts",
|
|
2098
2098
|
"kind": "runtime"
|
|
2099
2099
|
},
|
|
2100
|
+
{
|
|
2101
|
+
"name": "composePrintJpegStrips",
|
|
2102
|
+
"source": "src/output/print-jpeg.ts",
|
|
2103
|
+
"kind": "runtime"
|
|
2104
|
+
},
|
|
2100
2105
|
{
|
|
2101
2106
|
"name": "composeRelativeErrorBounds",
|
|
2102
2107
|
"source": "src/gpu/image-kernel-execution.ts",
|
|
@@ -2377,6 +2382,11 @@
|
|
|
2377
2382
|
"source": "src/color/illuminants.ts",
|
|
2378
2383
|
"kind": "runtime"
|
|
2379
2384
|
},
|
|
2385
|
+
{
|
|
2386
|
+
"name": "createPrintJpegStrip",
|
|
2387
|
+
"source": "src/output/print-jpeg.ts",
|
|
2388
|
+
"kind": "runtime"
|
|
2389
|
+
},
|
|
2380
2390
|
{
|
|
2381
2391
|
"name": "createPrintJpegTask",
|
|
2382
2392
|
"source": "src/output/print-jpeg.ts",
|
|
@@ -3882,6 +3892,11 @@
|
|
|
3882
3892
|
"source": "src/equipment/iso-capabilities.ts",
|
|
3883
3893
|
"kind": "type"
|
|
3884
3894
|
},
|
|
3895
|
+
{
|
|
3896
|
+
"name": "JpegStripBits",
|
|
3897
|
+
"source": "src/capture/export-jpeg.ts",
|
|
3898
|
+
"kind": "type"
|
|
3899
|
+
},
|
|
3885
3900
|
{
|
|
3886
3901
|
"name": "LateralCaLensCorrection",
|
|
3887
3902
|
"source": "src/output/lens-corrections.ts",
|
|
@@ -5522,6 +5537,16 @@
|
|
|
5522
5537
|
"source": "src/output/print-jpeg.ts",
|
|
5523
5538
|
"kind": "type"
|
|
5524
5539
|
},
|
|
5540
|
+
{
|
|
5541
|
+
"name": "PrintJpegStrip",
|
|
5542
|
+
"source": "src/output/print-jpeg.ts",
|
|
5543
|
+
"kind": "type"
|
|
5544
|
+
},
|
|
5545
|
+
{
|
|
5546
|
+
"name": "PrintJpegStripInput",
|
|
5547
|
+
"source": "src/output/print-jpeg.ts",
|
|
5548
|
+
"kind": "type"
|
|
5549
|
+
},
|
|
5525
5550
|
{
|
|
5526
5551
|
"name": "PrintJpegTask",
|
|
5527
5552
|
"source": "src/output/print-jpeg.ts",
|
|
@@ -7867,6 +7892,11 @@
|
|
|
7867
7892
|
"source": "src/capture/simulated-capture.ts",
|
|
7868
7893
|
"kind": "runtime"
|
|
7869
7894
|
},
|
|
7895
|
+
{
|
|
7896
|
+
"name": "serializeSimulatedCaptureDngFromParts",
|
|
7897
|
+
"source": "src/facade/simulate-capture.ts",
|
|
7898
|
+
"kind": "runtime"
|
|
7899
|
+
},
|
|
7870
7900
|
{
|
|
7871
7901
|
"name": "setExposureCompensationOnMeterTarget",
|
|
7872
7902
|
"source": "src/exposure/metering-target.ts",
|
|
@@ -7977,6 +8007,11 @@
|
|
|
7977
8007
|
"source": "src/facade/simulate-capture.ts",
|
|
7978
8008
|
"kind": "type"
|
|
7979
8009
|
},
|
|
8010
|
+
{
|
|
8011
|
+
"name": "SimulateCaptureDngPart",
|
|
8012
|
+
"source": "src/facade/simulate-capture.ts",
|
|
8013
|
+
"kind": "type"
|
|
8014
|
+
},
|
|
7980
8015
|
{
|
|
7981
8016
|
"name": "SimulateCaptureExposureMode",
|
|
7982
8017
|
"source": "src/facade/simulate-capture.ts",
|
|
@@ -175,7 +175,8 @@ export type SceneMaterialPoint = Omit<ScenePlanePoint, "wavelengthNanometers">;
|
|
|
175
175
|
|
|
176
176
|
## ScenePlanePoint
|
|
177
177
|
|
|
178
|
-
A point of the scene plane passed to caller scene functions
|
|
178
|
+
A point of the scene plane passed to caller scene functions: a new object for every call, which the engine does not read
|
|
179
|
+
after the call (not frozen: freezing cost about 40 % of a chart lookup).
|
|
179
180
|
|
|
180
181
|
```ts
|
|
181
182
|
export interface ScenePlanePoint {
|
|
@@ -62,6 +62,23 @@ export interface IdealReferenceResult {
|
|
|
62
62
|
}
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
+
## serializeSimulatedCaptureDngFromParts
|
|
66
|
+
|
|
67
|
+
Writes the whole-frame DNG of `options` (`output.format: "dng"`, no `output.region`) from the packed RAW of region renders of
|
|
68
|
+
the same request (#391), so the RAW can render in parallel. A region render's native sites are the same sites as the whole
|
|
69
|
+
render's (each site's seeds come from its index in the whole raster), so the joined RAW is the whole render's RAW, and the
|
|
70
|
+
request is resolved and written exactly as `simulateCapture` writes its DNG: the bytes are the same. The parts must cover
|
|
71
|
+
every native site of the frame; where they overlap (each region carries the demosaic margin) their sites must agree. Region
|
|
72
|
+
renders of the request with any format serve (a region's own `output.format` does not change its RAW). A region cannot take
|
|
73
|
+
`output.whiteBalance: "auto"` or `output.dng`: render the parts with a fixed white balance (the RAW codes do not depend on the
|
|
74
|
+
white-balance intent) and pass the DNG's own options here, where auto white balance is measured over the joined frame.
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
export async function serializeSimulatedCaptureDngFromParts(options: SimulateCaptureOptions, parts: readonly SimulateCaptureDngPart[]): Promise<NativeRawDng>;
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
This call is asynchronous; byte hashing uses the caller runtime's Web Crypto.
|
|
81
|
+
|
|
65
82
|
## SIMULATE_CAPTURE_BOX_APERTURE_DEFAULT_SAMPLES
|
|
66
83
|
|
|
67
84
|
Default midpoint samples per axis of `sensor.pixelAperture: "box"`.
|
|
@@ -176,6 +193,17 @@ edge-directed method that reduces zipper and false colour on sharp edges.
|
|
|
176
193
|
export type SimulateCaptureDemosaic = "bilinear" | "ahd";
|
|
177
194
|
```
|
|
178
195
|
|
|
196
|
+
## SimulateCaptureDngPart
|
|
197
|
+
|
|
198
|
+
One part of a whole-frame DNG (#391): a region render's packed RAW and where its native sites lie (`result.raw`, `result.region`).
|
|
199
|
+
|
|
200
|
+
```ts
|
|
201
|
+
export interface SimulateCaptureDngPart {
|
|
202
|
+
raw: Pick<NativeRawOutput, "codes" | "blackLevels" | "digitalSaturationCodes" | "saturationFlags" | "effectiveSaturationCodes">;
|
|
203
|
+
region: { nativeRect: { x: number; y: number; width: number; height: number } };
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
179
207
|
## SimulateCaptureExposureMode
|
|
180
208
|
|
|
181
209
|
The exact contract is declared below; use the domain guide for assumptions and staged integration.
|
|
@@ -72,7 +72,7 @@ export interface DiffractionLimitedPsfProfile {
|
|
|
72
72
|
/** Largest truncated energy over the wavelengths. */
|
|
73
73
|
maximumTruncatedEnergyFraction: number;
|
|
74
74
|
/**
|
|
75
|
-
* How the cells were integrated. 2.5: wavelengths with β = p·f_c ≥
|
|
75
|
+
* How the cells were integrated. 2.5: wavelengths with β = p·f_c ≥ `AIRY_REAL_SPACE_MINIMUM_BETA` (192 in 2.5–2.8.1, then 32) use the real-space
|
|
76
76
|
* encircled-energy method; `realSpaceWavelengthsNm` lists them, and `method` is `"frequency-domain-and-real-space"` when both ran.
|
|
77
77
|
* `maximumRadialNodes` counts frequency-domain radial nodes (0 when only the real-space method ran); `maximumAngularNodes` the
|
|
78
78
|
* angular nodes of either method (for the real-space method, all θ nodes of one wavelength).
|