package images import ( "bytes" "errors" "fmt" "image" "io" "io/ioutil" "net/http" "os" "strings" ) const ( maxChatMessageImageSize = 400000 resizeTargetImageSize = 350000 idealTargetImageSize = 50000 ) var DefaultBounds = FileSizeLimits{Ideal: idealTargetImageSize, Max: resizeTargetImageSize} func FetchAndStoreRemoteImage(url string) (string, error) { resp, err := http.Get(url) //nolint if err != nil { return "", fmt.Errorf("error fetching image from URL: %w", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { return "", fmt.Errorf("bad status code: %s", resp.Status) } tempFile, err := ioutil.TempFile("", "image-*") if err != nil { return "", fmt.Errorf("error creating a temporary file: %w", err) } defer tempFile.Close() _, err = io.Copy(tempFile, resp.Body) if err != nil { os.Remove(tempFile.Name()) // Ensure temporary file is deleted on error return "", fmt.Errorf("error writing image to temp file: %w", err) } return tempFile.Name(), nil } func OpenAndDecodeImage(imagePath string) (image.Image, error) { file, err := os.Open(imagePath) if err != nil { return nil, fmt.Errorf("error opening image file: %w", err) } defer file.Close() img, err := Decode(imagePath) if err != nil { return nil, fmt.Errorf("error decoding image: %w", err) } return img, nil } func AdjustImage(img image.Image, crop bool, inputImage CroppedImage) ([]byte, error) { if crop { cropRect := image.Rectangle{ Min: image.Point{X: inputImage.X, Y: inputImage.Y}, Max: image.Point{X: inputImage.X + inputImage.Width, Y: inputImage.Y + inputImage.Height}, } var err error img, err = Crop(img, cropRect) if err != nil { return nil, fmt.Errorf("error cropping image: %w", err) } } bb := bytes.NewBuffer([]byte{}) err := CompressToFileLimits(bb, img, DefaultBounds) if err != nil { return nil, fmt.Errorf("error compressing image: %w", err) } payload := bb.Bytes() if len(payload) > maxChatMessageImageSize { return nil, errors.New("image too large") } return payload, nil } func OpenAndAdjustImage(inputImage CroppedImage, crop bool) ([]byte, error) { var imgPath string = inputImage.ImagePath var err error // Check if the image is from a remote source if strings.HasPrefix(inputImage.ImagePath, "http://") || strings.HasPrefix(inputImage.ImagePath, "https://") { imgPath, err = FetchAndStoreRemoteImage(inputImage.ImagePath) if err != nil { return nil, err } defer os.Remove(imgPath) // Clean up the temporary file } // Decode the image img, err := OpenAndDecodeImage(imgPath) if err != nil { return nil, err } // Adjust (crop and compress) the image return AdjustImage(img, crop, inputImage) }