Skip to content

Commit bb96cef

Browse files
authored
New: Copy image to clipboard
1 parent f309c27 commit bb96cef

7 files changed

Lines changed: 131 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
1616
- Support for `HEIC` image format [`4f4b5a1`](https://github.com/ollm/OpenComic/commit/4f4b5a16572ea2bd5aff2e519d473b42d80312fb)
1717
- Option to apply configuration profile based on folder/file label [`71d9ff5`](https://github.com/ollm/OpenComic/commit/71d9ff5655f934e4d710e1833b081e4fddf8d428)
1818
- Option to disable `Align with next horizontal` when reading on double page [`97d8ecd`](https://github.com/ollm/OpenComic/commit/97d8ecdde04c2a5c418440d8fbbf06496b16c8ba)
19-
- Option in setting to adjust gamepad sensitivity
19+
- Option in setting to adjust gamepad sensitivity [`f309c27`](https://github.com/ollm/OpenComic/commit/f309c27195ccf91b0d20600c06f1af03deee5611)
20+
- Copy image to clipboard
2021

2122
##### 🐛 Bug Fixes
2223

languages/ca.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@
5656
"saveBookmarksImages": "Guardar les imatges marcades actuals",
5757
"saveAllBookmarksImages": "Guardar totes les imatges marcades",
5858
"saveImagesMessage": "S'han guardat correctament les imatges",
59+
"copyImage": "Copia la imatge al porta-retalls",
60+
"copyImageMessage": "S'ha copiat la imatge al porta-retalls",
5961
"clearFileCache": "Netejar la memòria cau de l'arxiu",
6062
"clearFileCacheSuccessfully": "S'ha netejat correctament la memòria cau de l'arxiu",
6163
"closeApp": "Tancar OpenComic"

languages/en.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@
5656
"saveBookmarksImages": "Save current bookmarked images",
5757
"saveAllBookmarksImages": "Save all bookmarked images",
5858
"saveImagesMessage": "Images have been saved successfully",
59+
"copyImage": "Copy image to clipboard",
60+
"copyImageMessage": "Image has been copied to clipboard",
5961
"clearFileCache": "Clear file cache",
6062
"clearFileCacheSuccessfully": "File cache has been successfully cleared",
6163
"closeApp": "Close OpenComic"

languages/es.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@
5656
"saveBookmarksImages": "Guardar las imágenes marcadas actuales",
5757
"saveAllBookmarksImages": "Guardar todas las imágenes marcadas",
5858
"saveImagesMessage": "Se han guardado correctamente las imágenes",
59+
"copyImage": "Copiar imagen al portapapeles",
60+
"copyImageMessage": "Se ha copiado la imagen al portapapeles",
5961
"clearFileCache": "Limpiar caché del archivo",
6062
"clearFileCacheSuccessfully": "Se ha limpiado correctamente la caché del archivo",
6163
"closeApp": "Cerrar OpenComic"

scripts/reading/context-menu.js

Lines changed: 107 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ function saveImage()
122122
saveAllImages(position);
123123
}
124124

125-
function saveAllImages(position = false)
125+
function saveAllImages(position = false, _return = false)
126126
{
127127
const images = reading.images();
128128
const imagesData = reading.imagesData();
@@ -141,6 +141,9 @@ function saveAllImages(position = false)
141141
highestPage = +key;
142142
}
143143

144+
if(_return)
145+
return toSave;
146+
144147
saveImages(toSave, String(highestPage).length);
145148
}
146149

@@ -261,6 +264,108 @@ function saveDialogDirectory(callback)
261264
});
262265
}
263266

267+
async function copyImageToClipboard()
268+
{
269+
const position = reading.currentImagePosition();
270+
const images = saveAllImages(position, true);
271+
const len = images.length;
272+
273+
if(!len)
274+
return;
275+
276+
for(let i = 0; i < len; i++)
277+
{
278+
images[i].image = fileManager.realPath(images[i].path);
279+
}
280+
281+
const sizes = await image.getSizes(images);
282+
let maxHeight = 0;
283+
284+
for(let i = 0; i < len; i++)
285+
{
286+
const size = sizes[i];
287+
288+
if(size.height > maxHeight)
289+
maxHeight = size.height;
290+
}
291+
292+
// Generate new sizes
293+
const resizes = [];
294+
let sumWidth = 0;
295+
296+
for(let i = 0; i < len; i++)
297+
{
298+
const size = sizes[i];
299+
const factor = maxHeight / size.height;
300+
const width = Math.round(size.width * factor);
301+
302+
resizes.push({
303+
width: width,
304+
height: Math.round(size.height * factor),
305+
});
306+
307+
sumWidth += width;
308+
}
309+
310+
// Resize images to blob and put them on canvas
311+
const canvas = document.createElement('canvas');
312+
canvas.width = sumWidth;
313+
canvas.height = maxHeight;
314+
const ctx = canvas.getContext('2d');
315+
316+
let left = 0;
317+
318+
for(let i = 0; i < len; i++)
319+
{
320+
let src = images[i].image;
321+
322+
const size = resizes[i];
323+
const options = {
324+
width: size.width,
325+
height: size.height,
326+
kernel: 'lanczos3',
327+
compressionLevel: 0,
328+
};
329+
330+
if(imageExtensions.blob.includes(app.extname(src))) // Convert unsupported images to blob
331+
{
332+
src = await workers.convertImageToBlob(src, {priorize: true});
333+
options.blob = true;
334+
}
335+
336+
let data = await image.resizeToBlob(src, options);
337+
338+
// Draw image
339+
const img = new Image();
340+
img.src = data.blob;
341+
await img.decode();
342+
ctx.drawImage(img, left, 0);
343+
344+
left += size.width;
345+
346+
URL.revokeObjectURL(data.blob);
347+
}
348+
349+
const nativeImage = electron.nativeImage.createFromDataURL(canvas.toDataURL(), {
350+
width: sumWidth,
351+
height: maxHeight,
352+
});
353+
354+
electron.clipboard.writeImage(nativeImage, 'clipboard');
355+
356+
events.snackbar({
357+
key: 'copyImageToClipboard',
358+
text: language.global.contextMenu.copyImageMessage,
359+
duration: 6,
360+
buttons: [
361+
{
362+
text: language.buttons.dismiss,
363+
function: 'events.closeSnackbar();',
364+
},
365+
],
366+
});
367+
}
368+
264369
module.exports = {
265370
show: show,
266371
openFileLocation: openFileLocation,
@@ -271,4 +376,5 @@ module.exports = {
271376
saveAllImages: saveAllImages,
272377
saveBookmarksImages: saveBookmarksImages,
273378
saveAllBookmarksImages: saveAllBookmarksImages,
379+
copyImageToClipboard: copyImageToClipboard,
274380
};

scripts/shortcuts.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ function loadShortcuts()
191191
'zoomRight',
192192
'saveImage',
193193
'saveAllImages',
194+
'copyImage',
194195
'saveBookmarksImages',
195196
'saveAllBookmarksImages',
196197
'resetZoom',
@@ -272,6 +273,7 @@ function loadShortcuts()
272273
items: [
273274
'saveImage',
274275
'saveAllImages',
276+
'copyImage',
275277
'saveBookmarksImages',
276278
'saveAllBookmarksImages',
277279
],
@@ -765,6 +767,14 @@ function loadShortcuts()
765767
return true;
766768
},
767769
},
770+
copyImage: {
771+
name: language.global.contextMenu.copyImage,
772+
function: function(event){
773+
if(inputIsFocused() || !reading.isLoaded()) return false;
774+
reading.contextMenu.copyImageToClipboard();
775+
return true;
776+
},
777+
},
768778
saveBookmarksImages: {
769779
name: language.global.contextMenu.saveBookmarksImages,
770780
function: function(event){
@@ -861,6 +871,7 @@ function loadShortcuts()
861871
'Esc': 'goBack',
862872
'Backspace': 'goBack',
863873
'Ctrl+S': 'saveImage',
874+
'Ctrl+C': 'copyImage',
864875
'F11': 'fullscreen',
865876
'G': 'gamepadMenu',
866877
},

templates/reading.elements.menus.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,11 @@
198198
<span>{{language.global.contextMenu.saveAllImages}}</span>
199199
</div>
200200

201+
<div class="menu-simple-element menu-simple-element-little reading-context-menu-copy-image gamepad-item" onclick="reading.contextMenu.copyImageToClipboard();">
202+
<i class="material-icon menu-simple-icon-first">content_copy</i>
203+
<span>{{language.global.contextMenu.copyImage}}</span>
204+
</div>
205+
201206
<div class="menu-simple-separator separator-save-images"></div>
202207

203208
<div class="menu-simple-element menu-simple-element-little reading-context-menu-save-bookmarks-images gamepad-item" onclick="reading.contextMenu.saveBookmarksImages(true);">

0 commit comments

Comments
 (0)