final version
This commit is contained in:
parent
a610a2ac06
commit
2933dfc135
|
@ -1,6 +1,11 @@
|
||||||
.idea
|
|
||||||
image/dzi
|
|
||||||
image/original
|
|
||||||
image/script
|
|
||||||
image/image.txt
|
image/image.txt
|
||||||
.venv
|
image/dzi
|
||||||
|
image/dzi_edited
|
||||||
|
image/original
|
||||||
|
image/script/bin
|
||||||
|
image/script/include
|
||||||
|
image/script/lib
|
||||||
|
image/script/lib64
|
||||||
|
image/script/pyvenv.cfg
|
||||||
|
upload.sh
|
||||||
|
annotations
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,18 +0,0 @@
|
||||||
[{
|
|
||||||
"@context": "http://www.w3.org/ns/anno.jsonld",
|
|
||||||
"id": "#a88b22d0-6106-4872-9435-c78b5e890000",
|
|
||||||
"type": "Annotation",
|
|
||||||
"body": [{
|
|
||||||
"type": "TextualBody",
|
|
||||||
"value": "Nothing here yet!",
|
|
||||||
"format" : "text/html",
|
|
||||||
"language" : "en"
|
|
||||||
}],
|
|
||||||
"target": {
|
|
||||||
"selector": {
|
|
||||||
"type": "FragmentSelector",
|
|
||||||
"conformsTo": "http://www.w3.org/TR/media-frags/",
|
|
||||||
"value": "xywh=pixel:0,0,1000,1000"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}]
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
#!/bin/bash
|
||||||
|
source script/bin/activate
|
||||||
|
|
||||||
|
# Xvfb :99 -screen 0 1280x1024x24 &
|
||||||
|
# export DISPLAY=:99
|
||||||
|
|
||||||
|
python3 script/generate_dzi_files.py
|
||||||
|
python3 script/generate_images_txt.py
|
||||||
|
python3 script/generate_filtered_photos.py
|
||||||
|
python3 script/generate_annotations.py
|
||||||
|
|
||||||
|
sudo chmod -R 775 .
|
||||||
|
sudo chown -R opc .
|
|
@ -0,0 +1,53 @@
|
||||||
|
import json
|
||||||
|
import uuid
|
||||||
|
import requests
|
||||||
|
|
||||||
|
def get_post_data(folder_name):
|
||||||
|
url = f"https://sketchersunited.org/posts/{folder_name.split('by')[0]}"
|
||||||
|
headers = {"Accept": "text/json"}
|
||||||
|
response = requests.get(url, headers=headers)
|
||||||
|
if response.status_code == 200:
|
||||||
|
return response.json()
|
||||||
|
return None
|
||||||
|
|
||||||
|
with open('image.txt', 'r') as file:
|
||||||
|
lines = file.readlines()
|
||||||
|
|
||||||
|
annotations = []
|
||||||
|
|
||||||
|
for line in lines:
|
||||||
|
folder_name, x, y, _, _, _ = line.strip().split()
|
||||||
|
annotation_id = str(uuid.uuid4())
|
||||||
|
|
||||||
|
post_data = get_post_data(folder_name)
|
||||||
|
if post_data:
|
||||||
|
annotation_text = f'🖼️ <a href="https://sketchersunited.org/posts/{post_data["post"]["id"]}">{post_data["post"]["title"]}</a> <br>👤 <a href="https://sketchersunited.org/users/{post_data["post"]["profile"]["id"]}">@{post_data["post"]["profile"]["username"]}</a>'
|
||||||
|
else:
|
||||||
|
annotation_text = "Data not available"
|
||||||
|
|
||||||
|
annotation = {
|
||||||
|
"@context": "http://www.w3.org/ns/anno.jsonld",
|
||||||
|
"id": f"#{annotation_id}",
|
||||||
|
"type": "Annotation",
|
||||||
|
"body": [{
|
||||||
|
"type": "TextualBody",
|
||||||
|
"value": annotation_text,
|
||||||
|
"format": "text/html",
|
||||||
|
"language": "en"
|
||||||
|
}],
|
||||||
|
"target": {
|
||||||
|
"selector": {
|
||||||
|
"type": "FragmentSelector",
|
||||||
|
"conformsTo": "http://www.w3.org/TR/media-frags/",
|
||||||
|
"value": f"xywh=pixel:{int(x)*1000},{int(y)*1000},1000,1000"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
annotations.append(annotation)
|
||||||
|
print(f"Appended annotation for {folder_name}")
|
||||||
|
|
||||||
|
with open('../annotations/annotations.w3c.json', 'w') as output_file:
|
||||||
|
json.dump(annotations, output_file, indent=2)
|
||||||
|
|
||||||
|
print("Annotations JSON file created.")
|
|
@ -12,7 +12,6 @@ def convert_to_jpg(input_file, output_dir):
|
||||||
convert_command = ["convert", input_file, "-quality", "100", output_file]
|
convert_command = ["convert", input_file, "-quality", "100", output_file]
|
||||||
|
|
||||||
subprocess.run(convert_command)
|
subprocess.run(convert_command)
|
||||||
print(f"Converted {input_file} to JPG")
|
|
||||||
|
|
||||||
process_image(output_file, output_dir)
|
process_image(output_file, output_dir)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
@ -23,35 +22,27 @@ def process_image(input_file, output_dir):
|
||||||
file_name_without_extension = os.path.splitext(os.path.basename(input_file))[0]
|
file_name_without_extension = os.path.splitext(os.path.basename(input_file))[0]
|
||||||
output_file = os.path.join(output_dir, file_name_without_extension, f"{file_name_without_extension}")
|
output_file = os.path.join(output_dir, file_name_without_extension, f"{file_name_without_extension}")
|
||||||
|
|
||||||
command = ["./magick-slicer.sh", input_file, output_file]
|
command = ["./script/magick-slicer.sh", input_file, output_file]
|
||||||
|
|
||||||
print(command)
|
|
||||||
print(output_file)
|
|
||||||
print(os.getcwd())
|
|
||||||
|
|
||||||
subprocess.run(command)
|
subprocess.run(command)
|
||||||
print(f"Processed {input_file}")
|
print(f"Processed {input_file}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error processing {input_file}: {e}")
|
print(f"Error processing {input_file}: {e}")
|
||||||
|
|
||||||
def main():
|
input_dir = "original"
|
||||||
|
output_dir = "dzi"
|
||||||
|
|
||||||
input_dir = "original"
|
os.makedirs(output_dir, exist_ok=True)
|
||||||
output_dir = "dzi"
|
os.makedirs(os.path.join(input_dir, "jpg"), exist_ok=True)
|
||||||
|
|
||||||
os.makedirs(output_dir, exist_ok=True)
|
image_files = []
|
||||||
os.makedirs(os.path.join(input_dir, "jpg"), exist_ok=True)
|
for root, _, files in os.walk(input_dir):
|
||||||
|
for filename in files:
|
||||||
|
if filename.lower().endswith((".jpg", ".jpeg", ".png", ".gif")):
|
||||||
|
image_files.append(os.path.join(root, filename))
|
||||||
|
|
||||||
image_files = []
|
for input_file in image_files:
|
||||||
for root, _, files in os.walk(input_dir):
|
convert_to_jpg(input_file, output_dir)
|
||||||
for filename in files:
|
|
||||||
if filename.lower().endswith((".jpg", ".jpeg", ".png", ".gif")):
|
|
||||||
image_files.append(os.path.join(root, filename))
|
|
||||||
|
|
||||||
for input_file in image_files:
|
shutil.rmtree(os.path.join(input_dir, "jpg"))
|
||||||
convert_to_jpg(input_file, output_dir)
|
print("Sliced all photos.")
|
||||||
|
|
||||||
shutil.rmtree(os.path.join(input_dir, "jpg"))
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
from PIL import Image, ImageOps, ImageEnhance
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
with open('image.txt', 'r') as file:
|
||||||
|
lines = file.readlines()
|
||||||
|
|
||||||
|
for line, folder_name in zip(lines, os.listdir('dzi')):
|
||||||
|
folder_name, x, y, red, green, blue = line.strip().split()
|
||||||
|
|
||||||
|
original_folder_path = os.path.join('dzi', folder_name, folder_name + '_files')
|
||||||
|
|
||||||
|
edited_folder_path = os.path.join('dzi_edited', folder_name, folder_name + '_files')
|
||||||
|
os.makedirs(edited_folder_path, exist_ok=True)
|
||||||
|
|
||||||
|
original_dzi_file_path = os.path.join('dzi', folder_name, f'{folder_name}.dzi')
|
||||||
|
edited_dzi_file_path = os.path.join('dzi_edited', folder_name, f'{folder_name}.dzi')
|
||||||
|
shutil.copy(original_dzi_file_path, edited_dzi_file_path)
|
||||||
|
|
||||||
|
for folder in os.listdir(original_folder_path):
|
||||||
|
for filename in os.listdir(os.path.join(original_folder_path, folder)):
|
||||||
|
original_image_path = os.path.join(original_folder_path, folder, filename)
|
||||||
|
grayscale_image = ImageOps.grayscale(Image.open(original_image_path))
|
||||||
|
|
||||||
|
colormap = ImageOps.colorize(grayscale_image, black=(0, 0, 0), white=(int(red), int(green), int(blue)))
|
||||||
|
|
||||||
|
enhancer = ImageEnhance.Brightness(colormap)
|
||||||
|
bright_colormap = enhancer.enhance(1.5)
|
||||||
|
|
||||||
|
edited_image_path = os.path.join(edited_folder_path, folder, filename)
|
||||||
|
|
||||||
|
os.makedirs(os.path.join(edited_folder_path, folder), exist_ok=True)
|
||||||
|
bright_colormap.save(edited_image_path, quality=100)
|
||||||
|
print("Processing " + folder_name)
|
||||||
|
|
||||||
|
print("Image processing completed.")
|
|
@ -0,0 +1,23 @@
|
||||||
|
from PIL import Image
|
||||||
|
import os
|
||||||
|
|
||||||
|
if os.path.exists("image.txt"):
|
||||||
|
os.remove("image.txt")
|
||||||
|
|
||||||
|
su_image = Image.open("sureal25x25.png").convert("RGBA")
|
||||||
|
su_pixels = su_image.load()
|
||||||
|
|
||||||
|
subfolder_names = sorted(os.listdir("dzi"))
|
||||||
|
|
||||||
|
with open("image.txt", "w") as output_file:
|
||||||
|
for y in range(su_image.height):
|
||||||
|
for x in range(su_image.width):
|
||||||
|
r, g, b, a = su_pixels[x, y]
|
||||||
|
|
||||||
|
if a == 255:
|
||||||
|
if subfolder_names:
|
||||||
|
folder_name = subfolder_names.pop(0)
|
||||||
|
output_file.write(f"{folder_name} {x} {y} {r} {g} {b}\n")
|
||||||
|
else:
|
||||||
|
print("Finished generating images txt")
|
||||||
|
exit()
|
|
@ -0,0 +1,2 @@
|
||||||
|
pillow
|
||||||
|
requests
|
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.9 KiB |
Binary file not shown.
After Width: | Height: | Size: 3.1 KiB |
|
@ -60,7 +60,7 @@
|
||||||
|
|
||||||
<h2>🌐 How do I use this page?</h2>
|
<h2>🌐 How do I use this page?</h2>
|
||||||
<p>Use either the mouse wheel or your fingers to zoom in and out of the view.
|
<p>Use either the mouse wheel or your fingers to zoom in and out of the view.
|
||||||
<br> You can tap on the image to see who drew it and get a link to the post.
|
<br> (Not yet implemented) You can tap on the image to see who drew it and get a link to the post.
|
||||||
<br>
|
<br>
|
||||||
<br>ℹ️ The view may get somewhat laggy on a mobile device. For the best experience use a desktop computer.
|
<br>ℹ️ The view may get somewhat laggy on a mobile device. For the best experience use a desktop computer.
|
||||||
<br>This is unavoidable due to the number of images downloaded and shown.
|
<br>This is unavoidable due to the number of images downloaded and shown.
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
const anno = OpenSeadragon.Annotorious(viewer);
|
const anno = OpenSeadragon.Annotorious(viewer);
|
||||||
anno.readOnly = true
|
anno.readOnly = true;
|
||||||
anno.loadAnnotations('annotations/initial.w3c.json');
|
anno.escape = false;
|
||||||
|
anno.loadAnnotations('annotations/annotations.w3c.json');
|
||||||
let annotationText = ""
|
let annotationText = ""
|
||||||
|
|
||||||
function renderHTML()
|
function renderHTML()
|
||||||
|
@ -25,4 +26,5 @@ anno.on('clickAnnotation', function(annotation, element)
|
||||||
viewer.addHandler('update-viewport', function(event)
|
viewer.addHandler('update-viewport', function(event)
|
||||||
{
|
{
|
||||||
renderHTML()
|
renderHTML()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,6 @@ let dictionaries = []
|
||||||
const imagePromises = [];
|
const imagePromises = [];
|
||||||
let image_count = 0
|
let image_count = 0
|
||||||
|
|
||||||
Caman.Store.put = function() {};
|
|
||||||
|
|
||||||
function load_image(image) {
|
function load_image(image) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
viewer.addTiledImage({
|
viewer.addTiledImage({
|
||||||
|
@ -31,17 +29,17 @@ fetch('image/image.txt')
|
||||||
.then(text => {
|
.then(text => {
|
||||||
const lines = text.split('\n');
|
const lines = text.split('\n');
|
||||||
lines.forEach(line => {
|
lines.forEach(line => {
|
||||||
if (!line.startsWith('#')) {
|
if (!line.startsWith('#') && line.length > 0) {
|
||||||
const parts = line.split(' ');
|
const parts = line.split(' ');
|
||||||
|
|
||||||
const dictionary = {
|
const dictionary = {
|
||||||
imageCount: image_count,
|
imageCount: image_count,
|
||||||
tileSource: 'image/dzi/' + parts[0] + '/' + parts[0] + '.dzi',
|
tileSource: 'image/dzi_edited/' + parts[0] + '/' + parts[0] + '.dzi',
|
||||||
x: parseInt(parts[1]),
|
x: parseInt(parts[1]),
|
||||||
y: parseInt(parts[2]),
|
y: parseInt(parts[2]),
|
||||||
red: parseInt(parts[3]),
|
red: parseInt(parts[3]),
|
||||||
blue: parseInt(parts[4]),
|
green: parseInt(parts[4]),
|
||||||
green: parseInt(parts[5]),
|
blue: parseInt(parts[5]),
|
||||||
};
|
};
|
||||||
|
|
||||||
const promise = load_image(dictionary);
|
const promise = load_image(dictionary);
|
||||||
|
@ -62,14 +60,13 @@ fetch('image/image.txt')
|
||||||
processors: [
|
processors: [
|
||||||
function (context, callback) {
|
function (context, callback) {
|
||||||
Caman(context.canvas, function () {
|
Caman(context.canvas, function () {
|
||||||
this.colorize(image.red, image.green, image.blue, 50);
|
this.colorize(image.red, image.green, image.blue, 80);
|
||||||
this.render(callback);
|
this.render(callback);
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
// },
|
|
||||||
// function (context, callback) {
|
// function (context, callback) {
|
||||||
// Caman(context.canvas, function () {
|
// Caman(context.canvas, function () {
|
||||||
// this.contrast(10);
|
// this.contrast(100);
|
||||||
// this.render(callback);
|
// this.render(callback);
|
||||||
// });
|
// });
|
||||||
// }
|
// }
|
||||||
|
@ -79,9 +76,9 @@ fetch('image/image.txt')
|
||||||
all_filters.push(filter)
|
all_filters.push(filter)
|
||||||
});
|
});
|
||||||
|
|
||||||
viewer.setFilterOptions({
|
// viewer.setFilterOptions({
|
||||||
filters: all_filters
|
// filters: all_filters
|
||||||
});
|
// });
|
||||||
|
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
const clientCountElement = document.getElementById('clientCount');
|
const clientCountElement = document.getElementById('clientCount');
|
||||||
const socket = new WebSocket('ws://localhost:8080/funsocket');
|
const socket = new WebSocket('wss://sketchersunitedcollab.com/funsocket');
|
||||||
|
|
||||||
socket.addEventListener('message', (event) => {
|
socket.addEventListener('message', (event) => {
|
||||||
const clientCount = parseInt(event.data);
|
if(event.data.toString().length < 5) {
|
||||||
let append = " people"
|
const clientCount = parseInt(event.data);
|
||||||
if (clientCount === 1) {
|
|
||||||
append = " person"
|
let append = " people"
|
||||||
|
if (clientCount === 1) {
|
||||||
|
append = " person"
|
||||||
|
}
|
||||||
|
clientCountElement.textContent = clientCount.toString() + append;
|
||||||
}
|
}
|
||||||
clientCountElement.textContent = clientCount.toString() + append;
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
Caman.Store.put = function() {};
|
||||||
|
|
||||||
const viewer = OpenSeadragon({
|
const viewer = OpenSeadragon({
|
||||||
id: "viewer",
|
id: "viewer",
|
||||||
showZoomControl: false,
|
showZoomControl: false,
|
||||||
|
@ -12,9 +14,9 @@ viewer.smartScrollZoom({
|
||||||
zoomIncrement: 1000
|
zoomIncrement: 1000
|
||||||
});
|
});
|
||||||
|
|
||||||
viewer.viewport.minZoomLevel = 0.0125;
|
viewer.viewport.minZoomLevel = 0.001;
|
||||||
viewer.viewport.maxZoomLevel = 100;
|
viewer.viewport.maxZoomLevel = 2;
|
||||||
viewer.viewport.defaultZoomLevel = 0.0125;
|
viewer.viewport.defaultZoomLevel = 0.05;
|
||||||
viewer.viewport.scrollHandlerSpeed = 1000;
|
viewer.viewport.scrollHandlerSpeed = 1000;
|
||||||
viewer.drawer.context.imageSmoothingEnabled = false;
|
viewer.drawer.context.imageSmoothingEnabled = false;
|
||||||
viewer.gestureSettingsMouse.clickToZoom = false;
|
viewer.gestureSettingsMouse.clickToZoom = false;
|
||||||
|
|
|
@ -12,7 +12,7 @@ body {
|
||||||
background-color: #222;
|
background-color: #222;
|
||||||
background-image: url("image/su.png");
|
background-image: url("image/su.png");
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-size: 1000px;
|
background-size: 400px;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
image-rendering: pixelated;
|
image-rendering: pixelated;
|
||||||
}
|
}
|
||||||
|
@ -170,10 +170,10 @@ a {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 1081px) {
|
@media screen and (max-width: 1081px) and (-webkit-min-device-pixel-ratio: 2) {
|
||||||
#viewer {
|
#viewer {
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
height: 100vh;
|
height: 66vh;
|
||||||
}
|
}
|
||||||
#modal-content {
|
#modal-content {
|
||||||
font-size: 20pt;
|
font-size: 20pt;
|
||||||
|
|
|
@ -15,7 +15,6 @@ class WebSocketHandler(tornado.websocket.WebSocketHandler):
|
||||||
self.send_client_count()
|
self.send_client_count()
|
||||||
|
|
||||||
def check_origin(self, origin):
|
def check_origin(self, origin):
|
||||||
# Allow all connections regardless of the origin
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def send_client_count(self):
|
def send_client_count(self):
|
||||||
|
@ -27,35 +26,26 @@ class WebSocketHandler(tornado.websocket.WebSocketHandler):
|
||||||
print(f"Error sending message to client: {e}")
|
print(f"Error sending message to client: {e}")
|
||||||
|
|
||||||
async def handle_message(self, message):
|
async def handle_message(self, message):
|
||||||
if message.startswith("post"):
|
try:
|
||||||
# Extract post_id_var and author_id_var from the message
|
post, user = message.split('by')
|
||||||
try:
|
post = int(post)
|
||||||
_, post_id_var, _, author_id_var = message.split("{")
|
user = int(user)
|
||||||
post_id = int(post_id_var.split("}")[0])
|
|
||||||
author_id = int(author_id_var.split("}")[0])
|
|
||||||
|
|
||||||
# Construct the URL
|
post_url = f"https://sketchersunited.org/posts/{post}"
|
||||||
post_url = f"https://post.com/{post_id}"
|
headers = {
|
||||||
|
"Accept": "application/json",
|
||||||
|
}
|
||||||
|
|
||||||
# Create HTTP request headers with Accept: application/json
|
request = HTTPRequest(post_url, method="GET", headers=headers)
|
||||||
headers = {
|
|
||||||
"Accept": "application/json",
|
|
||||||
}
|
|
||||||
|
|
||||||
# Create an HTTP request
|
http_client = AsyncHTTPClient()
|
||||||
request = HTTPRequest(post_url, method="GET", headers=headers)
|
response = await http_client.fetch(request)
|
||||||
|
self.write_message(response.body)
|
||||||
|
|
||||||
# Fetch the URL asynchronously
|
except Exception as e:
|
||||||
http_client = AsyncHTTPClient()
|
print(f"Error handling message: {e}")
|
||||||
response = await http_client.fetch(request)
|
|
||||||
|
|
||||||
# Send the JSON response back to the WebSocket client
|
|
||||||
self.write_message(response.body)
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error handling message: {e}")
|
|
||||||
|
|
||||||
def on_message(self, message):
|
def on_message(self, message):
|
||||||
# Handle incoming messages
|
|
||||||
tornado.ioloop.IOLoop.current().add_callback(self.handle_message, message)
|
tornado.ioloop.IOLoop.current().add_callback(self.handle_message, message)
|
||||||
|
|
||||||
app = tornado.web.Application([
|
app = tornado.web.Application([
|
||||||
|
|
Loading…
Reference in New Issue