Skip to content

Commit

Permalink
✨ Feature(custom): optimize windows clipboard script
Browse files Browse the repository at this point in the history
  • Loading branch information
Kuingsmile committed Aug 12, 2024
1 parent f579667 commit 52b4612
Show file tree
Hide file tree
Showing 4 changed files with 192 additions and 185 deletions.
226 changes: 118 additions & 108 deletions src/core/Lifecycle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,117 +93,11 @@ export class Lifecycle extends EventEmitter {
ctx.rawInputPath = [] as string[]
ctx.rawInput = cloneDeep(input)
ctx.output = [] as IImgInfo[]
const { compressOptions, watermarkOptions } = this.helpGetOption(ctx)
ctx.emit(IBuildInEvent.UPLOAD_PROGRESS, 0)
ctx.emit(IBuildInEvent.BEFORE_TRANSFORM, ctx)
ctx.log.info('Before transform')
if (compressOptions || watermarkOptions) {
const tempFilePath = path.join(ctx.baseDir, 'piclistTemp')

await Promise.allSettled(
ctx.input.map(async (item: string, index: number) => {
const itemIsUrl = isUrl(item)
const info: IPathTransformedImgInfo = itemIsUrl ? await getURLFile(item, ctx) : { success: false }
if (itemIsUrl && (!info.success || !info.buffer)) return

let transformedBuffer: Undefinable<Buffer>
let isSkip = false
ctx.rawInputPath![index] = item
const extention = itemIsUrl ? info.extname || '' : path.extname(item)
const fileBuffer: Buffer = itemIsUrl ? info.buffer! : fs.readFileSync(item)
if (isNeedAddWatermark(watermarkOptions, extention)) {
if (!(watermarkOptions?.watermarkFontPath || watermarkOptions?.watermarkType === 'image')) {
const downloadTTFRet = await this.downloadTTF()
if (!downloadTTFRet) {
this.ctx.log.warn('Download ttf file failed, skip add watermark.')
isSkip = true
}
}
if (!isSkip) {
ctx.log.info(watermarkMsg)
transformedBuffer = await imageAddWaterMark(fileBuffer, watermarkOptions!, this.ttfPath, ctx.log)
}
}
if (isNeedCompress(compressOptions, extention)) {
ctx.log.info(compressMsg)
if (!itemIsUrl && (extention === '.heic' || extention === '.heif')) {
const heicResult = await heicConvert({
buffer: fileBuffer,
format: 'JPEG',
quality: 1
})
const tempHeicConvertFile = path.join(tempFilePath, `${path.basename(item, extention)}.jpg`)
fs.writeFileSync(tempHeicConvertFile, Buffer.from(heicResult))
transformedBuffer = await imageCompress(
fs.readFileSync(tempHeicConvertFile),
compressOptions!,
'.jpg',
ctx.log
)
} else {
transformedBuffer = await imageCompress(
transformedBuffer ?? fileBuffer,
compressOptions!,
extention,
ctx.log
)
}
}
if (!transformedBuffer && compressOptions?.isRemoveExif) {
ctx.log.info('Remove exif info.')
transformedBuffer = await removeExif(fileBuffer, extention)
}
if (transformedBuffer) {
let newExt = compressOptions?.isConvert ? getConvertedFormat(compressOptions, extention) : extention
newExt = newExt.startsWith('.') ? newExt : `.${newExt}`
const tempFile = itemIsUrl
? path.join(
tempFilePath,
`${
info.fileName
? `${path.basename(info.fileName, path.extname(info.fileName))}`
: new Date().getTime()
}${newExt}`
)
: path.join(tempFilePath, `${path.basename(item, extention)}${newExt}`)
ctx.rawInputPath![index] = path.join(
path.dirname(item),
itemIsUrl ? path.basename(tempFile) : `${path.basename(item, extention)}${newExt}`
)
fs.writeFileSync(tempFile, transformedBuffer)
ctx.input[index] = tempFile
}
})
)
} else {
for (const item of ctx.input) {
ctx.rawInputPath.push(item)
}
}
// lifecycle main
await this.preprocess(ctx)
await this.beforeTransform(ctx)
await this.doTransform(ctx)
const renameConfig = ctx.getConfig<any>('buildIn.rename') || {}
if (renameConfig.enable) {
const format = renameConfig.format || '{filename}'
ctx.output = ctx.output.map((item: IImgInfo, index: number) => {
let fileName = item.fileName
if (format) {
fileName = renameFileNameWithCustomString(
ctx.rawInputPath![index],
format,
undefined,
item.base64Image ? item.base64Image : item.buffer
)
fileName = fileName.replace(/\/+/g, '/')
if (fileName.slice(-1) === '/') {
fileName = fileName + index.toString()
}
}
item.fileName = fileName
return item
})
}
await this.buildInRename(ctx)
await this.beforeUpload(ctx)
await this.doUpload(ctx)
ctx.input = ctx.rawInput
Expand All @@ -221,6 +115,122 @@ export class Lifecycle extends EventEmitter {
}
}

private async preprocess(ctx: IPicGo): Promise<IPicGo> {
const { compressOptions, watermarkOptions } = this.helpGetOption(ctx)
ctx.emit(IBuildInEvent.UPLOAD_PROGRESS, 0)
ctx.emit(IBuildInEvent.BEFORE_TRANSFORM, ctx)
ctx.log.info('Before transform')
if (compressOptions || watermarkOptions) {
const tempFilePath = path.join(ctx.baseDir, 'piclistTemp')

await Promise.allSettled(
ctx.input.map(async (item: string, index: number) => {
const itemIsUrl = isUrl(item)
const info: IPathTransformedImgInfo = itemIsUrl ? await getURLFile(item, ctx) : { success: false }
if (itemIsUrl && (!info.success || !info.buffer)) return

let transformedBuffer: Undefinable<Buffer>
let isSkip = false
ctx.rawInputPath![index] = item
const extention = itemIsUrl ? info.extname || '' : path.extname(item)
const fileBuffer: Buffer = itemIsUrl ? info.buffer! : fs.readFileSync(item)
if (isNeedAddWatermark(watermarkOptions, extention)) {
if (!(watermarkOptions?.watermarkFontPath || watermarkOptions?.watermarkType === 'image')) {
const downloadTTFRet = await this.downloadTTF()
if (!downloadTTFRet) {
this.ctx.log.warn('Download ttf file failed, skip add watermark.')
isSkip = true
}
}
if (!isSkip) {
ctx.log.info(watermarkMsg)
transformedBuffer = await imageAddWaterMark(fileBuffer, watermarkOptions!, this.ttfPath, ctx.log)
}
}
if (isNeedCompress(compressOptions, extention)) {
ctx.log.info(compressMsg)
if (!itemIsUrl && (extention === '.heic' || extention === '.heif')) {
const heicResult = await heicConvert({
buffer: fileBuffer,
format: 'JPEG',
quality: 1
})
const tempHeicConvertFile = path.join(tempFilePath, `${path.basename(item, extention)}.jpg`)
fs.writeFileSync(tempHeicConvertFile, Buffer.from(heicResult))
transformedBuffer = await imageCompress(
fs.readFileSync(tempHeicConvertFile),
compressOptions!,
'.jpg',
ctx.log
)
} else {
transformedBuffer = await imageCompress(
transformedBuffer ?? fileBuffer,
compressOptions!,
extention,
ctx.log
)
}
}
if (!transformedBuffer && compressOptions?.isRemoveExif) {
ctx.log.info('Remove exif info.')
transformedBuffer = await removeExif(fileBuffer, extention)
}
if (transformedBuffer) {
let newExt = compressOptions?.isConvert ? getConvertedFormat(compressOptions, extention) : extention
newExt = newExt.startsWith('.') ? newExt : `.${newExt}`
const tempFile = itemIsUrl
? path.join(
tempFilePath,
`${
info.fileName
? `${path.basename(info.fileName, path.extname(info.fileName))}`
: new Date().getTime()
}${newExt}`
)
: path.join(tempFilePath, `${path.basename(item, extention)}${newExt}`)
ctx.rawInputPath![index] = path.join(
path.dirname(item),
itemIsUrl ? path.basename(tempFile) : `${path.basename(item, extention)}${newExt}`
)
fs.writeFileSync(tempFile, transformedBuffer)
ctx.input[index] = tempFile
}
})
)
} else {
for (const item of ctx.input) {
ctx.rawInputPath!.push(item)
}
}
return ctx
}

private async buildInRename(ctx: IPicGo): Promise<IPicGo> {
const renameConfig = ctx.getConfig<any>('buildIn.rename') || {}
if (renameConfig.enable) {
const format = renameConfig.format || '{filename}'
ctx.output = ctx.output.map((item: IImgInfo, index: number) => {
let fileName = item.fileName
if (format) {
fileName = renameFileNameWithCustomString(
ctx.rawInputPath![index],
format,
undefined,
item.base64Image ? item.base64Image : item.buffer
)
fileName = fileName.replace(/\/+/g, '/')
if (fileName.slice(-1) === '/') {
fileName = fileName + index.toString()
}
}
item.fileName = fileName
return item
})
}
return ctx
}

private async beforeTransform(ctx: IPicGo): Promise<IPicGo> {
await this.handlePlugins(ctx.helper.beforeTransformPlugins, ctx)
return ctx
Expand Down
7 changes: 2 additions & 5 deletions src/core/PicGo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,8 @@ export class PicGo extends EventEmitter implements IPicGo {
if (name) {
this.pluginLoader.registerPlugin(name, plugin)
return this.pluginLoader.getPlugin(name)!
} else {
const pluginInstance = plugin(this)
return pluginInstance
}
return plugin(this)
}

registerCommands(): void {
Expand All @@ -151,9 +149,8 @@ export class PicGo extends EventEmitter implements IPicGo {
if (!name) {
this._config = this.db.read(true) as IConfig
return this._config as unknown as T
} else {
return get(this._config, name)
}
return get(this._config, name)
}

saveConfig(config: IStringKeyMap<any>): void {
Expand Down
52 changes: 26 additions & 26 deletions src/utils/clipboard/windows.ps1
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@

param($imagePath)

# Adapted from https://github.com/octan3/img-clipboard-dump/blob/master/dump-clipboard-png.ps1

Add-Type -Assembly PresentationCore
$img = [Windows.Clipboard]::GetImage()

if ($img -eq $null) {
"no image"
Exit 1
}

if (-not $imagePath) {
"no image"
Exit 1
}

$fcb = new-object Windows.Media.Imaging.FormatConvertedBitmap($img, [Windows.Media.PixelFormats]::Rgb24, $null, 0)
$stream = [IO.File]::Open($imagePath, "OpenOrCreate")
$encoder = New-Object Windows.Media.Imaging.PngBitmapEncoder
$encoder.Frames.Add([Windows.Media.Imaging.BitmapFrame]::Create($fcb)) | out-null
$encoder.Save($stream) | out-null
$stream.Dispose() | out-null

$imagePath

param($imagePath)

# Adapted from https://github.com/octan3/img-clipboard-dump/blob/master/dump-clipboard-png.ps1

Add-Type -Assembly PresentationCore
$img = [Windows.Clipboard]::GetImage()

if ($null -eq $img) {
"no image"
Exit 1
}

if (-not $imagePath) {
"no image"
Exit 1
}

$fcb = new-object Windows.Media.Imaging.FormatConvertedBitmap($img, [Windows.Media.PixelFormats]::Rgb24, $null, 0)
$stream = [IO.File]::Open($imagePath, "OpenOrCreate")
$encoder = New-Object Windows.Media.Imaging.PngBitmapEncoder
$encoder.Frames.Add([Windows.Media.Imaging.BitmapFrame]::Create($fcb)) | out-null
$encoder.Save($stream) | out-null
$stream.Dispose() | out-null

$imagePath
Loading

0 comments on commit 52b4612

Please sign in to comment.