PDF化!「260815_超かぐや姫おつかれさま本」
by
furyu-tei
13 hours ago [2026/08/17 02:56:09]
Dropboxから「260815_超かぐや姫おつかれさま本」の画像をPDF形式でダウンロードする
@@ -83,8 +83,6 @@
pdf_img_height = pdf_height;
pdf_img_width = pdf_height / img_ratio;
}
- console.log(`x:${(pdf_width - pdf_img_width) / 2}, y: ${(pdf_height - pdf_img_height) / 2}`);
- console.log(`pdf_img_width:${pdf_img_width}, pdf_img_height: ${pdf_img_height}`);
pdf.addImage({
imageData: canvas.toDataURL('image/png'),
format: 'PNG',
@@ -107,16 +105,13 @@
const img_bitmap = await createImageBitmap(img_data);
console.log(`${page_number+1}: ${img_bitmap.width}x${img_bitmap.height}`);
if (img_bitmap.width <= img_bitmap.height) {
- console.log(`img_number: ${img_number}`);
add_img_to_pdf(img_bitmap, 0, img_bitmap.width);
img_number++;
}
else {
const slice_width = Math.floor(img_bitmap.width / 2);
- console.log(`img_number: ${img_number}`);
add_img_to_pdf(img_bitmap, 0, slice_width);
img_number++;
- console.log(`img_number: ${img_number}`);
add_img_to_pdf(img_bitmap, slice_width, img_bitmap.width - slice_width);
img_number++;
}
/*
* @title PDF化!「260815_超かぐや姫おつかれさま本」
* @description Dropboxから「260815_超かぐや姫おつかれさま本」の画像をPDF形式でダウンロードする
* @include https://www.dropbox.com/*
* @license MIT License
* @require
* @javascript_url
*/
/*
//「260815_超かぐや姫おつかれさま本」公開ページはこちら↓
// https://www.dropbox.com/scl/fi/2dz2rnch41n0ym6svx2v1/260815_.pdf?rlkey=79hr9bq43shkosbwhe93003lu&st=z03mvt95&e=1&dl=0
// ※関連ツイート(ポスト) → https://x.com/momocyo/status/2088566368677331068
*/
(async () => {
const wait = msec => new Promise(resolve => setTimeout(resolve, msec));
const script = document.createElement('script');
script.nonce = document.querySelector('script[nonce]').nonce;
script.src = 'https://cdnjs.cloudflare.com/ajax/libs/jspdf/4.2.1/jspdf.umd.min.js';
document.documentElement.append(script);
for (let ci=0; ci < 50; ci++) {
if (typeof jspdf !== 'undefined') break;
await wait(100);
}
if (typeof jspdf === 'undefined') {
alert('Failed to load jsPDF');
return;
}
const jsPDF = jspdf.jsPDF;
const document_title = document.querySelector('title').textContent;
const max_page = [...document.querySelector('[data-testid="page-count"],[role="document"]>div>.dig-Layer>div>.dig-Text').childNodes].filter(elem=>elem.nodeName=='#text').map(elm=>elm.nodeValue).join('').match(/\/\s*(\d+)/)[1] - 0;
const max_page_strlen = `${max_page*2-2}`.length;
const sample_img = document.querySelector('[data-testid="preview-viewport"] [id^="pageContainer"][data-index] img');
const img_url = new URL(sample_img.src);
const img_ext = img_url.pathname.match(/\.[^.]+$/)[0];
const progress_container = document.createElement('div');
Object.assign(progress_container.style, {
position: 'fixed',
top: '4px',
left: '8px',
zIndex: 10000,
padding: '4px',
fontFamily: 'monospace',
color: 'black',
backgroundColor: 'lightyellow',
});
document.documentElement.append(progress_container);
const show_progress = page_number => progress_container.textContent = `ZIP(PDF): ${page_number} / ${max_page}`;
const canvas = document.createElement('canvas');
Object.assign(canvas.style, {
display: 'none',
});
document.documentElement.append(canvas);
const context = canvas.getContext('2d');
const canvas_to_blob = () => new Promise(resolve => canvas.toBlob(blob => resolve(blob), 'image/png', 1));
const get_img_filename = img_number => `${(''+img_number).padStart(max_page_strlen, 0)}.png`;
const pdf = new jsPDF({
orientation: 'portrait',
unit: 'mm',
format: 'a4',
});
pdf.setProperties({
title: '超かぐや姫!おつかれさま本',
author: 'パンケーキオクトパス',
keywords: 'C108,20260815',
creator: 'Unofficial bookmarklet (powered by jsPDF)'
});
const pdf_width = pdf.internal.pageSize.getWidth();
const pdf_height = pdf.internal.pageSize.getHeight();
const pdf_ratio = pdf_height / pdf_width;
const add_img_to_pdf = (img_bitmap, offset_x, slice_width) => {
canvas.width = slice_width;
canvas.height = img_bitmap.height;
context.drawImage(img_bitmap, offset_x, 0, slice_width, img_bitmap.height, 0, 0, slice_width, img_bitmap.height);
const img_ratio = img_bitmap.height / slice_width;
let pdf_img_width, pdf_img_height;
if (img_ratio < pdf_ratio) {
pdf_img_width = pdf_width;
pdf_img_height = pdf_width * img_ratio;
}
else {
pdf_img_height = pdf_height;
pdf_img_width = pdf_height / img_ratio;
}
pdf.addImage({
imageData: canvas.toDataURL('image/png'),
format: 'PNG',
x: (pdf_width - pdf_img_width) / 2,
y: (pdf_height - pdf_img_height) / 2,
width: pdf_img_width,
height: pdf_img_height,
});
pdf.addPage();
};
for (let page_number=0, img_number=1; page_number < max_page; page_number++) {
show_progress(page_number+1);
img_url.searchParams.set('page', page_number);
const response = await fetch(img_url.href);
if (! response.ok) {
console.error(`Fetch failure ${page_number+1}: ${img_url.href}`);
continue;
}
const img_data = await response.blob();
const img_bitmap = await createImageBitmap(img_data);
console.log(`${page_number+1}: ${img_bitmap.width}x${img_bitmap.height}`);
if (img_bitmap.width <= img_bitmap.height) {
add_img_to_pdf(img_bitmap, 0, img_bitmap.width);
img_number++;
}
else {
const slice_width = Math.floor(img_bitmap.width / 2);
add_img_to_pdf(img_bitmap, 0, slice_width);
img_number++;
add_img_to_pdf(img_bitmap, slice_width, img_bitmap.width - slice_width);
img_number++;
}
}
pdf.deletePage(pdf.getNumberOfPages());
pdf.save(`${document_title.replace(/\.[^.]+$/,'')}.pdf`);
canvas.remove();
progress_container.remove();
})();
- Permalink
- このページへの個別リンクです。
- RAW
- 書かれたコードへの直接のリンクです。
- Packed
- 文字列が圧縮された書かれたコードへのリンクです。
- Userscript
- Greasemonkey 等で利用する場合の .user.js へのリンクです。
- Loader
- @require やソースコードが長い場合に多段ロードする Loader コミのコードへのリンクです。
- Metadata
- コード中にコメントで @xxx と書かれたメタデータの JSON です。