fix: better handling png image size for scale < 2 (#6688)

Signed-off-by: Alexander Onnikov <Alexander.Onnikov@xored.com>
This commit is contained in:
Alexander Onnikov 2024-09-23 18:24:40 +07:00 committed by GitHub
parent 0763624688
commit 21a5f07870
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 38 additions and 24 deletions

View File

@ -27,6 +27,7 @@
import { getFileUrl } from '../file'
import { getPreviewType, previewTypes } from '../filetypes'
import { imageSizeToRatio } from '../image'
import { BlobMetadata, FilePreviewExtension } from '../types'
export let file: Ref<Blob>
@ -68,8 +69,8 @@
return
}
const pR: number = mD?.pixelRatio ?? 1
const fWidth: number = mD.originalWidth / pR
const fHeight: number = mD.originalHeight / pR
const fWidth: number = imageSizeToRatio(mD.originalWidth, pR)
const fHeight: number = imageSizeToRatio(mD.originalHeight, pR)
let mHeight: number = 0
let scale: number = 1
if (fWidth > pWidth) {

View File

@ -15,6 +15,11 @@
import extract from 'png-chunks-extract'
export function imageSizeToRatio (width: number, pixelRatio: number): number {
// consider pixel ratio < 2 as non retina and display them in original size
return pixelRatio < 2 ? width : Math.round(width / pixelRatio)
}
export async function getImageSize (file: Blob): Promise<{ width: number, height: number, pixelRatio: number }> {
const size = isPng(file) ? await getPngImageSize(file) : undefined
@ -65,20 +70,18 @@ async function getPngImageSize (file: Blob): Promise<{ width: number, height: nu
const idhrData = parseIHDR(new DataView(iHDRChunk.data.buffer))
const physData = parsePhys(new DataView(pHYsChunk.data.buffer))
if (physData.unit === 0 && physData.ppux === physData.ppuy) {
const pixelRatio = Math.round(physData.ppux / 2834.5)
return {
width: idhrData.width,
height: idhrData.height,
pixelRatio
}
// Assuming pixels are square
// http://www.libpng.org/pub/png/spec/1.2/PNG-Decoders.html#D.Pixel-dimensions
const pixelRatio = Math.round(physData.ppux * 0.0254) / 72
return {
width: idhrData.width,
height: idhrData.height,
pixelRatio
}
} catch (err) {
console.error(err)
return undefined
}
return undefined
}
// See http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html

View File

@ -17,7 +17,7 @@
<script lang="ts">
import { type Space, type Class, type CollaborativeDoc, type Doc, type Ref } from '@hcengineering/core'
import { IntlString, translate } from '@hcengineering/platform'
import { getFileUrl, getImageSize } from '@hcengineering/presentation'
import { getFileUrl, getImageSize, imageSizeToRatio } from '@hcengineering/presentation'
import { markupToJSON } from '@hcengineering/text'
import {
AnySvelteComponent,
@ -297,7 +297,7 @@
type: 'image',
attrs: {
'file-id': attached.file,
width: Math.round(size.width / size.pixelRatio)
width: imageSizeToRatio(size.width, size.pixelRatio)
}
},
{

View File

@ -1,7 +1,7 @@
<script lang="ts">
import { Markup } from '@hcengineering/core'
import { IntlString } from '@hcengineering/platform'
import presentation, { MessageViewer, getFileUrl, getImageSize } from '@hcengineering/presentation'
import presentation, { MessageViewer, getFileUrl, getImageSize, imageSizeToRatio } from '@hcengineering/presentation'
import { EmptyMarkup } from '@hcengineering/text'
import textEditor, { RefAction } from '@hcengineering/text-editor'
import {
@ -257,7 +257,7 @@
type: 'image',
attrs: {
'file-id': attached.file,
width: Math.round(size.width / size.pixelRatio)
width: imageSizeToRatio(size.width, size.pixelRatio)
}
},
{

View File

@ -153,12 +153,15 @@ export const ImageExtension = ImageNode.extend<ImageOptions>({
const fileName = node.attrs.alt ?? ''
const fileType = node.attrs['data-file-type'] ?? 'image/*'
const metadata = node.attrs.width !== undefined ? { originalWidth: node.attrs.width } : {}
showPopup(
FilePreviewPopup,
{
file: fileId,
name: fileName,
contentType: fileType,
metadata,
fullSize: true,
showIcon: false
},

View File

@ -13,7 +13,7 @@
// limitations under the License.
//
import { setPlatformStatus, unknownError } from '@hcengineering/platform'
import { getImageSize } from '@hcengineering/presentation'
import { imageSizeToRatio, getImageSize } from '@hcengineering/presentation'
import { Extension } from '@tiptap/core'
import { Plugin, PluginKey } from '@tiptap/pm/state'
import { type EditorView } from '@tiptap/pm/view'
@ -41,6 +41,8 @@ function getType (type: string): 'image' | 'other' {
* @public
*/
export const ImageUploadExtension = Extension.create<ImageUploadOptions>({
name: 'image-upload',
addOptions () {
return {
getFileUrl: () => ''
@ -157,7 +159,7 @@ async function handleImageUpload (
src: url,
alt: file.name,
title: file.name,
width: Math.round(size.width / size.pixelRatio)
width: imageSizeToRatio(size.width, size.pixelRatio)
})
const transaction = view.state.tr.insert(pos?.pos ?? 0, node)

View File

@ -14,7 +14,7 @@
-->
<script lang="ts">
import { type Blob, type Ref } from '@hcengineering/core'
import { getBlobRef, type BlobMetadata } from '@hcengineering/presentation'
import { getBlobRef, imageSizeToRatio, type BlobMetadata } from '@hcengineering/presentation'
import { Loading } from '@hcengineering/ui'
export let value: Ref<Blob>
@ -22,15 +22,20 @@
export let metadata: BlobMetadata | undefined
export let fit: boolean = false
$: p = getBlobRef(value, name)
$: width = metadata?.originalWidth ? `min(${metadata.originalWidth / metadata?.pixelRatio ?? 1}px, 100%)` : '100%'
$: height = metadata?.originalHeight
? `min(${metadata.originalHeight / metadata?.pixelRatio ?? 1}px, ${fit ? '100%' : '80vh'})`
: '100%'
$: originalWidth = metadata?.originalWidth
$: originalHeight = metadata?.originalHeight
$: pixelRatio = metadata?.pixelRatio ?? 1
$: imageWidth = originalWidth != null ? imageSizeToRatio(originalWidth, pixelRatio) : undefined
$: imageHeight = originalHeight != null ? imageSizeToRatio(originalHeight, pixelRatio) : undefined
$: width = imageWidth != null ? `min(${imageWidth}px, 100%)` : '100%'
$: height = imageHeight != null ? `min(${imageHeight}px, ${fit ? '100%' : '80vh'})` : '100%'
let loading = true
</script>
{#await p then blobRef}
{#await getBlobRef(value, name) then blobRef}
{#if loading}
<div class="flex-center w-full h-full clear-mins">
<Loading />