mirror of
https://github.com/hcengineering/platform.git
synced 2025-05-30 04:05:39 +00:00
fix: better handling png image size for scale < 2 (#6688)
Signed-off-by: Alexander Onnikov <Alexander.Onnikov@xored.com>
This commit is contained in:
parent
0763624688
commit
21a5f07870
@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
import { getFileUrl } from '../file'
|
import { getFileUrl } from '../file'
|
||||||
import { getPreviewType, previewTypes } from '../filetypes'
|
import { getPreviewType, previewTypes } from '../filetypes'
|
||||||
|
import { imageSizeToRatio } from '../image'
|
||||||
import { BlobMetadata, FilePreviewExtension } from '../types'
|
import { BlobMetadata, FilePreviewExtension } from '../types'
|
||||||
|
|
||||||
export let file: Ref<Blob>
|
export let file: Ref<Blob>
|
||||||
@ -68,8 +69,8 @@
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
const pR: number = mD?.pixelRatio ?? 1
|
const pR: number = mD?.pixelRatio ?? 1
|
||||||
const fWidth: number = mD.originalWidth / pR
|
const fWidth: number = imageSizeToRatio(mD.originalWidth, pR)
|
||||||
const fHeight: number = mD.originalHeight / pR
|
const fHeight: number = imageSizeToRatio(mD.originalHeight, pR)
|
||||||
let mHeight: number = 0
|
let mHeight: number = 0
|
||||||
let scale: number = 1
|
let scale: number = 1
|
||||||
if (fWidth > pWidth) {
|
if (fWidth > pWidth) {
|
||||||
|
@ -15,6 +15,11 @@
|
|||||||
|
|
||||||
import extract from 'png-chunks-extract'
|
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 }> {
|
export async function getImageSize (file: Blob): Promise<{ width: number, height: number, pixelRatio: number }> {
|
||||||
const size = isPng(file) ? await getPngImageSize(file) : undefined
|
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 idhrData = parseIHDR(new DataView(iHDRChunk.data.buffer))
|
||||||
const physData = parsePhys(new DataView(pHYsChunk.data.buffer))
|
const physData = parsePhys(new DataView(pHYsChunk.data.buffer))
|
||||||
|
|
||||||
if (physData.unit === 0 && physData.ppux === physData.ppuy) {
|
// Assuming pixels are square
|
||||||
const pixelRatio = Math.round(physData.ppux / 2834.5)
|
// http://www.libpng.org/pub/png/spec/1.2/PNG-Decoders.html#D.Pixel-dimensions
|
||||||
return {
|
const pixelRatio = Math.round(physData.ppux * 0.0254) / 72
|
||||||
width: idhrData.width,
|
return {
|
||||||
height: idhrData.height,
|
width: idhrData.width,
|
||||||
pixelRatio
|
height: idhrData.height,
|
||||||
}
|
pixelRatio
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
return undefined
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// See http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html
|
// See http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { type Space, type Class, type CollaborativeDoc, type Doc, type Ref } from '@hcengineering/core'
|
import { type Space, type Class, type CollaborativeDoc, type Doc, type Ref } from '@hcengineering/core'
|
||||||
import { IntlString, translate } from '@hcengineering/platform'
|
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 { markupToJSON } from '@hcengineering/text'
|
||||||
import {
|
import {
|
||||||
AnySvelteComponent,
|
AnySvelteComponent,
|
||||||
@ -297,7 +297,7 @@
|
|||||||
type: 'image',
|
type: 'image',
|
||||||
attrs: {
|
attrs: {
|
||||||
'file-id': attached.file,
|
'file-id': attached.file,
|
||||||
width: Math.round(size.width / size.pixelRatio)
|
width: imageSizeToRatio(size.width, size.pixelRatio)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Markup } from '@hcengineering/core'
|
import { Markup } from '@hcengineering/core'
|
||||||
import { IntlString } from '@hcengineering/platform'
|
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 { EmptyMarkup } from '@hcengineering/text'
|
||||||
import textEditor, { RefAction } from '@hcengineering/text-editor'
|
import textEditor, { RefAction } from '@hcengineering/text-editor'
|
||||||
import {
|
import {
|
||||||
@ -257,7 +257,7 @@
|
|||||||
type: 'image',
|
type: 'image',
|
||||||
attrs: {
|
attrs: {
|
||||||
'file-id': attached.file,
|
'file-id': attached.file,
|
||||||
width: Math.round(size.width / size.pixelRatio)
|
width: imageSizeToRatio(size.width, size.pixelRatio)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -153,12 +153,15 @@ export const ImageExtension = ImageNode.extend<ImageOptions>({
|
|||||||
const fileName = node.attrs.alt ?? ''
|
const fileName = node.attrs.alt ?? ''
|
||||||
const fileType = node.attrs['data-file-type'] ?? 'image/*'
|
const fileType = node.attrs['data-file-type'] ?? 'image/*'
|
||||||
|
|
||||||
|
const metadata = node.attrs.width !== undefined ? { originalWidth: node.attrs.width } : {}
|
||||||
|
|
||||||
showPopup(
|
showPopup(
|
||||||
FilePreviewPopup,
|
FilePreviewPopup,
|
||||||
{
|
{
|
||||||
file: fileId,
|
file: fileId,
|
||||||
name: fileName,
|
name: fileName,
|
||||||
contentType: fileType,
|
contentType: fileType,
|
||||||
|
metadata,
|
||||||
fullSize: true,
|
fullSize: true,
|
||||||
showIcon: false
|
showIcon: false
|
||||||
},
|
},
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
import { setPlatformStatus, unknownError } from '@hcengineering/platform'
|
import { setPlatformStatus, unknownError } from '@hcengineering/platform'
|
||||||
import { getImageSize } from '@hcengineering/presentation'
|
import { imageSizeToRatio, getImageSize } from '@hcengineering/presentation'
|
||||||
import { Extension } from '@tiptap/core'
|
import { Extension } from '@tiptap/core'
|
||||||
import { Plugin, PluginKey } from '@tiptap/pm/state'
|
import { Plugin, PluginKey } from '@tiptap/pm/state'
|
||||||
import { type EditorView } from '@tiptap/pm/view'
|
import { type EditorView } from '@tiptap/pm/view'
|
||||||
@ -41,6 +41,8 @@ function getType (type: string): 'image' | 'other' {
|
|||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
export const ImageUploadExtension = Extension.create<ImageUploadOptions>({
|
export const ImageUploadExtension = Extension.create<ImageUploadOptions>({
|
||||||
|
name: 'image-upload',
|
||||||
|
|
||||||
addOptions () {
|
addOptions () {
|
||||||
return {
|
return {
|
||||||
getFileUrl: () => ''
|
getFileUrl: () => ''
|
||||||
@ -157,7 +159,7 @@ async function handleImageUpload (
|
|||||||
src: url,
|
src: url,
|
||||||
alt: file.name,
|
alt: file.name,
|
||||||
title: 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)
|
const transaction = view.state.tr.insert(pos?.pos ?? 0, node)
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { type Blob, type Ref } from '@hcengineering/core'
|
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'
|
import { Loading } from '@hcengineering/ui'
|
||||||
|
|
||||||
export let value: Ref<Blob>
|
export let value: Ref<Blob>
|
||||||
@ -22,15 +22,20 @@
|
|||||||
export let metadata: BlobMetadata | undefined
|
export let metadata: BlobMetadata | undefined
|
||||||
export let fit: boolean = false
|
export let fit: boolean = false
|
||||||
|
|
||||||
$: p = getBlobRef(value, name)
|
$: originalWidth = metadata?.originalWidth
|
||||||
$: width = metadata?.originalWidth ? `min(${metadata.originalWidth / metadata?.pixelRatio ?? 1}px, 100%)` : '100%'
|
$: originalHeight = metadata?.originalHeight
|
||||||
$: height = metadata?.originalHeight
|
$: pixelRatio = metadata?.pixelRatio ?? 1
|
||||||
? `min(${metadata.originalHeight / metadata?.pixelRatio ?? 1}px, ${fit ? '100%' : '80vh'})`
|
|
||||||
: '100%'
|
$: 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
|
let loading = true
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#await p then blobRef}
|
{#await getBlobRef(value, name) then blobRef}
|
||||||
{#if loading}
|
{#if loading}
|
||||||
<div class="flex-center w-full h-full clear-mins">
|
<div class="flex-center w-full h-full clear-mins">
|
||||||
<Loading />
|
<Loading />
|
||||||
|
Loading…
Reference in New Issue
Block a user