{"id":4071,"date":"2025-11-08T07:59:11","date_gmt":"2025-11-08T07:59:11","guid":{"rendered":"https:\/\/stellarkiwii.com\/index.php\/user\/"},"modified":"2025-11-11T08:27:13","modified_gmt":"2025-11-11T08:27:13","slug":"user","status":"publish","type":"page","link":"https:\/\/stellarkiwii.com\/index.php\/user\/","title":{"rendered":"User"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"4071\" class=\"elementor elementor-4071\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"aux-parallax-section elementor-element elementor-element-755520cb e-flex e-con-boxed e-con e-parent\" data-id=\"755520cb\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-5261ea09 elementor-widget elementor-widget-shortcode\" data-id=\"5261ea09\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"shortcode.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-shortcode\">[ultimatemember form_id=\"3645\"]<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"aux-parallax-section elementor-element elementor-element-3c6f035 e-flex e-con-boxed e-con e-parent\" data-id=\"3c6f035\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-a3e746b elementor-widget elementor-widget-html\" data-id=\"a3e746b\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<!-- \ud83d\uddbc\ufe0f Visitor Upload 3D Gallery -->\r\n<div class=\"upload-section\">\r\n  <label for=\"upload\" class=\"upload-btn\">\ud83d\udcf8 Upload Your Images<\/label>\r\n  <input type=\"file\" id=\"upload\" multiple accept=\"image\/*\">\r\n<\/div>\r\n\r\n<div class=\"gallery-wrapper\">\r\n  <div class=\"gallery-3d\" id=\"preview\"><\/div>\r\n<\/div>\r\n\r\n<script>\r\nconst input = document.getElementById('upload');\r\nconst preview = document.getElementById('preview');\r\n\r\ninput.addEventListener('change', () => {\r\n  const files = Array.from(input.files);\r\n  preview.innerHTML = ''; \/\/ Clear previous images\r\n  if (files.length === 0) return;\r\n\r\n  const count = Math.min(files.length, 12); \/\/ limit to 12 images\r\n  const angleStep = 360 \/ count;\r\n\r\n  files.slice(0, count).forEach((file, i) => {\r\n    const reader = new FileReader();\r\n    reader.onload = e => {\r\n      const fig = document.createElement('figure');\r\n      fig.innerHTML = `<img decoding=\"async\" src=\"${e.target.result}\" alt=\"Uploaded image\">`;\r\n      fig.style.transform = `rotateY(${i * angleStep}deg) translateZ(400px)`;\r\n      preview.appendChild(fig);\r\n    };\r\n    reader.readAsDataURL(file);\r\n  });\r\n});\r\n<\/script>\r\n\r\n\r\n\r\n\r\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"aux-parallax-section elementor-element elementor-element-aa42fd5 e-flex e-con-boxed e-con e-parent\" data-id=\"aa42fd5\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-5e41853 elementor-widget elementor-widget-html\" data-id=\"5e41853\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div style=\"text-align:center; padding:25px;\">\r\n  <h2>\ud83d\udc8c Vintage Postcard Maker<\/h2>\r\n  <p>Upload your photo, add your message, and make it look like an old postcard!<\/p>\r\n\r\n  <input type=\"file\" id=\"photoInput\" accept=\"image\/*\" style=\"margin:10px 0;\">\r\n  \r\n  <div id=\"preview\" style=\"margin-top:20px; position:relative; display:inline-block;\">\r\n    <canvas id=\"canvas\" style=\"display:none; border-radius:12px; background:#f4f1e8;\"><\/canvas>\r\n    <div id=\"grainOverlay\"><\/div>\r\n  <\/div>\r\n\r\n  <div id=\"controls\" style=\"margin-top:20px; display:none;\">\r\n    <label for=\"captionText\">Write your message:<\/label><br>\r\n    <input type=\"text\" id=\"captionText\" placeholder=\"Greetings from the past...\" \r\n           style=\"padding:8px; width:80%; max-width:400px; font-family:'Cedarville Cursive', cursive; margin-top:8px; border-radius:6px; border:1px solid #ccc;\">\r\n    <br><br>\r\n    <label for=\"intensityRange\">Vintage Intensity:<\/label><br>\r\n    <input type=\"range\" id=\"intensityRange\" min=\"0\" max=\"100\" value=\"70\" style=\"width:250px;\">\r\n    <br>\r\n    <button id=\"downloadBtn\" style=\"margin-top:15px;\">Download Postcard<\/button>\r\n  <\/div>\r\n<\/div>\r\n\r\n<script>\r\ndocument.addEventListener(\"DOMContentLoaded\", function () {\r\n  const input = document.getElementById(\"photoInput\");\r\n  const canvas = document.getElementById(\"canvas\");\r\n  const ctx = canvas.getContext(\"2d\");\r\n  const controls = document.getElementById(\"controls\");\r\n  const captionInput = document.getElementById(\"captionText\");\r\n  const intensityRange = document.getElementById(\"intensityRange\");\r\n  const downloadBtn = document.getElementById(\"downloadBtn\");\r\n  const grainOverlay = document.getElementById(\"grainOverlay\");\r\n\r\n  let originalImageData;\r\n  let img;\r\n\r\n  input.addEventListener(\"change\", (e) => {\r\n    const file = e.target.files[0];\r\n    if (!file) return;\r\n    const reader = new FileReader();\r\n    reader.onload = (event) => {\r\n      img = new Image();\r\n      img.onload = () => {\r\n        const ratio = img.width \/ img.height;\r\n        const targetWidth = 800;\r\n        const targetHeight = targetWidth \/ ratio;\r\n        canvas.width = targetWidth;\r\n        canvas.height = targetHeight + 80; \/\/ space for frame caption\r\n\r\n        \/\/ Draw the base photo\r\n        ctx.fillStyle = \"#f4f1e8\";\r\n        ctx.fillRect(0, 0, canvas.width, canvas.height);\r\n        ctx.drawImage(img, 20, 20, canvas.width - 40, targetHeight - 40);\r\n\r\n        \/\/ Store original data for filter adjustments\r\n        originalImageData = ctx.getImageData(0, 0, canvas.width, targetHeight);\r\n        applyVintageEffect(0.7);\r\n\r\n        \/\/ Draw border frame\r\n        ctx.lineWidth = 8;\r\n        ctx.strokeStyle = \"#d8cfc4\";\r\n        ctx.strokeRect(10, 10, canvas.width - 20, targetHeight - 20);\r\n\r\n        canvas.style.display = \"block\";\r\n        controls.style.display = \"block\";\r\n        grainOverlay.style.display = \"block\";\r\n\r\n        drawCaption();\r\n      };\r\n      img.src = event.target.result;\r\n    };\r\n    reader.readAsDataURL(file);\r\n  });\r\n\r\n  intensityRange.addEventListener(\"input\", () => {\r\n    const intensity = intensityRange.value \/ 100;\r\n    applyVintageEffect(intensity);\r\n    drawCaption();\r\n  });\r\n\r\n  captionInput.addEventListener(\"input\", drawCaption);\r\n\r\n  function applyVintageEffect(intensity) {\r\n    const imageData = new ImageData(\r\n      new Uint8ClampedArray(originalImageData.data),\r\n      originalImageData.width,\r\n      originalImageData.height\r\n    );\r\n    const data = imageData.data;\r\n    for (let i = 0; i < data.length; i += 4) {\r\n      const r = data[i], g = data[i + 1], b = data[i + 2];\r\n      data[i]     = (r * (0.393 + 0.4*intensity)) + (g * (0.769 - 0.4*intensity)) + (b * (0.189 - 0.2*intensity));\r\n      data[i + 1] = (r * (0.349 - 0.2*intensity)) + (g * (0.686 + 0.2*intensity)) + (b * (0.168 - 0.1*intensity));\r\n      data[i + 2] = (r * (0.272 - 0.1*intensity)) + (g * (0.534 - 0.1*intensity)) + (b * (0.131 + 0.4*intensity));\r\n    }\r\n    ctx.putImageData(imageData, 0, 0);\r\n  }\r\n\r\n  function drawCaption() {\r\n    if (!img) return;\r\n    \/\/ redraw base\r\n    const ratio = img.width \/ img.height;\r\n    const targetWidth = 800;\r\n    const targetHeight = targetWidth \/ ratio;\r\n    ctx.fillStyle = \"#f4f1e8\";\r\n    ctx.fillRect(0, 0, canvas.width, canvas.height);\r\n    ctx.drawImage(img, 20, 20, canvas.width - 40, targetHeight - 40);\r\n    ctx.lineWidth = 8;\r\n    ctx.strokeStyle = \"#d8cfc4\";\r\n    ctx.strokeRect(10, 10, canvas.width - 20, targetHeight - 20);\r\n\r\n    \/\/ caption text\r\n    ctx.font = \"36px 'Cedarville Cursive', cursive\";\r\n    ctx.fillStyle = \"rgba(60,40,20,0.9)\";\r\n    ctx.textAlign = \"center\";\r\n    ctx.fillText(captionInput.value || \"Greetings from the past...\", canvas.width \/ 2, targetHeight + 50);\r\n  }\r\n\r\n  downloadBtn.addEventListener(\"click\", () => {\r\n    const link = document.createElement(\"a\");\r\n    link.download = \"vintage-postcard.png\";\r\n    link.href = canvas.toDataURL(\"image\/png\");\r\n    link.click();\r\n  });\r\n});\r\n<\/script>\r\n\r\n<style>\r\n@import url('https:\/\/fonts.googleapis.com\/css2?family=Cedarville+Cursive&display=swap');\r\n\r\n#canvas {\r\n  filter: contrast(1.05) brightness(0.95) saturate(0.85)\r\n          drop-shadow(0 6px 15px rgba(0,0,0,0.25));\r\n  animation: fadeIn 1s ease;\r\n  border-radius: 12px;\r\n}\r\n\r\n\/* Film grain texture *\/\r\n#grainOverlay {\r\n  pointer-events: none;\r\n  display: none;\r\n  position: absolute;\r\n  top: 0; left: 0;\r\n  width: 100%; height: 100%;\r\n  background-image: url('https:\/\/upload.wikimedia.org\/wikipedia\/commons\/7\/7a\/Film_grain_overlay.png');\r\n  background-size: cover;\r\n  opacity: 0.15;\r\n  mix-blend-mode: overlay;\r\n  border-radius: 12px;\r\n}\r\n\r\n\/* Subtle vignette *\/\r\n#preview::after {\r\n  content: \"\";\r\n  position: absolute;\r\n  top: 0; left: 0;\r\n  width: 100%; height: 100%;\r\n  border-radius: 12px;\r\n  box-shadow: inset 0 0 150px rgba(0,0,0,0.45);\r\n  pointer-events: none;\r\n}\r\n\r\n@keyframes fadeIn {\r\n  from { opacity: 0; transform: scale(0.97); }\r\n  to   { opacity: 1; transform: scale(1); }\r\n}\r\n\r\n\/* Button styling *\/\r\nbutton {\r\n  background: #704214;\r\n  color: #fff;\r\n  border: none;\r\n  border-radius: 5px;\r\n  padding: 10px 18px;\r\n  cursor: pointer;\r\n  font-weight: bold;\r\n}\r\nbutton:hover {\r\n  background: #8a5c2d;\r\n}\r\n<\/style>\r\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>[ultimatemember form_id=&#8221;3645&#8243;] \ud83d\udcf8 Upload Your Images \ud83d\udc8c Vintage Postcard Maker Upload your photo, add your message, and make it look like an old postcard! Write your message: Vintage Intensity: Download Postcard<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-4071","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/stellarkiwii.com\/index.php\/wp-json\/wp\/v2\/pages\/4071","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/stellarkiwii.com\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/stellarkiwii.com\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/stellarkiwii.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/stellarkiwii.com\/index.php\/wp-json\/wp\/v2\/comments?post=4071"}],"version-history":[{"count":39,"href":"https:\/\/stellarkiwii.com\/index.php\/wp-json\/wp\/v2\/pages\/4071\/revisions"}],"predecessor-version":[{"id":4126,"href":"https:\/\/stellarkiwii.com\/index.php\/wp-json\/wp\/v2\/pages\/4071\/revisions\/4126"}],"wp:attachment":[{"href":"https:\/\/stellarkiwii.com\/index.php\/wp-json\/wp\/v2\/media?parent=4071"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}