mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-09 13:45:26 +02:00
Make image preview code re-useable for other types of previews that have both metadata and an image
This commit is contained in:
@@ -283,14 +283,14 @@ func (self *GraphicsHandler) RenderImagePreview(h *Handler, p *ImagePreview, x,
|
||||
}
|
||||
files_supported := self.files_supported.Load()
|
||||
|
||||
if p.img_metadata.Width <= px_width && p.img_metadata.Height <= px_height {
|
||||
if p.custom_metadata.image.Width <= px_width && p.custom_metadata.image.Height <= px_height {
|
||||
if files_supported {
|
||||
self.transmit(h.lp, nil, p.img_metadata, p.cached_data)
|
||||
self.transmit(h.lp, nil, p.custom_metadata.image, p.cached_data)
|
||||
} else {
|
||||
if err = p.ensure_source_image(); err != nil {
|
||||
return
|
||||
}
|
||||
self.transmit(h.lp, p.source_img, p.img_metadata, nil)
|
||||
self.transmit(h.lp, p.source_img, p.custom_metadata.image, nil)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -35,19 +35,25 @@ type ShowData struct {
|
||||
metadata fs.FileInfo
|
||||
x, y, width, height int
|
||||
cached_data map[string]string
|
||||
img_metadata *images.SerializableImageMetadata
|
||||
custom_metadata metadata
|
||||
}
|
||||
|
||||
type PreviewRenderer interface {
|
||||
Render(string) (map[string][]byte, *images.ImageData, error)
|
||||
Unmarshall(map[string]string) (any, error)
|
||||
Render(string) (map[string][]byte, metadata, *images.ImageData, error)
|
||||
ShowMetadata(h *Handler, s ShowData) int
|
||||
}
|
||||
|
||||
type render_data struct {
|
||||
cached_data map[string]string
|
||||
img *images.ImageData
|
||||
img_metadata *images.SerializableImageMetadata
|
||||
err error
|
||||
cached_data map[string]string
|
||||
img *images.ImageData
|
||||
metadata metadata
|
||||
err error
|
||||
}
|
||||
|
||||
type metadata struct {
|
||||
image *images.SerializableImageMetadata
|
||||
custom any
|
||||
}
|
||||
|
||||
type ImagePreview struct {
|
||||
@@ -59,7 +65,7 @@ type ImagePreview struct {
|
||||
render_channel chan render_data
|
||||
ready atomic.Bool
|
||||
source_img *images.ImageData
|
||||
img_metadata *images.SerializableImageMetadata
|
||||
custom_metadata metadata
|
||||
renderer PreviewRenderer
|
||||
file_metadata_preview Preview
|
||||
WakeupMainThread func() bool
|
||||
@@ -124,7 +130,7 @@ func (p *ImagePreview) render_image(h *Handler, x, y, width, height int) {
|
||||
|
||||
offset := p.renderer.ShowMetadata(h, ShowData{
|
||||
abspath: p.abspath, metadata: p.metadata, x: x, y: y, width: width, height: height, cached_data: p.cached_data,
|
||||
img_metadata: p.img_metadata,
|
||||
custom_metadata: p.custom_metadata,
|
||||
})
|
||||
h.graphics_handler.RenderImagePreview(h, p, x, y+offset, width, height-offset)
|
||||
}
|
||||
@@ -143,7 +149,7 @@ func (p *ImagePreview) Render(h *Handler, x, y, width, height int) {
|
||||
p.render_channel = nil
|
||||
p.cached_data = hd.cached_data
|
||||
p.source_img = hd.img
|
||||
p.img_metadata = hd.img_metadata
|
||||
p.custom_metadata = hd.metadata
|
||||
if hd.err != nil {
|
||||
p.render_err = NewErrorPreview(fmt.Errorf("Failed to render the preview with error: %w", hd.err))
|
||||
}
|
||||
@@ -178,20 +184,21 @@ func (p *ImagePreview) start_rendering() {
|
||||
if b, err := os.ReadFile(d); err == nil {
|
||||
var m images.SerializableImageMetadata
|
||||
if err = json.Unmarshal(b, &m); err == nil {
|
||||
p.render_channel <- render_data{cached_data: ans, img_metadata: &m}
|
||||
return
|
||||
if cm, err := p.renderer.Unmarshall(ans); err == nil {
|
||||
p.render_channel <- render_data{cached_data: ans, metadata: metadata{image: &m, custom: cm}}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
rdata, img, err := p.renderer.Render(p.abspath)
|
||||
rdata, metadata, img, err := p.renderer.Render(p.abspath)
|
||||
if err != nil {
|
||||
p.render_channel <- render_data{err: err}
|
||||
} else {
|
||||
ans, err = p.disk_cache.AddPath(p.abspath, key, rdata)
|
||||
if err == nil {
|
||||
m := img.SerializeOnlyMetadata()
|
||||
p.render_channel <- render_data{cached_data: ans, img_metadata: &m, img: img}
|
||||
p.render_channel <- render_data{cached_data: ans, metadata: metadata, img: img}
|
||||
} else {
|
||||
p.render_channel <- render_data{err: err}
|
||||
}
|
||||
@@ -200,17 +207,18 @@ func (p *ImagePreview) start_rendering() {
|
||||
|
||||
type ImagePreviewRenderer uint
|
||||
|
||||
func (p ImagePreviewRenderer) Render(abspath string) (ans map[string][]byte, img *images.ImageData, err error) {
|
||||
func (p ImagePreviewRenderer) Render(abspath string) (ans map[string][]byte, m metadata, img *images.ImageData, err error) {
|
||||
if img, err = images.OpenImageFromPath(abspath); err != nil {
|
||||
return nil, nil, err
|
||||
return nil, metadata{}, nil, err
|
||||
}
|
||||
m, data := img.Serialize()
|
||||
im, data := img.Serialize()
|
||||
ans = make(map[string][]byte, len(data)+1)
|
||||
metadata, err := json.Marshal(m)
|
||||
sm, err := json.Marshal(im)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, metadata{}, nil, err
|
||||
}
|
||||
ans[IMAGE_METADATA_KEY] = metadata
|
||||
ans[IMAGE_METADATA_KEY] = sm
|
||||
m = metadata{image: &im}
|
||||
for i, d := range data {
|
||||
key := IMAGE_DATA_PREFIX + strconv.Itoa(i)
|
||||
ans[key] = d
|
||||
@@ -218,11 +226,13 @@ func (p ImagePreviewRenderer) Render(abspath string) (ans map[string][]byte, img
|
||||
return
|
||||
}
|
||||
|
||||
func (p ImagePreviewRenderer) Unmarshall(map[string]string) (any, error) { return nil, nil }
|
||||
|
||||
func (p ImagePreviewRenderer) ShowMetadata(h *Handler, s ShowData) int {
|
||||
text := ""
|
||||
offset := 0
|
||||
if s.img_metadata != nil {
|
||||
text = fmt.Sprintf("%s: %dx%d %s", s.img_metadata.Format_uppercase, s.img_metadata.Width, s.img_metadata.Height, humanize.Bytes(uint64(s.metadata.Size())))
|
||||
if m := s.custom_metadata.image; m != nil {
|
||||
text = fmt.Sprintf("%s: %dx%d %s", m.Format_uppercase, m.Width, m.Height, humanize.Bytes(uint64(s.metadata.Size())))
|
||||
icon := icons.IconForPath("/a.gif")
|
||||
text = icon + " " + text
|
||||
offset += h.render_wrapped_text_in_region(text, s.x, s.y, s.width, s.height, true)
|
||||
|
||||
Reference in New Issue
Block a user