import { image, video } from 'bare-media'
import b4a from 'b4a'
import {
CHAT_MESSAGE_PREVIEW,
CHAT_LINK_PREVIEW,
CHAT_MESSAGE_MAX_FRAMES,
PROFILE_AVATAR,
ROOM_AVATAR
} from '../shared/constants'
export async function createChatImagePreview({ path }) {
const rgba = await image(path).decode()
return _createChatFilePreview(rgba)
}
export async function createChatVideoPreview({ path }) {
const rgba = await video(path).extractFrames({ frameIndex: 1 })
return _createChatFilePreview(rgba)
}
export async function createChatLinkPreview({ path, buffer }) {
const rgba = path ? await image(path).decode() : await image.decode(buffer)
return _createChatMessagePreviewSingle(rgba, CHAT_LINK_PREVIEW)
}
export async function createProfileAvatar({ path, crop }) {
return _createAvatar(path, crop, PROFILE_AVATAR)
}
export async function createRoomAvatar({ path, crop }) {
return _createAvatar(path, crop, ROOM_AVATAR)
}
export async function decodeImage({ httpLink }) {
const rgba = await image(httpLink).decode()
const { width, height, data } = rgba
return {
metadata: {
dimensions: { width, height }
},
data
}
}
async function _createChatFilePreview(rgba) {
const sliced = image.slice(rgba, {
end: CHAT_MESSAGE_MAX_FRAMES
})
const [small, medium, large] = await Promise.all([
_createChatMessagePreviewSingle(sliced, CHAT_MESSAGE_PREVIEW.small),
_createChatMessagePreviewSingle(sliced, CHAT_MESSAGE_PREVIEW.medium),
_createChatMessagePreviewSingle(rgba, CHAT_MESSAGE_PREVIEW.large)
])
return {
metadata: {
dimensions: {
width: rgba.width,
height: rgba.height
}
},
small,
medium,
large
}
}
async function _createChatMessagePreviewSingle(rgba, opts) {
const resized = await image.resize(rgba, opts.resize)
const buffer = await image.encode(resized, opts.encode)
const data = opts.base64 ? { base64: b4a.toString(buffer, 'base64') } : { buffer }
return {
metadata: {
mimetype: opts.encode.mimetype,
dimensions: {
width: resized.width,
height: resized.height
}
},
...data
}
}
async function _createAvatar(path, crop, opts) {
const rgba = await image(path).decode()
const { width, height } = rgba
const short = Math.min(width, height)
const cropArea = crop || {
left: width > height ? Math.floor((width - height) / 2) : 0,
top: height > width ? Math.floor((height - width) / 2) : 0,
width: short,
height: short
}
const cropped = await image.crop(rgba, cropArea)
const [small, medium] = await Promise.all([
_createAvatarSingle(cropped, opts.small),
_createAvatarSingle(cropped, opts.medium)
])
return { small, medium }
}
async function _createAvatarSingle(rgba, opts) {
const resized = await image.resize(rgba, opts.resize)
const buffer = await image.encode(resized, opts.encode)
return {
metadata: {
mimetype: opts.encode.mimetype,
dimensions: {
width: resized.width,
height: resized.height
}
},
base64: b4a.toString(buffer, 'base64')
}
}