### Full Stretch Workflow Example Source: https://context7.com/beshanoe/pixinscript/llms.txt Demonstrates a typical image stretch workflow combining PixelMath, ColorSaturation, and SCNR. This example assumes an active window and applies the processes sequentially. ```typescript // Usage in a full stretch workflow const targetView = ImageWindow.activeWindow.currentView; applyPixelMath(targetView, 5); if (!targetView.image.isGrayscale) { applyColorSaturation(targetView, 1.0); applySCNR(targetView); } console.noteln("Star Stretch Process Completed!"); ``` -------------------------------- ### Install Dependencies Source: https://github.com/beshanoe/pixinscript/blob/master/docs/GettingStarted.md Install all necessary project dependencies using npm within the cloned PixInScript directory. ```bash npm install ``` -------------------------------- ### Hello World React Script Example Source: https://github.com/beshanoe/pixinscript/blob/master/README.md A basic 'Hello World' script demonstrating React UI components and PixInScript's rendering capabilities. It includes state management for visibility and a counter. ```javascript import React, { useState } from "react"; import { render, useDialog } from "@pixinscript/react"; import { UIHorizontalSizer, UILabel, UIPushButton, UIVerticalSizer, } from "@pixinscript/ui"; function ScriptDialog() { const dialog = useDialog(); const [isVisible, setIsVisible] = useState(false); const [count, setCount] = useState(0); return ( {isVisible && } setIsVisible(!isVisible)} /> dialog.ok()} /> ); } render(, { dialog: { windowTitle: "Hello World Script", minWidth: 400, maxHeight: 300, userResizable: false, }, }); ``` -------------------------------- ### UI Components Source: https://context7.com/beshanoe/pixinscript/llms.txt Examples of various PixInsight UI components wrapped for React, demonstrating their common props and usage patterns. ```APIDOC ## UI Components Every class in the PixInsight control hierarchy has a corresponding `UI*` component that accepts all native properties as React props (including event callbacks as `onXxx` functions) plus layout props `stretchFactor`, `alignment`, `margin`, and `spacing` that are forwarded to the parent `Sizer`. All components use `React.forwardRef` to expose the underlying PixInsight control instance via a ref. ### UINumericControl Built-in label + slider + edit with setPrecision/setValue. ```tsx setStretchAmount(v)} toolTip="

Values above 5 should be used with caution.

" /> ``` ### UIComboBox Items array keeps the combo in sync via useEffect. ```tsx setSelectedIndex(i)} /> ``` ### UIViewList Lists open PixInsight views; mode prop filters what is shown. ```tsx setTargetView(view)} stretchFactor={1} /> ``` ### UIGroupBox With optional title checkbox for enable/disable sections. ```tsx setClosingEnabled(v)} spacing={5} margin={5} > setClosingSize(v)} /> ``` ### UIStretch Acts as a flexible spacer inside a sizer. ```tsx {/* pushes next item to the right */} {}} /> ``` ### UIScrollBox Ref gives direct access to the ScrollBox for scroll events. ```tsx const scrollRef = useRef(null); scrollRef.current?.viewport.update()} onVerticalScrollPosUpdated={() => scrollRef.current?.viewport.update()} /> ``` ``` -------------------------------- ### Build PixInScript Project Source: https://github.com/beshanoe/pixinscript/blob/master/docs/GettingStarted.md Build all packages within the PixInScript monorepo using the 'npm run build' command. Alternatively, use 'npm run dev' to start the development environment for all examples, which recompiles scripts on changes. ```bash npm run build ``` ```bash npm run dev ``` -------------------------------- ### render() Source: https://context7.com/beshanoe/pixinscript/llms.txt Mounts a React component tree into a new PixInsight Dialog. It handles the creation of the dialog, context setup, reconciliation, and displays the modal window. ```APIDOC ## `render()` — Mount a React component tree into a PixInsight Dialog `render` is the main entry point exported by `@pixinscript/react`. It instantiates a `Dialog`, wraps it with `DialogContext`, drives the custom reconciler to populate the dialog's sizer tree with the component tree, and then calls `dialog.execute()` to show the modal window. The `options.dialog` object accepts any `Dialog` property (e.g., `windowTitle`, `userResizable`, `scaledMinWidth`). ### Parameters - **component**: `React.ReactNode` - The root React component to render. - **options**: `object` - Configuration options for the dialog and rendering. - **options.debug**: `boolean` - If true, logs reconciler operations. - **options.dialog**: `object` - Properties for the PixInsight `Dialog`. - **options.dialog.windowTitle**: `string` - The title of the dialog window. - **options.dialog.minWidth**: `number` - The minimum width of the dialog. - **options.dialog.maxHeight**: `number` - The maximum height of the dialog. - **options.dialog.userResizable**: `boolean` - Whether the user can resize the dialog. ### Request Example ```tsx import React from "react"; import { render } from "@pixinscript/react"; import { UILabel, UIVerticalSizer } from "@pixinscript/ui"; function MyDialogContent() { return ( ); } render(, { dialog: { windowTitle: "My Custom Dialog", minWidth: 300, }, }); ``` ``` -------------------------------- ### Build Specific PixInScript Scripts Source: https://github.com/beshanoe/pixinscript/blob/master/docs/GettingStarted.md Build and start the development environment for a specific script, like 'hello-world', using the '--filter' flag with 'npm run dev'. ```bash npm run dev -- --filter hello-world ``` -------------------------------- ### Develop PixInsight Script with Watch Mode Source: https://context7.com/beshanoe/pixinscript/llms.txt Starts Webpack in watch mode for incremental recompiles on file changes. No ZIP is produced in dev mode. Reload PixInsight after rebuilds to see changes. ```bash # Watch mode for the hello-world example (from monorepo root) npm run dev -- --filter hello-world # Or inside the script directory directly pixinscript dev # Output on each rebuild: # Starting watch mode # asset script.js 543 KiB [emitted] # webpack compiled successfully ``` -------------------------------- ### Build PixInScript Project Source: https://github.com/beshanoe/pixinscript/blob/master/README.md Compile the PixInScript project. This command bundles the script and prepares it for PixInsight. ```sh npm run build ``` -------------------------------- ### Build PixInScript with ZIP (Default) Source: https://github.com/beshanoe/pixinscript/blob/master/README.md Compiles the script and creates a ZIP archive ready for PixInsight. This is the default behavior of the build command. ```sh pixinscript build ``` -------------------------------- ### PixInScript Configuration in package.json Source: https://context7.com/beshanoe/pixinscript/llms.txt The CLI reads configuration from the 'pixinscript' key in package.json. 'featureId' and 'featureInfo' are required and injected as header comments. ```json // package.json { "name": "hello-world", "version": "1.0.0", "pixinscript": { "script": { "featureId": "com.example.scripts.HelloWorld", "featureInfo": "A simple Hello World PixInScript example" } }, "scripts": { "build": "pixinscript build", "dev": "pixinscript dev" }, "dependencies": { "@pixinscript/core": "^0.2.1", "@pixinscript/react": "^0.2.1", "@pixinscript/ui": "^0.2.1" } } ``` -------------------------------- ### Zip PixInsight Script Files Source: https://context7.com/beshanoe/pixinscript/llms.txt Creates a ZIP archive from the dist/ folder without recompiling. Useful for packaging after code signing. Custom filenames and internal paths can be specified. ```bash # Default: produces dist/script.zip with files at the archive root pixinscript zip # Custom filename and internal directory path inside the ZIP pixinscript zip -f my-script-v1.0.zip -p "PixInsight/Scripts/MyScript/" # Full signed-script workflow: pixinscript build --no-zip # 1. compile # (sign dist/script.js externally) pixinscript zip -f signed.zip -p "scripts/" # 2. package ``` -------------------------------- ### Workflow for Signed Scripts Source: https://github.com/beshanoe/pixinscript/blob/master/README.md Steps for building and packaging signed scripts. It involves building without a ZIP, signing the JavaScript file, and then creating the final ZIP archive. ```sh pixinscript build --no-zip ``` ```sh pixinscript zip -f signed-script.zip -p "pixinsight/" ``` -------------------------------- ### Build PixInsight Script Source: https://context7.com/beshanoe/pixinscript/llms.txt Compiles TypeScript/TSX source into a PixInsight-compatible script.js bundle. Use --no-zip to skip archive creation, which is necessary for code signing. ```bash # Standard build — outputs dist/script.js and dist/script.zip pixinscript build # Build without ZIP (e.g., prior to code signing) pixinscript build --no-zip # Expected output: # Building script # asset script.js 543 KiB [emitted] (name: main) # webpack 5.x.x compiled successfully in 4321 ms ``` -------------------------------- ### Manage Image Windows in PixInsight Source: https://context7.com/beshanoe/pixinscript/llms.txt Open, create, manipulate, and save image windows using the ImageWindow API. Use temporary off-screen windows for processing. ```typescript // Open an image file and access its main view const windows = ImageWindow.open("/path/to/image.fits"); const win = windows[0]; const view = win.mainView; console.log(`Opened: ${win.filePath} (${view.image.width}×${view.image.height})`); // Create a temporary off-screen processing window const src = ImageWindow.activeWindow.currentView.image; const processingWin = new ImageWindow( src.width, src.height, src.numberOfChannels, src.bitsPerSample, src.isReal, src.isColor ); processingWin.hide(); processingWin.mainView.beginProcess(); processingWin.mainView.image.assign(src); processingWin.mainView.endProcess(); // ... apply transforms ... applyPixelMath(processingWin.mainView, 5); // Export a Bitmap for painting in a ScrollBox viewport const bitmap: Bitmap = processingWin.mainView.image.render(); // Save the result and close the window processingWin.saveAs("/path/to/output.fits"); processingWin.forceClose(); ``` -------------------------------- ### Create ZIP Archive Source: https://github.com/beshanoe/pixinscript/blob/master/README.md Creates a ZIP archive from the 'dist' folder. Options include specifying a custom filename and an internal path structure within the ZIP. ```sh pixinscript zip ``` ```sh pixinscript zip -f custom-name.zip -p "scripts/" ``` -------------------------------- ### Build PixInScript without ZIP Source: https://github.com/beshanoe/pixinscript/blob/master/README.md Compiles the script without creating a ZIP archive. This is useful for scripts that require code signing before packaging. ```sh pixinscript build --no-zip ``` -------------------------------- ### Render React Component into PixInsight Dialog Source: https://context7.com/beshanoe/pixinscript/llms.txt Use `render` to mount a React component tree into a new PixInsight Dialog. Options can configure dialog properties like title and size. ```tsx import React, { useState } from "react"; import { render, useDialog } from "@pixinscript/react"; import { UIVerticalSizer, UILabel, UIPushButton, UIHorizontalSizer, } from "@pixinscript/ui"; function ScriptDialog() { const dialog = useDialog(); const [count, setCount] = useState(0); const [visible, setVisible] = useState(false); return ( {visible && } setVisible((v) => !v)} /> setCount((c) => c + 1)} /> setCount((c) => c - 1)} /> dialog.ok()} /> ); } render(, { debug: false, // set true to log reconciler operations dialog: { windowTitle: "Hello World Script", minWidth: 400, maxHeight: 300, userResizable: false, }, }); ``` -------------------------------- ### Utilize Polyfilled Browser APIs in PixInsight Source: https://context7.com/beshanoe/pixinscript/llms.txt The @pixinscript/core/polyfill enables standard browser APIs like setTimeout, setInterval, and console methods within PixInsight scripts. It must be the first Webpack entry point. ```javascript // Polyfill is loaded automatically by the CLI via webpack.config.ts: // entry: ["@pixinscript/core/polyfill", "src/index"] // After loading, these APIs work as expected inside PixInsight scripts: timeout(() => { console.log("runs after 500 ms using PixInsight Timer"); }, 500); const id = setInterval(() => { console.log("repeating every 1 s"); }, 1000); clearInterval(id); // console methods map to PixInsight Console: console.log("info message"); // → Console.writeln(...) console.warn("warning"); // → Console.warning(...) console.error("error"); // → Console.critical(...) ``` -------------------------------- ### directRender() Source: https://context7.com/beshanoe/pixinscript/llms.txt A lower-level API to render a React component tree into an existing PixInsight `Control` or `Sizer`, useful for embedding React sub-trees. ```APIDOC ## `directRender()` — Render into an arbitrary Control or Sizer `directRender` is a lower-level API that lets you mount a React tree into any existing PixInsight `Control` or `Sizer` rather than creating a new top-level `Dialog`. Useful when embedding a React-managed sub-tree inside a manually constructed dialog or inside a `UIScrollBox` viewport. ### Parameters - **component**: `React.ReactNode` - The root React component to render. - **container**: `Control | Sizer` - The PixInsight Control or Sizer to render into. ### Request Example ```tsx import React from "react"; import { directRender } from "@pixinscript/react"; import { UILabel, UIVerticalSizer } from "@pixinscript/ui"; // Assume `existingFrame` is a PixInsight Frame control already added to a dialog const existingFrame = new Frame(); directRender( , existingFrame // container must be a Control or Sizer ); // The frame's sizer is now managed by the React reconciler; subsequent state changes will update controls automatically. ``` ``` -------------------------------- ### Configure PixinscriptWebpackPlugin in Webpack Source: https://context7.com/beshanoe/pixinscript/llms.txt Use this Webpack configuration to integrate the PixinscriptWebpackPlugin. Ensure optimization.minimize is false for PixInsight readability. The plugin injects required feature headers. ```typescript import { PixinscriptWebpackPlugin } from "@pixinscript/webpack-plugin"; import * as path from "path"; import webpack = require("webpack"); const config: webpack.Configuration = { entry: ["@pixinscript/core/polyfill", "./src/index"], mode: "production", optimization: { minimize: false }, // PixInsight requires readable source module: { rules: [ { test: /\.tsx?$/, use: "ts-loader", exclude: /node_modules/ }, { test: /\.m?jsx?$/, use: { loader: "babel-loader", options: { presets: [ ["@babel/preset-env", { targets: { ie: "8" }, useBuiltIns: "entry", corejs: "3" }], "@babel/preset-react", ], }, }, }, ], }, resolve: { extensions: [".tsx", ".ts", ".js", ".jsx"] }, output: { filename: "script.js", path: path.resolve(__dirname, "dist") }, plugins: [ new PixinscriptWebpackPlugin({ featureId: "com.example.MyScript", featureInfo: "My custom PixInsight processing script", }), // Resulting script.js will begin with: // #feature-id com.example.MyScript // #feature-info My custom PixInsight processing script // (bundled JS follows) ], }; ``` -------------------------------- ### Render React Component into Existing PixInsight Control Source: https://context7.com/beshanoe/pixinscript/llms.txt Use `directRender` to mount a React component tree into an existing PixInsight `Control` or `Sizer`. This is useful for embedding React sub-trees within manually constructed dialogs. ```tsx import React from "react"; import { directRender } from "@pixinscript/react"; import { UILabel, UIVerticalSizer } from "@pixinscript/ui"; // Assume `existingFrame` is a PixInsight Frame control already added to a dialog const existingFrame = new Frame(); directRender( , existingFrame // container must be a Control or Sizer ); // The frame's sizer is now managed by the React reconciler; // subsequent state changes will update controls automatically. ``` -------------------------------- ### useDialog() Source: https://context7.com/beshanoe/pixinscript/llms.txt A React context hook that provides access to the `Dialog` instance created by `render()`, allowing interaction with dialog methods like `ok()`, `cancel()`, and `newInstance()` from any component. ```APIDOC ## `useDialog()` — Access the enclosing Dialog from any component A React context hook exported by `@pixinscript/react` that returns the `Dialog` instance created by `render()`. Use it to call `dialog.ok()`, `dialog.cancel()`, `dialog.newInstance()`, or any other `Dialog` method from deep within the component tree without prop-drilling. ### Returns - **dialog**: `Dialog` - The PixInsight `Dialog` instance. ### Usage Example ```tsx import React from "react"; import { useDialog } from "@pixinscript/react"; import { UIHorizontalSizer, UIPushButton, UIToolButton } from "@pixinscript/ui"; function DialogFooter() { const dialog = useDialog(); return ( { Parameters.set("version", "1.0"); dialog.newInstance(); }} /> dialog.cancel()} /> dialog.ok()} /> ); } ``` ``` -------------------------------- ### React-wrapped PixInsight UI Controls Source: https://context7.com/beshanoe/pixinscript/llms.txt Use these components to integrate PixInsight controls into React applications. They accept native PixInsight properties as props and forward layout props to the parent Sizer. Components use React.forwardRef to expose the underlying PixInsight control instance. ```tsx import React, { useRef } from "react"; import { UIVerticalSizer, UIHorizontalSizer, UILabel, UIEdit, UICheckBox, UIComboBox, UINumericControl, UISpinBox, UISlider, UITextBox, UIGroupBox, UIViewList, UIStretch, UIPushButton, UIScrollBox, UIToolButton, UITabBox, UITreeBox, } from "@pixinscript/ui"; // UINumericControl — built-in label + slider + edit with setPrecision/setValue setStretchAmount(v)} toolTip="

Values above 5 should be used with caution.

" /> // UIComboBox — items array keeps the combo in sync via useEffect setSelectedIndex(i)} /> // UIViewList — lists open PixInsight views; mode prop filters what is shown setTargetView(view)} stretchFactor={1} /> // UIGroupBox with optional title checkbox for enable/disable sections setClosingEnabled(v)} spacing={5} margin={5} > setClosingSize(v)} /> // UIStretch — acts as a flexible spacer inside a sizer {/* pushes next item to the right */} {}} /> // UIScrollBox — ref gives direct access to the ScrollBox for scroll events const scrollRef = useRef(null); scrollRef.current?.viewport.update()} onVerticalScrollPosUpdated={() => scrollRef.current?.viewport.update()} /> ``` -------------------------------- ### Boost Color Saturation with Akima Spline Source: https://context7.com/beshanoe/pixinscript/llms.txt Enhances color saturation using the ColorSaturation process class with an Akima-spline curve. The 'satAmount' parameter controls the overall saturation boost. ```typescript // Boost color saturation with an Akima-spline curve export function applyColorSaturation(view: View, satAmount: number) { const P = new ColorSaturation(); P.HS = [ [0.0, satAmount * 0.4], [0.5, satAmount * 0.7], [1.0, satAmount * 0.4], ]; P.HSt = ColorSaturation.prototype.AkimaSubsplines; P.hueShift = 0.0; P.executeOn(view); } ``` -------------------------------- ### Apply Hyperbolic Stretch with PixelMath Source: https://context7.com/beshanoe/pixinscript/llms.txt Applies a hyperbolic stretch to an image using the PixelMath process class. Adjust the 'amount' parameter to control the intensity of the stretch. ```typescript import type { View } from "@pixinscript/core"; // type only — runtime is global // Apply a hyperbolic stretch using PixelMath export function applyPixelMath(view: View, amount: number) { const P = new PixelMath(); P.expression = `((3^${amount})*$T)/((3^${amount} - 1)*$T + 1)`; P.executeOn(view); } ``` -------------------------------- ### Save and Load Script Parameters Source: https://context7.com/beshanoe/pixinscript/llms.txt Persist script parameters using the global Parameters object. Load parameters only if they exist to avoid errors. ```typescript // Define all parameter defaults in one place export const ScriptParameters = { amount: 5, satAmount: 1, removeGreen: false, save() { Parameters.set("amount", ScriptParameters.amount); Parameters.set("satAmount", ScriptParameters.satAmount); Parameters.set("removeGreen", ScriptParameters.removeGreen); }, load() { if (Parameters.has("amount")) ScriptParameters.amount = Parameters.getReal("amount"); if (Parameters.has("satAmount")) ScriptParameters.satAmount = Parameters.getReal("satAmount"); if (Parameters.has("removeGreen")) ScriptParameters.removeGreen = Parameters.getBoolean("removeGreen"); }, }; // In your script entry point: function main() { if (Parameters.isGlobalTarget) { Console.criticalln("Script cannot run in global context."); return; } if (Parameters.isViewTarget) { ScriptParameters.load(); applyPixelMath(Parameters.targetView, ScriptParameters.amount); return; } render(, { dialog: { windowTitle: "My Script" } }); } main(); ``` -------------------------------- ### Clone PixInScript Repository Source: https://github.com/beshanoe/pixinscript/blob/master/docs/GettingStarted.md Clone the PixInScript monorepo to work directly within it. This is recommended for contributing to TypeScript definitions and the project. ```bash git clone https://github.com/beshanoe/pixinscript.git cd pixinscript ``` -------------------------------- ### Access Dialog Instance with useDialog Hook Source: https://context7.com/beshanoe/pixinscript/llms.txt The `useDialog` hook provides access to the `Dialog` instance created by `render()`. Use it to call dialog methods like `ok()`, `cancel()`, or `newInstance()` from any component within the dialog's tree. ```tsx import React from "react"; import { useDialog } from "@pixinscript/react"; import { UIHorizontalSizer, UIPushButton, UIToolButton } from "@pixinscript/ui"; function DialogFooter() { const dialog = useDialog(); return ( {/* Save parameters as a draggable script instance */} { // persist any Parameters before creating the instance Parameters.set("version", "1.0"); dialog.newInstance(); }} /> dialog.cancel()} /> dialog.ok()} /> ); } ``` -------------------------------- ### Use PJSR Enum Constants from @pixinscript/core Source: https://context7.com/beshanoe/pixinscript/llms.txt Import and use typed enum constants from @pixinscript/core for PJSR flags and modes to ensure type safety and improve IDE autocompletion, avoiding raw integer literals. ```typescript import { TextAlign_Left, TextAlign_VertCenter, TextAlign_Right, StdCursor_OpenHand, StdCursor_ClosedHand, FrameStyle_Box, ColorSpace, ImageOp, Interpolation, SampleType, MorphOp, } from "@pixinscript/core"; // Use in UI component props // Use with native PixInsight API calls const img = new Image(); img.colorSpace = ColorSpace.RGB; const cursor = new Cursor(StdCursor_OpenHand); controlRef.current!.viewport.cursor = cursor; // Morphological operator type — avoids magic numbers img.morphologicalTransformation(MorphOp.Dilation, [structureMatrix]); ``` -------------------------------- ### useCombinedRefs Utility Source: https://context7.com/beshanoe/pixinscript/llms.txt A utility function to merge multiple refs onto a single element, useful when a component needs to expose its ref while also maintaining an internal ref. ```APIDOC ## `useCombinedRefs()` — Merge multiple refs onto one element A utility exported from `@pixinscript/ui` that merges a forwarded outer ref with an internal `useRef`. Necessary whenever a component both exposes a ref to its parent and needs its own internal ref to the same native control. ```tsx import React, { useRef } from "react"; import { UIScrollBox, useCombinedRefs } from "@pixinscript/ui"; const ScrollControl = React.forwardRef (({ minWidth }, outerRef) => { const innerRef = React.useRef(null); // Both innerRef.current and outerRef.current will point to the same ScrollBox const ref = useCombinedRefs(outerRef, innerRef); React.useEffect(() => { if (!ref.current) return; ref.current.autoScroll = true; ref.current.viewport.onPaint = (x0, y0, x1, y1) => { const g = new Graphics(ref.current!.viewport); g.fillRect(x0, y0, x1, y1, new Brush(0xff000000)); g.end(); }; }, []); return ; } ); ``` ``` -------------------------------- ### Extract Structures with Multiscale Linear Transform Source: https://context7.com/beshanoe/pixinscript/llms.txt Detects and extracts star structures from an image using the Starlet transform via the MultiscaleLinearTransform process. Specify the minimum and maximum layers for structure detection. ```typescript // Multiscale star structure detection via Starlet transform export function extractStructures( image: Image, minLayer: number, maxLayer: number ): Image { const copy = new Image(); copy.assign(image); const layers = []; for (let i = 1; i <= maxLayer + 1; i++) { layers.push([i >= minLayer && i <= maxLayer, true, 0.0, false, 3.0, 1.0, 1]); } const P = new MultiscaleLinearTransform(); P.layers = layers; P.transform = MultiscaleLinearTransform.prototype.StarletTransform; P.executeOn(copy); return copy; } ``` -------------------------------- ### Subtract Images Pixel-by-Pixel Source: https://context7.com/beshanoe/pixinscript/llms.txt Performs pixel-wise subtraction between two images, clamping the result at 0. This operation is performed on a copy of the first image, leaving the original unmodified. ```typescript // Subtract two images pixel-by-pixel (clamp at 0) export function subtract(image: Image, second: Image): Image { const result = new Image(); result.assign(image); result.initPixelIterator(); second.initPixelIterator(); const v1 = new Vector(), v2 = new Vector(); do { result.getPixelValue(v1); second.getPixelValue(v2); v2.isLessThan(v1) ? v1.sub(v2) : v1.mul(0); result.setPixelValue(v1); second.nextPixel(); } while (result.nextPixel()); return result; } ``` -------------------------------- ### Merge Refs with useCombinedRefs Hook Source: https://context7.com/beshanoe/pixinscript/llms.txt Use `useCombinedRefs` to merge an outer forwarded ref with an internal `useRef`. This is essential when a component needs to expose a ref to its parent while also using its own internal ref for the same native control. Ensure the ref type matches the native control. ```tsx import React from "react"; import { UIScrollBox, useCombinedRefs } from "@pixinscript/ui"; const ScrollControl = React.forwardRef (({ minWidth }, outerRef) => { const innerRef = React.useRef(null); // Both innerRef.current and outerRef.current will point to the same ScrollBox const ref = useCombinedRefs(outerRef, innerRef); React.useEffect(() => { if (!ref.current) return; ref.current.autoScroll = true; ref.current.viewport.onPaint = (x0, y0, x1, y1) => { const g = new Graphics(ref.current!.viewport); g.fillRect(x0, y0, x1, y1, new Brush(0xff000000)); g.end(); }; }, []); return ; }); ``` -------------------------------- ### Blend Images Through a Mask Source: https://context7.com/beshanoe/pixinscript/llms.txt Blends two images (source and destination) using a mask. The operation is defined as out = src*(1-mask) + dst*mask. This function operates on pixel data directly. ```typescript // Blend two images through a mask: out = src*(1-mask) + dst*mask export function assignThroughMask(src: Image, dst: Image, mask: Image): Image { mask.colorSpace = src.colorSpace; const result = new Image(); result.assign(src); result.initPixelIterator(); dst.initPixelIterator(); mask.initPixelIterator(); const v1 = new Vector(), v2 = new Vector(), vM = new Vector(); const old = new Vector(v1.length); do { result.getPixelValue(v1); dst.getPixelValue(v2); mask.getPixelValue(vM); v2.mul(vM); for (let i = 0; i < v1.length; i++) old.at(i, v1.at(i)); v1.mul(vM); old.sub(v1); old.add(v2); result.setPixelValue(old); dst.nextPixel(); mask.nextPixel(); } while (result.nextPixel()); return result; } ``` -------------------------------- ### Remove Green Cast with SCNR Source: https://context7.com/beshanoe/pixinscript/llms.txt Removes green color casts from an image using the Subtractive Chromatic Noise Reduction (SCNR) process. It preserves lightness by default and uses the average neutral protection method. ```typescript // Remove green cast using Subtractive Chromatic Noise Reduction export function applySCNR(view: View) { const P = new SCNR(); P.amount = 1.0; P.protectionMethod = SCNR.prototype.AverageNeutral; P.colorToRemove = SCNR.prototype.Green; P.preserveLightness = true; P.executeOn(view); } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.