icat: Report panics in the render function correctly

Also, only fallback to imagemagick on error when the engine is not
specified as builtin
This commit is contained in:
Kovid Goyal
2025-10-15 08:17:53 +05:30
parent dd7caaa91b
commit 284ae74201
4 changed files with 32 additions and 14 deletions

View File

@@ -5,6 +5,7 @@ package icat
import ( import (
"fmt" "fmt"
"github.com/kovidgoyal/go-parallel"
"github.com/kovidgoyal/kitty/tools/tui/graphics" "github.com/kovidgoyal/kitty/tools/tui/graphics"
"github.com/kovidgoyal/kitty/tools/utils/images" "github.com/kovidgoyal/kitty/tools/utils/images"
) )
@@ -31,6 +32,11 @@ func Render(path string, ro *images.RenderOptions, frames []images.IdentifyRecor
} }
func render_image_with_magick(imgd *image_data, src *opened_input) (err error) { func render_image_with_magick(imgd *image_data, src *opened_input) (err error) {
defer func() {
if r := recover(); r != nil {
err = parallel.Format_stacktrace_on_panic(r, 1)
}
}()
err = src.PutOnFilesystem() err = src.PutOnFilesystem()
if err != nil { if err != nil {
return err return err

View File

@@ -4,13 +4,15 @@ package icat
import ( import (
"fmt" "fmt"
"image"
"image/gif"
"github.com/kovidgoyal/go-parallel"
"github.com/kovidgoyal/kitty/tools/tty" "github.com/kovidgoyal/kitty/tools/tty"
"github.com/kovidgoyal/kitty/tools/tui/graphics" "github.com/kovidgoyal/kitty/tools/tui/graphics"
"github.com/kovidgoyal/kitty/tools/utils" "github.com/kovidgoyal/kitty/tools/utils"
"github.com/kovidgoyal/kitty/tools/utils/images" "github.com/kovidgoyal/kitty/tools/utils/images"
"github.com/kovidgoyal/kitty/tools/utils/shm" "github.com/kovidgoyal/kitty/tools/utils/shm"
"image"
"image/gif"
"github.com/kovidgoyal/exiffix" "github.com/kovidgoyal/exiffix"
"github.com/kovidgoyal/imaging" "github.com/kovidgoyal/imaging"
@@ -151,6 +153,11 @@ func add_gif_frames(ctx *images.Context, imgd *image_data, gf *gif.GIF) error {
} }
func render_image_with_go(imgd *image_data, src *opened_input) (err error) { func render_image_with_go(imgd *image_data, src *opened_input) (err error) {
defer func() {
if r := recover(); r != nil {
err = parallel.Format_stacktrace_on_panic(r, 1)
}
}()
ctx := images.Context{} ctx := images.Context{}
switch { switch {
case imgd.format_uppercase == "GIF" && opts.Loop != 0: case imgd.format_uppercase == "GIF" && opts.Loop != 0:

View File

@@ -279,7 +279,7 @@ func process_arg(arg input_arg) {
var format string var format string
var err error var err error
imgd := image_data{source_name: arg.value} imgd := image_data{source_name: arg.value}
if opts.Engine == "auto" || opts.Engine == "native" { if opts.Engine == "auto" || opts.Engine == "builtin" {
c, format, err = image.DecodeConfig(f.file) c, format, err = image.DecodeConfig(f.file)
f.Rewind() f.Rewind()
can_use_go = err == nil can_use_go = err == nil
@@ -299,12 +299,16 @@ func process_arg(arg input_arg) {
} }
err = render_image_with_go(&imgd, &f) err = render_image_with_go(&imgd, &f)
if err != nil { if err != nil {
merr := render_image_with_magick(&imgd, &f) if opts.Engine != "builtin" {
if merr != nil { merr := render_image_with_magick(&imgd, &f)
report_error(arg.value, "Could not render image to RGB", err) if merr != nil {
return report_error(arg.value, "Could not render image to RGB", err)
return
}
err = nil
} }
err = nil report_error(arg.value, "could not render", err)
return
} }
} else { } else {
err = render_image_with_magick(&imgd, &f) err = render_image_with_magick(&imgd, &f)

View File

@@ -24,16 +24,17 @@ func (self *Context) run_paste(src imaging.Scanner, background image.Image, pos
var pix []uint8 var pix []uint8
switch v := background.(type) { switch v := background.(type) {
case *image.NRGBA: case *image.NRGBA:
i := background.(*image.NRGBA) stride = v.Stride
stride = i.Stride pix = v.Pix
pix = i.Pix
case *imaging.NRGB: case *imaging.NRGB:
i := background.(*imaging.NRGB) stride = v.Stride
stride = i.Stride pix = v.Pix
pix = i.Pix
default: default:
panic(fmt.Sprintf("Unsupported image type: %v", v)) panic(fmt.Sprintf("Unsupported image type: %v", v))
} }
if len(pix) != background.Bounds().Dy()*stride {
panic(fmt.Sprintf("background image has insufficient pixel data. Bounds: %v Stride: %d", background.Bounds(), stride))
}
if err := self.SafeParallel(interRect.Min.Y, interRect.Max.Y, func(ys <-chan int) { if err := self.SafeParallel(interRect.Min.Y, interRect.Max.Y, func(ys <-chan int) {
for y := range ys { for y := range ys {
x1 := interRect.Min.X - pasteRect.Min.X x1 := interRect.Min.X - pasteRect.Min.X