You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: mediafile_thumbs.go
    path of file: ./repos/photoprism/internal/photoprism
    
    the code of the file until where you have to start completion: package photoprism

import (
	"bytes"
	"errors"
	"fmt"
	"image"
	"os/exec"
	"strconv"
	"strings"
	"time"

	"github.com/disintegration/imaging"
	"github.com/dustin/go-humanize/english"

	"github.com/photoprism/photoprism/internal/thumb"
	"github.com/photoprism/photoprism/pkg/capture"
	"github.com/photoprism/photoprism/pkg/clean"
	"github.com/photoprism/photoprism/pkg/fs"
)

// Bounds returns the media dimensions as image.Rectangle.
func (m *MediaFile) Bounds() image.Rectangle {
	return image.Rectangle{Min: image.Point{}, Max: image.Point{X: m.Width(), Y: m.Height(
    
func (m *MediaFile) CreateThumbnails(thumbPath string, force bool) (err error) {
	if !m.IsPreviewImage() {
		// Skip.
		return
	}

	count := 0
	start := time.Now()

	defer func() {
		switch count {
		case 0:
			log.Debug(capture.Time(start, fmt.Sprintf("media: created no new thumbnails for %s", clean.Log(m.RootRelName()))))
		default:
			log.Info(capture.Time(start, fmt.Sprintf("media: created %s for %s", english.Plural(count, "thumbnail", "thumbnails"), clean.Log(m.RootRelName()))))
		}
	}()

	hash := m.Hash()

	var original image.Image

	var srcImg image.Image
	var srcName thumb.Name

	for _, name := range thumb.Names {
		var size thumb.Size
		var fileName string

		if size = thumb.Sizes[name]; size.Uncached() {
			// Skip, exceeds pre-cached size limit.
			continue
		} else if fileName, err = size.FileName(hash, thumbPath); err != nil {
			log.Errorf("media: failed creating %s (%s)", clean.Log(string(name)), err)
			return err
		} else if force || !fs.FileExists(fileName) {
			// Open original if needed.
			if original == nil {
				img, imgErr := thumb.Open(m.FileName(), m.Orientation())

				// Failed to open the JPEG file?
				if imgErr != nil {
					msg := imgErr.Error()

					// Non-repairable file error?
					if !(strings.Contains(msg, "EOF") ||
						strings.HasPrefix(msg, "invalid JPEG")) {
						log.Debugf("media: %s in %s", msg, clean.Log(m.RootRelName()))
						return imgErr
					}

					// Try to repair the file by creating a properly encoded copy with ImageMagick.
					if fixed, fixErr := NewConvert(conf).FixJpeg(m, false); fixErr != nil {
						return fixErr
					} else if fixedImg, openErr := thumb.Open(fixed.FileName(), m.Orientation()); openErr != nil {
						return openErr
					} else {
						img = fixedImg
					}
				}

				original = img

				log.Debugf("media: opened %s [%s]", clean.Log(m.RootRelName()), thumb.MemSize(original).String())
			}

			// Thumb size too large
			// for the original image?
			if size.Skip(original) {
				continue
			}

			// Reuse existing thumb to improve performance
			// and reduce server load?
			if size.Source != "" {
				if size.Source == srcName && srcImg != nil {
					_, err = size.Create(srcImg, fileName)
				} else {
					_, err = size.Create(original, fileName)
				}
			} else {
				srcImg, err = size.Create(original, fileName)
				srcName = name
			}

			// Failed?
			if err != nil {
				log.Errorf("media: failed creating %s (%s)", name.String(), err)
				return err
			}

			count++
		}
	}

	return nil
}