Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support EXIF rotation data #396

Open
andoks opened this issue Feb 5, 2024 · 2 comments
Open

Support EXIF rotation data #396

andoks opened this issue Feb 5, 2024 · 2 comments

Comments

@andoks
Copy link

andoks commented Feb 5, 2024

Is your feature request related to a problem? Please describe.

When i embed images using image.NewFromBytes(image, type, props), they are sometimes displayed in the wrong orientation.

Describe the solution you'd like

Assuming the reason is that the embedding does not take exif orientation information into account, and that is the reason this happens; I would like maroto to be able to take exif orientation information into account from the image data.

Describe alternatives you've considered

  • Rotating the images by hand per image (manual labour, do not want to do this)
  • Rotating the images myself in the code (something like this describes)

Additional context

@johnfercher
Copy link
Owner

Maroto uses gofpdf under the hood, idk if gofpdf supports this.

@andoks
Copy link
Author

andoks commented Feb 23, 2024

I solved it by using goexif like so, borrowed from stack overflow somewhere I think:

func readJPEG(rs io.ReadSeeker) (JPEG, error) {
	img, err := jpeg.Decode(rs)
	if err != nil {
		return nil, fmt.Errorf("faile to decode image as JPEG, error was: %w", err)
	}
	_, err = rs.Seek(0, io.SeekStart)

	// deal with exif
	x, err := exif.Decode(rs)
	if err != nil && x != nil {
		return nil, fmt.Errorf("failed reading exif information from image, error was: %w", err)
	}
	if x != nil {
		orient, _ := x.Get(exif.Orientation)
		if orient != nil {
			img = reverseOrientation(img, orient.String())
		} else {
			img = reverseOrientation(img, "1")
		}
	}

	var buf bytes.Buffer
	err = jpeg.Encode(&buf, img, nil)
	if err != nil {
		return nil, fmt.Errorf("failed encode image after exif-orientation adjusting it, error was: %w", err)
	}

	return buf.Bytes(), nil
}

func reverseOrientation(img image.Image, o string) *image.NRGBA {
	switch o {
	case "1":
		return imaging.Clone(img)
	case "2":
		return imaging.FlipV(img)
	case "3":
		return imaging.Rotate180(img)
	case "4":
		return imaging.Rotate180(imaging.FlipV(img))
	case "5":
		return imaging.Rotate270(imaging.FlipV(img))
	case "6":
		return imaging.Rotate270(img)
	case "7":
		return imaging.Rotate90(imaging.FlipV(img))
	case "8":
		return imaging.Rotate90(img)
	}
	slog.Error("unknown orientation, expect 1-8", slog.String("orientation", o))
	return imaging.Clone(img)
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants