Private/Read-PiskelLayerData.ps1
|
function Read-PiskelLayerData { <# .SYNOPSIS Reads and decodes layer data from a parsed .piskel file. .DESCRIPTION Extracts RGBA pixel data from each layer in a .piskel file by decoding the embedded base64 PNG images. Only processes the first frame of each layer (animation is not supported). .PARAMETER PiskelData Parsed JSON object from a .piskel file. .PARAMETER Width Expected image width in pixels. .PARAMETER Height Expected image height in pixels. .OUTPUTS System.Array of byte arrays, one per valid layer. #> [CmdletBinding()] [OutputType([byte[][]])] param( [Parameter(Mandatory)] [PSObject]$PiskelData, [Parameter(Mandatory)] [int]$Width, [Parameter(Mandatory)] [int]$Height ) $expectedBytes = $Width * $Height * 4 $layers = [System.Collections.Generic.List[byte[]]]::new() foreach ($layerJson in $PiskelData.piskel.layers) { $layer = $layerJson | ConvertFrom-Json if ($layer.frameCount -gt 1) { Write-Warning "Layer '$($layer.name)' has $($layer.frameCount) frames; only the first frame will be used" } $chunk = $layer.chunks[0] $base64Png = $chunk.base64PNG # strip data URI prefix if ($base64Png -match '^data:image/png;base64,') { $base64Png = $base64Png -replace '^data:image/png;base64,', '' } try { $pngBytes = [Convert]::FromBase64String($base64Png) $decoded = ConvertFrom-PngData -Data $pngBytes if ($null -eq $decoded) { Write-Warning "Failed to decode PNG for layer '$($layer.name)'" continue } if ($decoded.RgbaData.Length -eq $expectedBytes) { $layers.Add($decoded.RgbaData) } else { Write-Warning "Layer '$($layer.name)' pixel count mismatch: expected $expectedBytes bytes, got $($decoded.RgbaData.Length)" } } catch { Write-Verbose "Skipped layer '$($layer.name)': $($_.Exception.Message)" } } return , $layers.ToArray() } |