Skip to content

PhotoLencer #192

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
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
83 changes: 83 additions & 0 deletions submissions/securePhotos/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# PhotoLancer
***PhotoLancer*** enhances your browsing experience by unblurring and displaying high-quality images in modern galleries on platforms like **Google Photos**. 🚀

---

### 📸 **PhotoLancer – Unblur & Enhance Image Galleries**
> **A modern Chrome extension that unblurs images and enhances gallery views on Google Photos and Facebook.**


---

## 🚀 **Features**
✅ **Unblur Images Instantly** – View high-quality images effortlessly.
✅ **Smart Positioning** – The preview modal appears in the best position to avoid cropping.
✅ **Supports Google Photos & Facebook** – Works with dynamically loaded images.
✅ **Beautiful Glass UI** – A sleek, modern design with smooth animations.
✅ **Optimized for Performance** – Runs efficiently without slowing down browsing.

---

## 🛠 **Installation Guide**
### **🔹 Manual Installation (For Developers & Testing)**
1. **Download the repository**
```sh
https://github.com/0mahi11/PhotoLancer.git
```
2. **Open Chrome** and go to `chrome://extensions/`.
3. **Enable Developer Mode** (top right corner).
4. **Click "Load Unpacked"** and select the extension folder.
5. **Done!** Your extension is now running! 🎉

### **🔹 Chrome Web Store (Coming Soon)**
Once published, you’ll be able to install it from the [Chrome Web Store](#).

---

## 📖 **How It Works**
1. **Hover over a blurred image** – The extension detects it automatically.
2. **A high-quality preview appears** – Unblurred and well-positioned.
3. **Move away to hide** – The modal smoothly disappears.

---

## 🖥 **Supported Platforms**
✅ **Google Photos**
✅ **Facebook** (Profile pictures, cover images, and more)
✅ **More platforms coming soon!**

---

## 💻 **Technical Details**
### **🔹 File Structure**
```
📂 PhotoLancer/
├── 📜 manifest.json # Chrome extension configuration
├── 📜 content.js # Core script handling image unblurring
├── 🎨 styles.css # Modern UI styles
├── 📜 README.md # This documentation
└── 📂 icons/ # Extension icons (optional)
```

### **🔹 Technologies Used**
- **JavaScript** – For handling dynamic images & DOM updates
- **CSS** – Glass UI with smooth animations
- **MutationObserver** – Detects dynamically loaded images (e.g., Facebook)

---

## 🛠 **Contributing**
We welcome contributions! 🚀
1. Fork the repo
2. Create a new branch (`git checkout -b feature-name`)
3. Make your changes
4. Push and submit a PR

---

## ⚖ **License**
**PhotoLancer** is **open-source** under the **MIT License**.

---

🔥 **Enjoy browsing without blur!** 🚀
117 changes: 117 additions & 0 deletions submissions/securePhotos/content.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
(function () {
const modal = document.createElement("div");
modal.id = "unblur-modal";
Object.assign(modal.style, {
position: "absolute",
display: "none",
zIndex: "10000",
padding: "15px",
background: "rgba(255, 255, 255, 0.95)", // Soft glass effect
boxShadow: "0 15px 40px rgba(0,0,0,0.3)",
backdropFilter: "blur(10px)",
borderRadius: "12px",
transition: "opacity 0.3s ease, transform 0.3s ease",
transform: "scale(0.9)",
overflow: "hidden",
display: "flex",
justifyContent: "center",
alignItems: "center",
border: "1px solid rgba(255, 255, 255, 0.2)",
});
document.body.appendChild(modal);

function getImageSource(target) {
// Standard sites (Google Images, etc.)
let child = target.querySelector("div.RY3tic[data-latest-bg]");
if (child) return child.getAttribute("data-latest-bg");

// Facebook images (supports newer DOM structure)
let fbImg = target.querySelector("img[src]");
if (fbImg) return fbImg.src;

return null;
}

function showModal(target) {
modal.innerHTML = "";
const imgSrc = getImageSource(target);

if (imgSrc) {
const img = document.createElement("img");
img.src = imgSrc;

Object.assign(img.style, {
filter: "none",
width: "100%",
height: "100%",
borderRadius: "8px",
display: "block",
objectFit: "cover", // Ensures image fills the modal
maxWidth: "100%",
maxHeight: "100%",
boxShadow: "0 6px 20px rgba(0,0,0,0.2)",
});

modal.appendChild(img);

// Get target image size
const rect = target.getBoundingClientRect();
const imgWidth = rect.width;
const imgHeight = rect.height;

// Set modal size relative to the image
const modalWidth = Math.min(imgWidth * 1.2, 600); // Scale but cap at 600px
const modalHeight = Math.min(imgHeight * 1.2, 500); // Scale but cap at 500px

const offset = 20;
let left = rect.left + window.scrollX + rect.width / 2 - modalWidth / 2;
let top = rect.top + window.scrollY + rect.height + offset;

// If not enough space below, move above
if (top + modalHeight > window.innerHeight + window.scrollY) {
top = rect.top + window.scrollY - modalHeight - offset;
}

// Ensure modal stays within viewport
if (left + modalWidth > window.innerWidth) {
left = window.innerWidth - modalWidth - 10;
}
if (left < 10) {
left = 10;
}

// Apply position & size
modal.style.width = `${modalWidth}px`;
modal.style.height = `${modalHeight}px`;
modal.style.left = `${left}px`;
modal.style.top = `${top}px`;
modal.style.display = "flex";
modal.style.opacity = "1";
modal.style.transform = "scale(1)";
}
}

function hideModal() {
modal.style.opacity = "0";
modal.style.transform = "scale(0.9)";
setTimeout(() => {
modal.style.display = "none";
}, 300);
}

function addGalleryListeners() {
const galleryItems = document.querySelectorAll("div.rtIMgb, div.x1i10hfl"); // Google & Facebook images
galleryItems.forEach((item) => {
if (!item.dataset.hoverListenerAdded) {
item.addEventListener("mouseenter", () => showModal(item));
item.addEventListener("mouseleave", hideModal);
item.dataset.hoverListenerAdded = "true";
}
});
}

addGalleryListeners();

const observer = new MutationObserver(addGalleryListeners);
observer.observe(document.body, { childList: true, subtree: true });
})();
Binary file added submissions/securePhotos/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions submissions/securePhotos/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"manifest_version": 3,
"name": "PhotoLancer",
"description": "Secure your photos as blur and enjoy",
"version": "1.0",
"icons": {
"128": "logo.png"
},
"content_scripts": [
{
"matches": ["https://photos.google.com/*"],
"js": ["content.js"],
"css": ["styles.css"]
}
],
"permissions": []
}
23 changes: 23 additions & 0 deletions submissions/securePhotos/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/* Apply blur to the gallery container tag instead of an img tag */
div.rtIMgb {
filter: blur(5px) !important;
transition: filter 0.3s ease;
}

/* Modern Gallery Layout: style the main photo grid as a responsive grid.
This assumes the gallery container uses role="grid" */
div[role="grid"] {
display: grid !important;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 15px;
padding: 15px;
}

/* Optional: give each gallery item a modern “card” look */
div[role="grid"] > div {
background: #fff;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}