E56RSY75LHUPKXPOPPGFDHPSACMRWPHOAD2GREJN3OFPA6QFM64QC }}return img}// CreateRGBImage creates an image.Image from a 2D RGBPixel array.// The array is organized as [rows][cols] where rows = frequency bins.func CreateRGBImage(data [][]RGBPixel) image.Image {if len(data) == 0 || len(data[0]) == 0 {return nil}height := len(data)width := len(data[0])img := image.NewRGBA(image.Rect(0, 0, width, height))for y := 0; y < height; y++ {for x := 0; x < width; x++ {img.SetRGBA(x, y, color.RGBA{R: data[y][x].R,G: data[y][x].G,B: data[y][x].B,A: 255,})
if isGray {result := image.NewGray(image.Rect(0, 0, newWidth, newHeight))for y := 0; y < newHeight; y++ {for x := 0; x < newWidth; x++ {srcX := int(float64(x) * scaleX)srcY := int(float64(y) * scaleY)if srcX >= srcWidth {srcX = srcWidth - 1}if srcY >= srcHeight {srcY = srcHeight - 1}c := img.At(srcX+bounds.Min.X, srcY+bounds.Min.Y)gray := color.GrayModel.Convert(c).(color.Gray)result.SetGray(x, y, gray)}}return result}
return result
// encodePNG encodes an image to PNG format.// Detects whether image is grayscale or RGB and uses appropriate encoder.func encodePNG(img image.Image, w io.Writer) error {if _, ok := img.(*image.Gray); ok {return encodeGrayscalePNG(img, w)}return encodeRGBPNG(img, w)
// PNG signaturesignature := []byte{0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A}if _, err := w.Write(signature); err != nil {return err}// IHDR chunkihdr := make([]byte, 13)ihdr[0] = byte(width >> 24)ihdr[1] = byte(width >> 16)ihdr[2] = byte(width >> 8)ihdr[3] = byte(width)ihdr[4] = byte(height >> 24)ihdr[5] = byte(height >> 16)ihdr[6] = byte(height >> 8)ihdr[7] = byte(height)ihdr[8] = 8 // bit depthihdr[9] = 2 // color type: RGBihdr[10] = 0 // compression: deflateihdr[11] = 0 // filter: adaptiveihdr[12] = 0 // interlace: noneif err := writePNGChunk(w, "IHDR", ihdr); err != nil {return err}// IDAT chunk (image data)// RGB: 3 bytes per pixel + 1 filter byte per rowrawData := make([]byte, 0, height*(width*3+1))for y := 0; y < height; y++ {rawData = append(rawData, 0) // filter byte (none)for x := 0; x < width; x++ {r, g, b, _ := img.At(x+bounds.Min.X, y+bounds.Min.Y).RGBA()rawData = append(rawData, byte(r>>8), byte(g>>8), byte(b>>8))}}compressed := deflateCompress(rawData)if err := writePNGChunk(w, "IDAT", compressed); err != nil {return err}// IEND chunkif err := writePNGChunk(w, "IEND", nil); err != nil {return err}return nil}
package utils// RGBPixel represents an RGB color valuetype RGBPixel struct {R, G, B uint8}// L4Colormap is the Black-Red-Yellow heat colormap from PerceptualColourMaps.jl// Control points:// Index 0: Black (0.0, 0.0, 0.0)// Index 85: Dark Red (0.85, 0.0, 0.0)// Index 170: Orange-Red (1.0, 0.15, 0.0)// Index 255: Yellow (1.0, 1.0, 0.0)var L4Colormap [256]RGBPixelfunc init() {// Generate L4 colormap using piecewise linear interpolation// This avoids overshoot issues with cubic splinescontrolPoints := []struct {idx intr float64g float64b float64}{{0, 0.0, 0.0, 0.0},{85, 0.85, 0.0, 0.0},{170, 1.0, 0.15, 0.0},{255, 1.0, 1.0, 0.0},}for i := 0; i < 256; i++ {// Find the segment we're invar seg intfor seg = 0; seg < len(controlPoints)-1; seg++ {if i <= controlPoints[seg+1].idx {break}}if seg >= len(controlPoints)-1 {seg = len(controlPoints) - 2}// Linear interpolation within segmentp0 := controlPoints[seg]p1 := controlPoints[seg+1]t := 0.0if p1.idx != p0.idx {t = float64(i-p0.idx) / float64(p1.idx-p0.idx)}L4Colormap[i] = RGBPixel{R: uint8((p0.r + t*(p1.r-p0.r)) * 255.0),G: uint8((p0.g + t*(p1.g-p0.g)) * 255.0),B: uint8((p0.b + t*(p1.b-p0.b)) * 255.0),}}}// ApplyL4Colormap converts a grayscale image to RGB using the L4 colormapfunc ApplyL4Colormap(grayscale [][]uint8) [][]RGBPixel {if len(grayscale) == 0 || len(grayscale[0]) == 0 {return nil}rows := len(grayscale)cols := len(grayscale[0])result := make([][]RGBPixel, rows)for i := range result {result[i] = make([]RGBPixel, cols)}for y := 0; y < rows; y++ {for x := 0; x < cols; x++ {result[y][x] = L4Colormap[grayscale[y][x]]}}return result}
// Create imageimg := utils.CreateGrayscaleImage(spectrogram)
// Create image (grayscale or color)var img image.Imageif input.Color {// Apply L4 colormapcolorData := utils.ApplyL4Colormap(spectrogram)img = utils.CreateRGBImage(colorData)} else {img = utils.CreateGrayscaleImage(spectrogram)}