github.com/xyproto/orbiton/v2@v2.65.12-0.20240516144430-e10a419274ec/image.go (about)

     1  package main
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"image"
     7  	"path/filepath"
     8  
     9  	"github.com/xyproto/carveimg"
    10  	"github.com/xyproto/vt100"
    11  	"golang.org/x/image/draw"
    12  )
    13  
    14  // var imageResizeFunction = draw.NearestNeighbor
    15  // var imageResizeFunction = draw.ApproxBiLinear
    16  // var imageResizeFunction = draw.BiLinear
    17  var imageResizeFunction = draw.CatmullRom
    18  
    19  func displayImage(c *vt100.Canvas, filename string, waitForKeypress bool) error {
    20  	// Find the width and height of the canvas
    21  	width := int(c.Width())
    22  	height := int(c.Height())
    23  
    24  	// Load the given filename
    25  	nImage, err := carveimg.LoadImage(filename)
    26  	if err != nil {
    27  		vt100.Close()
    28  		return fmt.Errorf("could not load %s: %s", filename, err)
    29  	}
    30  
    31  	imageHeight := nImage.Bounds().Max.Y - nImage.Bounds().Min.Y
    32  	imageWidth := nImage.Bounds().Max.X - nImage.Bounds().Min.X
    33  	if imageWidth == 0 {
    34  		return errors.New("the width of the given image is 0")
    35  	}
    36  
    37  	ratio := (float64(imageHeight) / float64(imageWidth)) * 4.0 // terminal "pixels" are a bit narrow, so multiply by 4.0
    38  	if ratio == 0 {
    39  		return errors.New("the ratio of the given image is 0")
    40  	}
    41  
    42  	// Use a smaller width, if that makes the image more like the original proportions
    43  	proportionalWidth := int(float64(height) * ratio)
    44  	if proportionalWidth < width {
    45  		width = proportionalWidth
    46  	}
    47  
    48  	// Set the desired size to the size of the current terminal emulator
    49  	resizedImage := image.NewRGBA(image.Rect(0, 0, width, height))
    50  
    51  	// Resize the image
    52  	imageResizeFunction.Scale(resizedImage, resizedImage.Rect, nImage, nImage.Bounds(), draw.Over, nil)
    53  
    54  	// Draw the image to the canvas, using only the basic 16 colors
    55  	if err := carveimg.Draw(c, resizedImage); err != nil {
    56  		vt100.Close()
    57  		return fmt.Errorf("could not draw image: %s", err)
    58  	}
    59  
    60  	// Output the filename on top of the image
    61  	title := " " + filepath.Base(filename) + " "
    62  	c.Write(uint((width-len(title))/2), uint(height-1), vt100.Black, vt100.BackgroundGray, title)
    63  
    64  	// Draw the contents of the canvas to the screen
    65  	c.Draw()
    66  
    67  	// Hide the cursor
    68  	vt100.ShowCursor(false)
    69  	defer vt100.ShowCursor(true)
    70  
    71  	if waitForKeypress {
    72  		// Wait for a keypress
    73  		vt100.WaitForKey()
    74  	}
    75  
    76  	return nil
    77  }