{
  "reviewedAt": "2026-10-23",
  "sourceKind": "Production editor working copy; not claimed to be a public GitHub commit",
  "excerpts": [
    {
      "file": "app/studio/general-filters.ts",
      "start": 21,
      "end": 26,
      "code": "export const generalFilterNames={...galleryEffectNames,lighting:'Lighting Effects',extrude:'Extrude',lensProfile:'Lens Profile Correction',...legacyFilterNames,...filterNames,...advancedFilterNames,displace:'Displace',smartSharpen:'Smart Sharpen',shakeReduction:'Shake Reduction',shear:'Shear',deinterlace:'De-Interlace',sharpen:'Sharpen',sharpenMore:'Sharpen More',edges:'Find Edges',emboss:'Emboss',solarize:'Solarize',posterize:'Posterize',offset:'Offset',twirl:'Twirl',ripple:'Ripple',lens:'Lens Correction'};\nexport type GeneralFilterType=keyof typeof generalFilterNames;\nexport type GeneralFilter=Omit<SmartFilter,'type'> & {type:GeneralFilterType;halftoneShape?:'dot'|'line'|'circle';ditherMode?:'ordered'|'diffusion';ditherColor?:boolean;galleryInk?:string;galleryPaper?:string;lighting?:LightingSettings;extrude?:ExtrudeSettings;lensProfile?:LensProfileSettings;offsetX:number;offsetY:number;edge:'wrap'|'clamp'|'transparent';scale:number;vertical:number;horizontal:number;vignette:number;displacement?:{width:number;height:number;data:string};mapMode?:'stretch'|'tile';redFringe?:number;blueFringe?:number;shear?:number[];removeBlur?:'gaussian'|'motion';iterations?:number;kernel?:number[];divisor?:number;bias?:number};\nexport const defaultGeneralFilter=(type:GeneralFilterType):GeneralFilter=>({id:crypto.randomUUID(),type,radius:type==='posterize'?6:3,amount:type==='lens'?0:type==='noise'?10:100,threshold:type==='traceContour'||Object.hasOwn(galleryEffectNames,type)?128:0,opacity:1,blend:'normal',enabled:true,angle:0,seed:1,distribution:'uniform',monochromatic:true,offsetX:0,offsetY:0,edge:type==='offset'?'wrap':(type==='lens'||type==='lensProfile')?'transparent':'clamp',scale:100,vertical:0,horizontal:0,vignette:0,...(Object.hasOwn(galleryEffectNames,type)?{galleryInk:'#24202c',galleryPaper:'#f7eedb'}:{}),...(type==='lighting'?{lighting:defaultLighting()}:{}),...(type==='extrude'?{extrude:defaultExtrude(),radius:16,amount:30,angle:-45}:{}),...(type==='displace'?{offsetX:10,offsetY:10,mapMode:'stretch' as const}:{}),...(type==='lens'?{redFringe:0,blueFringe:0}:{}),...((type==='smartSharpen'||type==='shakeReduction')?{removeBlur:(type==='shakeReduction'?'motion':'gaussian') as 'motion'|'gaussian',iterations:5,radius:type==='shakeReduction'?2:1}:{}),...(type==='shear'?{shear:[0,20,-20,20,0]}:{}),...(type==='custom'?{kernel:[0,-1,0,-1,5,-1,0,-1,0],divisor:1,bias:0}:{})});\nexport function validateGeneralFilters(value:unknown):asserts value is GeneralFilter[]{\n if(!Array.isArray(value)||!value.length||value.length>16)throw Error('Choose between 1 and 16 filters.');",
      "sha256": "da2a0b0df622b0ae33caf8eeb735e9f4fa619ebd50ce28887e094ec79102590f"
    },
    {
      "file": "app/studio/general-filters.ts",
      "start": 47,
      "end": 49,
      "code": "export const supportsPrecisionGeneralFilter=(type:string)=>!!smartFilterType(type)||hasPrecisionGeneralKernel(type);\nexport function canGeneralFilter(doc:StudioDoc,l?:Layer,type?:string){return (!(doc.precision&&(doc.precision.depth!==8||doc.precision.space!=='RGB'))||!!type&&supportsPrecisionGeneralFilter(type))&&!!l&&!layerLocked(doc,l,'pixels')&&(l.kind==='image'||l.kind==='paint')&&!l.smartObject&&!l.psdData?.placedLayer&&!l.shape&&!l.gridWarp&&!l.puppet;}\nconst check=(cancel:()=>boolean)=>{if(cancel())throw Error('Filter cancelled. No changes applied.');};",
      "sha256": "da2a0b0df622b0ae33caf8eeb735e9f4fa619ebd50ce28887e094ec79102590f"
    },
    {
      "file": "app/studio/general-filters.ts",
      "start": 95,
      "end": 98,
      "code": "export async function applyGeneralFilters(doc:StudioDoc,layer:Layer,filters:GeneralFilter[],cancel=()=>false):Promise<StudioDoc>{\n validateGeneralFilters(filters);if(doc.precision&&(doc.precision.depth!==8||doc.precision.space!=='RGB')&&filters.some(f=>f.enabled&&f.opacity&&!supportsPrecisionGeneralFilter(f.type)))throw Error('This stack contains a filter that requires RGB 8-bit. Remove it or convert explicitly in Image > Color Mode and Precision.');if(!canGeneralFilter(doc,layer,'gaussian')||!filters.every(f=>!f.enabled||!f.opacity||canGeneralFilter(doc,layer,f.type)))throw Error('Select an unlocked raster layer. Use Rasterize Layer for text, shapes or Smart Objects.');if(layer.width*layer.height>16_000_000)throw Error('General filters support up to 16 megapixels per layer.');\n if(doc.precision&&(doc.precision.depth!==8||doc.precision.space!=='RGB')){\n  check(cancel);const before=await precisionLayer(layer,doc.precision,{masks:false});check(cancel);const after=await renderPrecisionGeneralFilters(before,filters,1,cancel),clip=doc.selection?selectionForLayer(doc.selection,layer):undefined,n=precisionChannels(before.space),stride=n+1;",
      "sha256": "da2a0b0df622b0ae33caf8eeb735e9f4fa619ebd50ce28887e094ec79102590f"
    },
    {
      "file": "app/studio/gallery-effects.ts",
      "start": 22,
      "end": 27,
      "code": "const clamp=(v:number,a=0,b=255)=>Math.max(a,Math.min(b,v));\n/** Independent painting, printmaking and paper-texture effects; not Adobe kernels. */\nexport async function galleryEffectPixels(image:ImageData,f:GeneralFilter,ratio=1,cancel=()=>false){\n const {width:w,height:h,data:src}=image,n=w*h;\n if(n>4_000_000)throw Error('Gallery painting and texture effects support up to 4 MP.');\n const check=async()=>{await new Promise<void>(r=>setTimeout(r,0));if(cancel())throw Error('Filter cancelled. No changes applied.');};",
      "sha256": "6bde97046e2b849b517331671508a9f22c9f8e8202d7ff7181bdade137dbd8da"
    }
  ],
  "productionUI": {
    "episode": 34,
    "at": "2026-10-24T00:46:29.674Z",
    "url": "https://slohero.com/photoshot/editor/",
    "inputKind": "AI-generated fictional adult demonstration PNG, not a real-person photograph",
    "effects": [
      "Cutout",
      "Colored Pencil",
      "Texturizer"
    ],
    "cutoutToneDetail": 90,
    "selectedEffectStrength": 65,
    "selectedOpacity": 0.45,
    "stackReordered": true,
    "undoExact": true,
    "actionReplayExact": true,
    "projectReopenExact": true,
    "passed": true,
    "errors": [],
    "imageRevision": "v3: restrained intermediate facial redesign from the original textual face descriptions; text-only generation."
  },
  "checks": [
    {
      "file": "general-filters-render-results.json",
      "sha256": "2c6d6fd1671eddabd491dc2df6eee37db03994f47c80686ab2b38ed0cb2bad2d",
      "results": {
        "passed": true,
        "checks": [
          "Offset has exact wrap-around coordinates and premultiplied transparent pixels",
          "Neutral geometric filters and convolution on constant image",
          "All 106 filters change pixels and preserve selection exterior, masks, position and original document",
          "Locks, invalid inputs and cancellation leave source unchanged",
          "Action semantic replay, atomic failure and PSD/PSB rendered-pixel round trip"
        ]
      },
      "freshRun": true
    },
    {
      "file": "gallery-effects-results.json",
      "sha256": "0e23467444cfe224bc438a00401c7a4c2a155e5170ab4b4efd6212f2b24f3562",
      "results": {
        "passed": true,
        "effects": 48,
        "deterministic": true,
        "seedControls": true,
        "alphaPreserved": true,
        "disabledIdentity": true,
        "invalidRejected": true,
        "cancellation": true
      },
      "freshRun": true
    },
    {
      "file": "gallery-effects-ui-results.json",
      "sha256": "2bf0c50c2017114fe3be3f47db22675d7ea443b41510be3f09199464e58e0b6f",
      "results": {
        "passed": true,
        "sixMenuGroups": true,
        "previewCancel": true,
        "stackControlsAndReorder": true,
        "originalToggle": true,
        "applyUndoRedo": true,
        "recordedReplayExact": true,
        "errors": []
      },
      "freshRun": true
    }
  ],
  "imageDisclosure": "AI 생성 시연 이미지 · 실제 인물 촬영 및 공식 협업 이미지가 아닙니다. 편집 화면과 결과는 실제 포토샷에서 만들었습니다.",
  "imageRevision": {
    "version": 3,
    "at": "2026-10-24T00:46:29.674Z",
    "method": "Text-only intermediate variation with two local adjustments; no reference photographs provided to generator.",
    "sourceSha256": "f06536524ce434a3dcb286c57149b0cf040a638d68ac89e0f1e65e5796440497",
    "previousImagesRetained": true
  }
}