Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 53 additions & 18 deletions effect/utils.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
import numpy as np
from qiskit import generate_preset_pass_manager
from qiskit.primitives import BackendEstimatorV2 as Estimator
import os
from qiskit_aer import AerSimulator
import colorsys
from itertools import product
import matplotlib.pyplot as plt
from matplotlib.path import Path as plt_path
from scipy.ndimage import distance_transform_edt

try:
from matplotlib.path import Path as plt_path
except ImportError:
plt_path = None

try:
from scipy.ndimage import distance_transform_edt
except ImportError:
distance_transform_edt = None

try:
from qiskit import generate_preset_pass_manager
from qiskit.primitives import BackendEstimatorV2 as Estimator
from qiskit_aer import AerSimulator
except ImportError:
generate_preset_pass_manager = None
Estimator = None
AerSimulator = None

def svd(matrix=None,U=None,S=None,Vt=None):
if U is not None:
Expand Down Expand Up @@ -89,26 +102,47 @@ def points_within_radius(points, radius=10, border = None, return_distance = Fal
# Create binary mask
mask = np.zeros((height, width), dtype=bool)
mask[shifted[:, 0], shifted[:, 1]] = True # y, x

# Distance transform
dist = distance_transform_edt(~mask)
# Find pixels within offset
region_mask = dist <= radius
ys, xs = np.nonzero(region_mask)

# Shift back to original coordinates
coords = np.stack([ys, xs], axis=1) + min_yx
#print(coords)

if distance_transform_edt is not None:
# Distance transform
dist = distance_transform_edt(~mask)
# Find pixels within offset
region_mask = dist <= radius
ys, xs = np.nonzero(region_mask)

# Shift back to original coordinates
coords = np.stack([ys, xs], axis=1) + min_yx
distances = dist[ys, xs] / radius
else:
line_points = np.argwhere(mask)
grid_y, grid_x = np.indices((height, width))
grid = np.stack([grid_y.ravel(), grid_x.ravel()], axis=1)

min_dist_sq = np.empty(grid.shape[0], dtype=np.float64)
chunk_size = 2048
for start in range(0, grid.shape[0], chunk_size):
end = start + chunk_size
chunk = grid[start:end]
diff = chunk[:, None, :] - line_points[None, :, :]
dist_sq = np.sum(diff * diff, axis=2)
min_dist_sq[start:end] = dist_sq.min(axis=1)

region_mask = min_dist_sq <= radius ** 2
coords = grid[region_mask] + min_yx
distances = np.sqrt(min_dist_sq[region_mask]) / radius

if border is not None:
coords = np.clip(coords, [0, 0], [border[0] - 1, border[1] - 1])

if return_distance:
distances = dist[ys, xs] / radius
return coords, distances

return coords

def points_within_lasso(points,border = None):
if plt_path is None:
raise ImportError("matplotlib is required to use lasso paths.")

min_x = np.min(points[:,1])
max_x = np.max(points[:,1])+1
min_y = np.min(points[:,0])
Expand Down Expand Up @@ -152,6 +186,8 @@ def run_estimator(circuits, operators, backend=None, options = None):
It can receive a single circuit or a list of circuits.
It can receive a single operator or a list of operators or a list of list of operators (one for each circuit).
'''
if generate_preset_pass_manager is None or Estimator is None or AerSimulator is None:
raise ImportError("Qiskit and qiskit-aer are required to run estimator-based effects.")

#iqm_server_url = "https://cocos.resonance.meetiqm.com/garnet:mock" # Replace this with the correct URL
#provider = IQMProvider(iqm_server_url)
Expand Down Expand Up @@ -352,4 +388,3 @@ def apply_patch_to_image(original_image: np.ndarray, new_patch: np.ndarray, blur
new_patch[..., :3] = (1 - alpha) * original_float[..., :3] + alpha * new_patch[..., :3]

return (new_patch * 255).astype(np.uint8)

2 changes: 1 addition & 1 deletion src/EffectManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public void loadEffects() {
// Clear existing effects to prevent contamination
effects.clear();

File effectsDir = new File("effect");
File effectsDir = QuantumBrush.appFile("effect");
if (!effectsDir.exists() || !effectsDir.isDirectory()) {
System.err.println("Error: effect directory not found or not a directory");
return;
Expand Down
43 changes: 22 additions & 21 deletions src/FileManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,23 @@ public FileManager(QuantumBrush app) {
public void saveProject(String projectId, PImage originalImage) {
String projectPath = "project/" + projectId;
ensureDirectoryExists(projectPath);
File projectDir = QuantumBrush.appFile(projectPath);

// Save original image
if (originalImage != null) {
originalImage.save(projectPath + "/original.png");
originalImage.save(new File(projectDir, "original.png").getAbsolutePath());
}

// IMPORTANT: Also save the current state (with all effects applied)
PImage currentImage = app.getCurrentImage();
if (currentImage != null) {
currentImage.save(projectPath + "/current.png");
currentImage.save(new File(projectDir, "current.png").getAbsolutePath());
System.out.println("Saved current state to: " + projectPath + "/current.png");
}
}

public boolean ensureDirectoryExists(String path) {
File directory = new File(path);
File directory = QuantumBrush.appFile(path);
if (!directory.exists()) {
return directory.mkdirs();
}
Expand All @@ -51,17 +52,17 @@ public void saveStroke(

// Save instructions
String instructionsPath = strokeDirPath + "/" + strokeId + "_instructions.json";
app.saveJSONObject(instructions, instructionsPath);
app.saveJSONObject(instructions, QuantumBrush.appFile(instructionsPath).getAbsolutePath());

// Save input image
if (inputImage != null) {
String imagePath = strokeDirPath + "/" + strokeId + "_input.png";
inputImage.save(imagePath);
inputImage.save(QuantumBrush.appFile(imagePath).getAbsolutePath());
}
}

public JSONObject loadEffectRequirements(String effectName) {
File requirementsFile = new File(
File requirementsFile = QuantumBrush.appFile(
"effect/" + effectName + "/" + effectName + "_requirements.json"
);
if (requirementsFile.exists()) {
Expand Down Expand Up @@ -89,18 +90,18 @@ public void createProjectMetadata(String projectId, String projectName) {
metadata.setLong("modified_time", currentTime);

// Save metadata
app.saveJSONObject(metadata, "metadata/" + projectId + ".json");
app.saveJSONObject(metadata, QuantumBrush.appFile("metadata/" + projectId + ".json").getAbsolutePath());
}

public void updateProjectMetadata(String projectId) {
String metadataPath = "metadata/" + projectId + ".json";
File metadataFile = new File(metadataPath);
File metadataFile = QuantumBrush.appFile(metadataPath);

if (metadataFile.exists()) {
try {
JSONObject metadata = app.loadJSONObject(metadataPath);
JSONObject metadata = app.loadJSONObject(metadataFile.getAbsolutePath());
metadata.setLong("modified_time", System.currentTimeMillis());
app.saveJSONObject(metadata, metadataPath);
app.saveJSONObject(metadata, metadataFile.getAbsolutePath());
} catch (Exception e) {
System.err.println("Error updating metadata: " + e.getMessage());
}
Expand All @@ -110,7 +111,7 @@ public void updateProjectMetadata(String projectId) {
public ArrayList<JSONObject> getProjectsMetadata() {
ArrayList<JSONObject> projects = new ArrayList<>();

File metadataDir = new File("metadata");
File metadataDir = QuantumBrush.appFile("metadata");
if (!metadataDir.exists()) {
ensureDirectoryExists("metadata");
return projects;
Expand All @@ -126,7 +127,7 @@ public ArrayList<JSONObject> getProjectsMetadata() {
// Check if the corresponding project directory exists
JSONObject metadata = app.loadJSONObject(file.getAbsolutePath());
String projectId = metadata.getString("project_id", "");
File projectDir = new File("project/" + projectId);
File projectDir = QuantumBrush.appFile("project/" + projectId);

// Only add to the list if the project directory exists
if (projectDir.exists() && projectDir.isDirectory()) {
Expand Down Expand Up @@ -174,11 +175,11 @@ public ArrayList<JSONObject> getProjectsMetadata() {

public JSONObject getProjectMetadata(String projectId) {
String metadataPath = "metadata/" + projectId + ".json";
File metadataFile = new File(metadataPath);
File metadataFile = QuantumBrush.appFile(metadataPath);

if (metadataFile.exists()) {
try {
return app.loadJSONObject(metadataPath);
return app.loadJSONObject(metadataFile.getAbsolutePath());
} catch (Exception e) {
System.err.println("Error loading metadata: " + e.getMessage());
}
Expand All @@ -190,15 +191,15 @@ public JSONObject getProjectMetadata(String projectId) {
// Add a method to load strokes when a project is loaded
public boolean loadProject(String projectId) {
String projectPath = "project/" + projectId;
File projectDir = new File(projectPath);
File projectDir = QuantumBrush.appFile(projectPath);

if (!projectDir.exists()) {
return false;
}

// Try to load current state first (with all effects applied)
File currentImageFile = new File(projectPath + "/current.png");
File originalImageFile = new File(projectPath + "/original.png");
File currentImageFile = QuantumBrush.appFile(projectPath + "/current.png");
File originalImageFile = QuantumBrush.appFile(projectPath + "/original.png");

PImage loadedImage = null;

Expand Down Expand Up @@ -246,13 +247,13 @@ public boolean deleteProject(String projectId) {

try {
// Delete project directory and all its contents
File projectDir = new File("project/" + projectId);
File projectDir = QuantumBrush.appFile("project/" + projectId);
if (projectDir.exists()) {
success &= deleteDirectory(projectDir);
}

// Delete metadata file
File metadataFile = new File("metadata/" + projectId + ".json");
File metadataFile = QuantumBrush.appFile("metadata/" + projectId + ".json");
if (metadataFile.exists()) {
success &= metadataFile.delete();
}
Expand Down Expand Up @@ -294,7 +295,7 @@ private boolean deleteDirectory(File directory) {
public int cleanupOrphanedMetadata() {
int cleanedCount = 0;

File metadataDir = new File("metadata");
File metadataDir = QuantumBrush.appFile("metadata");
if (!metadataDir.exists()) {
return 0;
}
Expand All @@ -308,7 +309,7 @@ public int cleanupOrphanedMetadata() {
try {
JSONObject metadata = app.loadJSONObject(file.getAbsolutePath());
String projectId = metadata.getString("project_id", "");
File projectDir = new File("project/" + projectId);
File projectDir = QuantumBrush.appFile("project/" + projectId);

// Only delete if project directory truly doesn't exist
if (!projectDir.exists()) {
Expand Down
Loading