-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
938044e
commit 66eef49
Showing
4 changed files
with
225 additions
and
0 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Affinity Thumbnail Viewer - View and Download Thumbnails</title> | ||
<meta name="description" content="Affinity Thumbnail Viewer is a tool for viewing and downloading thumbnails from .afphoto and .afdesign files."> | ||
<link rel="stylesheet" href="styles.css"> | ||
<link rel="icon" href="images/icon.png" type="image/png"> | ||
</head> | ||
<body> | ||
<div class="container"> | ||
<h1>AFFINITY THUMBNAIL VIEWER</h1> | ||
<input type="file" id="fileInput" accept=".afphoto,.afdesign"> | ||
<label for="fileInput">Choose a file</label> | ||
<div id="output"></div> | ||
<a id="downloadBtn" download="">Download Image</a> | ||
<div class="credits">Page created by <strong><a href="https://linktr.ee/omega_slender" target="_blank" rel="noopener">Omega Slender</a></strong>, based on the work of <strong><a href="https://forum.affinity.serif.com/index.php?/topic/180457-afthumbs-extracting-png-thumbnails-from-afphoto-and-afdesign-files/" target="_blank" rel="noopener">v_kyr</a></strong></div> | ||
</div> | ||
<script src="script.js"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
document.getElementById('fileInput').addEventListener('change', () => { | ||
const fileInput = document.getElementById('fileInput'); | ||
const output = document.getElementById('output'); | ||
const downloadBtn = document.getElementById('downloadBtn'); | ||
|
||
if (fileInput.files.length === 0) { | ||
alert('Please select a file.'); | ||
return; | ||
} | ||
|
||
const file = fileInput.files[0]; | ||
|
||
if (!file.name.match(/\.(afphoto|afdesign)$/i)) { | ||
alert('Please select a .afphoto or .afdesign file.'); | ||
return; | ||
} | ||
|
||
const reader = new FileReader(); | ||
reader.onload = function(event) { | ||
const arrayBuffer = event.target.result; | ||
const binaryData = new Uint8Array(arrayBuffer); | ||
|
||
const images = extractPngs(binaryData); | ||
if (images.length > 0) { | ||
const outputImage = images.reduce((a, b) => a.byteLength < b.byteLength ? a : b); | ||
const blob = new Blob([outputImage], { type: 'image/png' }); | ||
const url = URL.createObjectURL(blob); | ||
|
||
const img = document.createElement('img'); | ||
img.src = url; | ||
output.innerHTML = ''; | ||
output.appendChild(img); | ||
|
||
downloadBtn.href = url; | ||
downloadBtn.download = file.name.replace(/\.(afphoto|afdesign)$/i, '.png'); | ||
downloadBtn.style.display = 'inline-block'; | ||
} else { | ||
output.textContent = 'No PNG images found in the file.'; | ||
downloadBtn.style.display = 'none'; | ||
} | ||
}; | ||
reader.readAsArrayBuffer(file); | ||
}); | ||
|
||
function extractPngs(binaryData) { | ||
const images = []; | ||
const numBytes = binaryData.length; | ||
|
||
for (let i = 0; i < numBytes; i++) { | ||
if ( | ||
binaryData[i] === 0x89 && | ||
binaryData[i + 1] === 0x50 && | ||
binaryData[i + 2] === 0x4E && | ||
binaryData[i + 3] === 0x47 && | ||
binaryData[i + 4] === 0x0D && | ||
binaryData[i + 5] === 0x0A && | ||
binaryData[i + 6] === 0x1A && | ||
binaryData[i + 7] === 0x0A | ||
) { | ||
const pngSize = binaryData[i + 8] | | ||
(binaryData[i + 9] << 8) | | ||
(binaryData[i + 10] << 16) | | ||
(binaryData[i + 11] << 24); | ||
const pngData = binaryData.slice(i, i + pngSize + 8); | ||
images.push(pngData); | ||
} | ||
} | ||
|
||
return images; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
body { | ||
background: linear-gradient(135deg, #FC466B, #3F5EFB); | ||
font-family: 'Arial', sans-serif; | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
height: 100vh; | ||
margin: 0; | ||
color: #E0E0E0; | ||
} | ||
|
||
.container { | ||
background-color: #1E1E1E; | ||
padding: 20px; | ||
border-radius: 15px; | ||
box-shadow: 0 0 20px rgba(0, 0, 0, 0.5); | ||
text-align: center; | ||
max-width: 550px; | ||
width: 100%; | ||
} | ||
|
||
h1 { | ||
margin-bottom: 20px; | ||
font-size: 28px; | ||
color: #FFFFFF; | ||
font-weight: bold; | ||
} | ||
|
||
input[type="file"] { | ||
display: none; | ||
} | ||
|
||
label { | ||
background-color: #3B3B3B; | ||
color: #E0E0E0; | ||
padding: 10px 20px; | ||
border-radius: 5px; | ||
cursor: pointer; | ||
} | ||
|
||
label:hover { | ||
background-color: #575757; | ||
} | ||
|
||
#output { | ||
margin-top: 20px; | ||
} | ||
|
||
#output img { | ||
max-width: 1000px; | ||
max-height: 350px; | ||
max-width: 100%; | ||
height: auto; | ||
border-radius: 10px; | ||
box-shadow: 0 0 15px rgba(0, 0, 0, 0.3); | ||
} | ||
|
||
#downloadBtn { | ||
background: linear-gradient(135deg, #4CAF50, #009688); | ||
color: #ffffff; | ||
padding: 10px 20px; | ||
border-radius: 5px; | ||
cursor: pointer; | ||
display: none; | ||
margin-top: 10px; | ||
text-decoration: none; | ||
background-size: 200% 200%; | ||
} | ||
|
||
#downloadBtn:hover, | ||
#downloadBtn:active { | ||
background: linear-gradient(135deg, #54d058, #00baa8); | ||
} | ||
|
||
.credits { | ||
font-size: 12px; | ||
color: #E0E0E0; | ||
margin-top: 20px; | ||
} | ||
|
||
.credits a { | ||
color: #E0E0E0; | ||
text-decoration: none; | ||
transition: color 0.3s ease; | ||
} | ||
|
||
.credits a:hover { | ||
color: #FFFFFF; | ||
} | ||
|
||
.credits strong { | ||
font-weight: bold; | ||
} | ||
|
||
@media (max-width: 600px) { | ||
.container { | ||
padding: 20px; | ||
border-radius: 10px; | ||
} | ||
|
||
h1 { | ||
font-size: 20px; | ||
margin-bottom: 15px; | ||
} | ||
|
||
label { | ||
padding: 10px 15px; | ||
} | ||
|
||
#downloadBtn { | ||
padding: 10px 15px; | ||
} | ||
} | ||
|
||
@media (max-width: 400px) { | ||
.container { | ||
padding: 15px; | ||
border-radius: 8px; | ||
} | ||
|
||
h1 { | ||
font-size: 18px; | ||
margin-bottom: 10px; | ||
} | ||
|
||
label { | ||
padding: 8px 10px; | ||
} | ||
|
||
#downloadBtn { | ||
padding: 8px 10px; | ||
} | ||
} |