Skip to content

Commit

Permalink
fix: drawImage with exif orientation (#814)
Browse files Browse the repository at this point in the history
  • Loading branch information
Brooooooklyn authored Apr 17, 2024
1 parent 11ab7e2 commit a54cd33
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 8 deletions.
Binary file added __test__/fixtures/with-exif.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 18 additions & 0 deletions __test__/image.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,24 @@ test('alt state should be ok', (t) => {
t.is(image.alt, 'hello')
})

test('with-exif image width and height should be correct', async (t) => {
const file = await fs.readFile(join(__dirname, 'fixtures', 'with-exif.jpg'))
const image = new Image()
image.src = file
t.is(image.width, 450)
t.is(image.height, 600)
})

test('draw-image-exif', async (t) => {
const file = await fs.readFile(join(__dirname, 'fixtures', 'with-exif.jpg'))
const image = new Image()
image.src = file
const canvas = createCanvas(800, 800)
const ctx = canvas.getContext('2d')
ctx.drawImage(image, 0, 0)
await snapshotImage(t, { canvas })
})

test('properties should be readonly', (t) => {
const image = new Image()
const expectation = {
Expand Down
Binary file added __test__/snapshots/draw-image-exif.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 3 additions & 4 deletions load-image.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ const { Readable } = require('stream')

let http, https

const MAX_REDIRECTS = 20,
REDIRECT_STATUSES = new Set([301, 302]),
DATA_URI = /^\s*data:/
const MAX_REDIRECTS = 20
const REDIRECT_STATUSES = new Set([301, 302])

/**
* Loads the given source into canvas Image
Expand All @@ -23,7 +22,7 @@ module.exports = async function loadImage(source, options = {}) {
// if the source is Image instance, copy the image src to new image
if (source instanceof Image) return createImage(source.src, options.alt)
// if source is string and in data uri format, construct image using data uri
if (typeof source === 'string' && DATA_URI.test(source)) {
if (typeof source === 'string' && source.trimStart().startsWith('data:')) {
const commaIdx = source.indexOf(',')
const encoding = source.lastIndexOf('base64', commaIdx) < 0 ? 'utf-8' : 'base64'
const data = Buffer.from(source.slice(commaIdx + 1), encoding)
Expand Down
37 changes: 33 additions & 4 deletions skia-c/skia_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1482,13 +1482,42 @@ extern "C"
auto data = SkData::MakeWithoutCopy(reinterpret_cast<const void *>(ptr), size);
auto codec = SkCodec::MakeFromData(data);
auto info = codec->getInfo();
auto row_bytes = info.width() * info.bytesPerPixel();
auto row_bytes = info.minRowBytes();
auto bitmap = new SkBitmap();
bitmap->allocPixels(info);
codec->getPixels(info, bitmap->getPixels(), row_bytes);
bitmap_info->bitmap = reinterpret_cast<skiac_bitmap *>(bitmap);
bitmap_info->width = info.width();
bitmap_info->height = info.height();
auto dimension = codec->dimensions();
auto origin = codec->getOrigin();
auto width = dimension.width();
auto height = dimension.height();
// https://github.com/chromium/chromium/blob/126.0.6423.1/third_party/blink/renderer/platform/graphics/image.cc#L124
// need to create a new bitmap with the correct orientation
if (origin != SkEncodedOrigin::kTopLeft_SkEncodedOrigin) {
if (
origin == SkEncodedOrigin::kLeftTop_SkEncodedOrigin ||
origin == SkEncodedOrigin::kRightTop_SkEncodedOrigin ||
origin == SkEncodedOrigin::kRightBottom_SkEncodedOrigin ||
origin == SkEncodedOrigin::kLeftBottom_SkEncodedOrigin
)
{
width = height;
height = dimension.width();
}
auto oriented_bitmap = new SkBitmap();
auto oriented_bitmap_info = SkImageInfo::Make(width, height, info.colorType(), info.alphaType());
oriented_bitmap->allocPixels(oriented_bitmap_info);
auto canvas = new SkCanvas(*oriented_bitmap);
auto matrix = SkEncodedOriginToMatrix(origin, width, height);
canvas->setMatrix(matrix);
auto image = SkImages::RasterFromBitmap(*bitmap);
canvas->drawImage(image, 0, 0);
bitmap_info->bitmap = reinterpret_cast<skiac_bitmap *>(oriented_bitmap);
delete bitmap;
} else {
bitmap_info->bitmap = reinterpret_cast<skiac_bitmap *>(bitmap);
}
bitmap_info->width = width;
bitmap_info->height = height;
}

void skiac_bitmap_make_from_svg(const uint8_t *data, size_t length, float width, float height, skiac_bitmap_info *bitmap_info, skiac_font_collection *c_collection, uint8_t cs)
Expand Down

0 comments on commit a54cd33

Please sign in to comment.