{"id":856149,"date":"2026-05-23T21:12:52","date_gmt":"2026-05-23T21:12:52","guid":{"rendered":"https:\/\/elektrobox.ch\/?page_id=856149"},"modified":"2026-06-03T19:25:18","modified_gmt":"2026-06-03T19:25:18","slug":"matrix-picture-frame","status":"publish","type":"page","link":"https:\/\/elektrobox.ch\/index.php\/matrix-picture-frame\/","title":{"rendered":"LED Matrix Picture Frame"},"content":{"rendered":"\n<style data-wp-block-html=\"css\">\n\/* =========================================================\n   ElektroBox Project Page CSS\n   Shared layout for all project pages\n   Matches the ElektroClock restructured HTML form\n   Paste once into Appearance -> Customize -> Additional CSS\n   ========================================================= *\/\n\n.ebox-project-page,\n.ebox-project-page *,\n.ebox-project-page *::before,\n.ebox-project-page *::after {\n  box-sizing: border-box;\n}\n\n.ebox-project-page {\n  width: 100%;\n  max-width: 1080px;\n  margin: 0 auto;\n  padding: 0 20px;\n  font-family: inherit;\n  line-height: 1.7;\n  color: #1f2933;\n  overflow-x: hidden;\n}\n\n.ebox-project-page h1,\n.ebox-project-page h2,\n.ebox-project-page h3 {\n  color: #111827;\n  line-height: 1.25;\n  overflow-wrap: break-word;\n}\n\n.ebox-project-page h1 {\n  margin: 0 0 16px;\n  font-size: clamp(2.15rem, 4.5vw, 3.5rem);\n  letter-spacing: -0.035em;\n}\n\n.ebox-project-page h2 {\n  margin: 52px 0 16px;\n  padding-bottom: 8px;\n  border-bottom: 2px solid #e5e7eb;\n  font-size: clamp(1.45rem, 2.6vw, 2.05rem);\n}\n\n.ebox-project-page h3 {\n  margin: 28px 0 10px;\n  font-size: 1.2rem;\n}\n\n.ebox-project-page p {\n  margin: 0 0 18px;\n}\n\n.ebox-project-page ul,\n.ebox-project-page ol {\n  margin: 0 0 20px 22px;\n  padding: 0;\n}\n\n.ebox-project-page li {\n  margin: 6px 0;\n}\n\n.ebox-project-page code {\n  padding: 0.08em 0.28em;\n  border-radius: 6px;\n  background: #eef2f7;\n  color: #111827;\n  font-family: Consolas, Monaco, \"Courier New\", monospace;\n  font-size: 0.92em;\n}\n\n\/* Hero *\/\n\n.ebox-hero {\n  margin: 28px 0 34px;\n  padding: clamp(24px, 4vw, 44px);\n  border: 1px solid #e5e7eb;\n  border-radius: 22px;\n  background: linear-gradient(135deg, #f8fafc 0%, #ffffff 55%, #eef6ff 100%);\n  box-shadow: 0 10px 30px rgba(15, 23, 42, 0.08);\n}\n\n.ebox-hero-with-image {\n  display: grid;\n  grid-template-columns: minmax(0, 1.35fr) minmax(260px, 0.9fr);\n  align-items: center;\n  gap: 32px;\n}\n\n.ebox-hero-text {\n  min-width: 0;\n}\n\n.ebox-hero-label {\n  display: inline-block;\n  margin-bottom: 14px;\n  padding: 6px 14px;\n  border-radius: 999px;\n  background: #e0f2fe;\n  color: #075985;\n  font-size: 0.92rem;\n  font-weight: 800;\n}\n\n.ebox-hero-image {\n  min-width: 0;\n  width: 100%;\n}\n\n.ebox-hero-image img {\n  display: block;\n  width: 100%;\n  height: auto;\n  border-radius: 18px;\n  object-fit: cover;\n  box-shadow: 0 10px 28px rgba(15, 23, 42, 0.14);\n}\n\n\/* Video *\/\n\n.ebox-video-section {\n  margin: 42px 0 46px;\n}\n\n.ebox-video-card,\n.ebox-video-box {\n  margin: 20px 0 12px;\n  padding: clamp(12px, 2vw, 18px);\n  border: 1px solid #dce3ea;\n  border-radius: 22px;\n  background: #f8fafc;\n  box-shadow: 0 8px 24px rgba(15, 23, 42, 0.06);\n}\n\n.ebox-video-frame,\n.ebox-video-wrapper {\n  position: relative;\n  width: 100%;\n  aspect-ratio: 16 \/ 9;\n  overflow: hidden;\n  border-radius: 18px;\n  background: #0f172a;\n}\n\n.ebox-video-frame iframe,\n.ebox-video-wrapper iframe {\n  position: absolute;\n  inset: 0;\n  display: block;\n  width: 100%;\n  height: 100%;\n  border: 0;\n}\n\n\/* Cards and grids *\/\n\n.ebox-card-grid,\n.ebox-summary-grid,\n.ebox-check-grid {\n  display: grid;\n  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));\n  gap: 16px;\n  margin: 20px 0 28px;\n}\n\n.ebox-info-card,\n.ebox-check-card {\n  min-width: 0;\n  padding: 18px;\n  border: 1px solid #e5e7eb;\n  border-radius: 16px;\n  background: #ffffff;\n  box-shadow: 0 6px 18px rgba(15, 23, 42, 0.06);\n}\n\n.ebox-info-card strong,\n.ebox-check-card strong {\n  display: block;\n  margin-bottom: 6px;\n  color: #111827;\n}\n\n\/* Sections and images *\/\n\n.ebox-step {\n  margin: 24px 0;\n  padding: clamp(18px, 3vw, 26px);\n  border: 1px solid #e5e7eb;\n  border-radius: 18px;\n  background: #ffffff;\n  box-shadow: 0 8px 22px rgba(15, 23, 42, 0.05);\n}\n\n.ebox-step h2 {\n  margin-top: 0;\n}\n\n.ebox-section-grid {\n  display: grid;\n  grid-template-columns: minmax(0, 1.1fr) minmax(260px, 0.9fr);\n  gap: 28px;\n  align-items: center;\n  margin: 20px 0 30px;\n}\n\n.ebox-image-card,\n.ebox-svg-preview {\n  min-width: 0;\n  margin: 28px 0 34px;\n  padding: clamp(12px, 2vw, 20px);\n  border: 1px solid #dce3ea;\n  border-radius: 18px;\n  background: #f8fafc;\n  box-shadow: 0 8px 24px rgba(15, 23, 42, 0.06);\n  overflow: hidden;\n  text-align: center;\n}\n\n.ebox-image-card img,\n.ebox-svg-preview img {\n  display: block;\n  width: 100%;\n  max-width: 100%;\n  height: auto;\n  max-height: 72vh;\n  margin: 0 auto;\n  border-radius: 14px;\n  object-fit: contain;\n}\n\n.ebox-image-card .ebox-img-tall {\n  width: auto;\n  max-height: 520px;\n}\n\n.ebox-caption,\n.ebox-svg-caption {\n  margin: 12px 0 0;\n  color: #475569;\n  font-size: 0.95rem;\n  text-align: center;\n}\n\n\/* Notes *\/\n\n.ebox-note,\n.ebox-warning {\n  margin: 22px 0;\n  padding: 18px 20px;\n  border-radius: 12px;\n}\n\n.ebox-note {\n  border-left: 5px solid #0ea5e9;\n  background: #f0f9ff;\n}\n\n.ebox-warning {\n  border-left: 5px solid #f97316;\n  background: #fff7ed;\n}\n\n\/* Flow *\/\n\n.ebox-flow {\n  display: grid;\n  gap: 10px;\n  margin: 20px 0 26px;\n}\n\n.ebox-flow-step {\n  padding: 14px 16px;\n  border-radius: 14px;\n  background: #111827;\n  color: #ffffff;\n  font-weight: 700;\n}\n\n\/* Collapsible details *\/\n\n.ebox-details {\n  margin: 24px 0 34px;\n  border: 1px solid #e5e7eb;\n  border-radius: 18px;\n  background: #ffffff;\n  box-shadow: 0 8px 24px rgba(15, 23, 42, 0.06);\n  overflow: hidden;\n}\n\n.ebox-details summary {\n  cursor: pointer;\n  padding: 16px 18px;\n  color: #111827;\n  font-weight: 800;\n  background: #f8fafc;\n  border-bottom: 1px solid #e5e7eb;\n}\n\n.ebox-details-content {\n  padding: 18px;\n}\n\n\/* Code *\/\n\n.ebox-code-block {\n  margin: 20px 0 26px;\n  border: 1px solid #d1d5db;\n  border-radius: 16px;\n  overflow: hidden;\n  background: #0b1020;\n  box-shadow: 0 10px 28px rgba(15, 23, 42, 0.16);\n}\n\n.ebox-code-header {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  gap: 12px;\n  padding: 12px 14px;\n  background: #111827;\n  color: #ffffff;\n}\n\n.ebox-code-title {\n  font-size: 0.95rem;\n  font-weight: 800;\n  word-break: break-word;\n}\n\n.ebox-copy-button {\n  appearance: none;\n  border: 0;\n  border-radius: 999px;\n  padding: 8px 13px;\n  background: #dbeafe;\n  color: #0f172a;\n  cursor: pointer;\n  font-weight: 800;\n  font-size: 0.85rem;\n  white-space: nowrap;\n}\n\n.ebox-copy-button:hover {\n  background: #bfdbfe;\n}\n\n.ebox-code-textarea {\n  display: block;\n  width: 100%;\n  min-height: 360px;\n  max-height: 620px;\n  padding: 18px;\n  border: 0;\n  outline: none;\n  resize: vertical;\n  background: #0b1020;\n  color: #e5e7eb;\n  font-family: Consolas, Monaco, \"Courier New\", monospace;\n  font-size: 13px;\n  line-height: 1.55;\n  white-space: pre;\n  overflow: auto;\n}\n\n.ebox-code-textarea.small {\n  min-height: 190px;\n}\n\n.ebox-code-textarea.medium {\n  min-height: 300px;\n}\n\n.ebox-code-textarea.large {\n  min-height: 520px;\n}\n\n.ebox-small-code-box {\n  margin: 18px 0 28px;\n}\n\n.ebox-small-code {\n  width: 100%;\n  min-height: 90px;\n  max-height: 500px;\n  height: 220px;\n  padding: 16px;\n  resize: vertical;\n  overflow: auto;\n  border: 1px solid #334155;\n  border-radius: 12px;\n  background-color: #111827;\n  color: #f1f5f9;\n  font-family: Consolas, Monaco, \"Courier New\", monospace;\n  font-size: 13px;\n  line-height: 1.45;\n  white-space: pre;\n  box-sizing: border-box;\n}\n\n\/* Tables, galleries, FAQ *\/\n\n.ebox-table {\n  width: 100%;\n  border-collapse: collapse;\n  margin: 18px 0 28px;\n}\n\n.ebox-table th,\n.ebox-table td {\n  border: 1px solid #d1d5db;\n  padding: 10px;\n  text-align: left;\n  vertical-align: top;\n}\n\n.ebox-table th {\n  background: #f2f2f2;\n}\n\n.ebox-gallery {\n  display: grid;\n  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));\n  gap: 18px;\n  margin: 22px 0 32px;\n}\n\n.ebox-faq-list {\n  display: grid;\n  gap: 14px;\n  margin: 20px 0 34px;\n}\n\n.ebox-faq-list details {\n  border: 1px solid #e5e7eb;\n  border-radius: 16px;\n  background: #ffffff;\n  box-shadow: 0 6px 18px rgba(15, 23, 42, 0.05);\n  overflow: hidden;\n}\n\n.ebox-faq-list summary {\n  cursor: pointer;\n  padding: 16px 18px;\n  color: #111827;\n  font-weight: 800;\n}\n\n.ebox-faq-content {\n  padding: 0 18px 18px;\n  color: #4b5563;\n}\n\n\/* Links and final box *\/\n\n.ebox-download-link,\n.ebox-schematic-link {\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n  margin: 10px 0 18px;\n  padding: 10px 16px;\n  border-radius: 999px;\n  background: #dbe8ee;\n  color: #1f3a46;\n  font-size: 0.92rem;\n  font-weight: 800;\n  text-decoration: none;\n}\n\n.ebox-download-link:hover,\n.ebox-schematic-link:hover {\n  background: #c8dce5;\n  color: #132a34;\n}\n\n.ebox-final-box {\n  margin: 42px 0 24px;\n  padding: clamp(20px, 3vw, 28px);\n  border: 1px solid #e5e7eb;\n  border-radius: 20px;\n  background: #f8fafc;\n}\n\n\/* Optional project-specific accent hooks *\/\n\n.ebox-project-page--elektroclock .ebox-hero-label,\n.ebox-project-page--matrix .ebox-hero-label {\n  background: #e0f2fe;\n  color: #075985;\n}\n\n.ebox-project-page--lightbox .ebox-hero-label {\n  background: #fef3c7;\n  color: #92400e;\n}\n\n.ebox-project-page--rgb .ebox-hero-label {\n  background: #fae8ff;\n  color: #86198f;\n}\n\n.ebox-project-page--pcmon .ebox-hero-label {\n  background: #dcfce7;\n  color: #166534;\n}\n\n.ebox-project-page--ttm .ebox-hero-label {\n  background: #ffedd5;\n  color: #9a3412;\n}\n\n\/* Responsive *\/\n\n@media (max-width: 820px) {\n  .ebox-hero-with-image,\n  .ebox-section-grid {\n    grid-template-columns: 1fr;\n  }\n\n  .ebox-hero-image {\n    margin-top: 8px;\n  }\n}\n\n@media (max-width: 640px) {\n  .ebox-project-page {\n    padding: 0 16px;\n  }\n\n  .ebox-hero {\n    padding: 22px 18px;\n  }\n\n  .ebox-code-header {\n    flex-direction: column;\n    align-items: flex-start;\n  }\n\n  .ebox-copy-button {\n    width: 100%;\n  }\n\n  .ebox-code-textarea {\n    min-height: 320px;\n    font-size: 12.5px;\n  }\n\n  .ebox-image-card .ebox-img-tall {\n    width: 100%;\n    max-height: none;\n  }\n}\n<\/style>\n\n\n\n<div class=\"ebox-project-page ebox-project-page--matrix\">\n\n  <section class=\"ebox-hero ebox-hero-with-image\">\n    <div class=\"ebox-hero-text\">\n      <span class=\"ebox-hero-label\">ESP32 RGB Matrix Project<\/span>\n      <h1>DIY LED Matrix Picture Frame<\/h1>\n      <p>\n        In this ElektroBox project, I build a small LED matrix picture frame using an ESP32 and two\n        chained RGB LED matrix panels.\n      <\/p>\n      <p>\n        The picture frame displays a custom 64 \u00d7 64 pixel image stored as an RGB565 bitmap. The ESP32\n        reads the bitmap data from program memory and draws it across both matrix panels.\n      <\/p>\n    <\/div>\n\n    <div class=\"ebox-hero-image\">\n      <img decoding=\"async\" src=\"https:\/\/elektrobox.ch\/wp-content\/uploads\/2026\/05\/IMG_2602-scaled.jpg\" alt=\"DIY LED matrix picture frame with ESP32 and two RGB matrix panels\">\n    <\/div>\n  <\/section>\n\n  <h2>1. Project Idea<\/h2>\n\n  <p>\n    The idea for this project came from leftover parts from my ElektroClock build. While working with\n    LED matrix displays, I noticed that multiple panels can be chained together. This makes it possible\n    to create a larger display area and use it as a small pixel-art picture frame.\n  <\/p>\n\n  <div class=\"ebox-card-grid\">\n    <div class=\"ebox-info-card\"><strong>Main controller<\/strong>ESP32 development board.<\/div>\n    <div class=\"ebox-info-card\"><strong>Display<\/strong>Two chained 64 \u00d7 32 RGB HUB75 LED matrix panels.<\/div>\n    <div class=\"ebox-info-card\"><strong>Image format<\/strong>64 \u00d7 64 pixel RGB565 bitmap stored in program memory.<\/div>\n  <\/div>\n\n  <h2>2. Required Parts<\/h2>\n\n  <ul>\n    <li>ESP32 development board<\/li>\n    <li>Two RGB LED matrix panels<\/li>\n    <li>HUB75 ribbon cable or jumper wires<\/li>\n    <li>Stable 5 V power supply<\/li>\n    <li>Leftover PCB from the ElektroClock project or a prototype wiring setup<\/li>\n    <li>Jumper wires<\/li>\n    <li>3D-printed mounting plate<\/li>\n    <li>Prototype case or enclosure<\/li>\n    <li>Optional screws and spacers<\/li>\n  <\/ul>\n\n  <h2>3. How the System Works<\/h2>\n\n  <p>\n    The two matrix panels are chained together. The ESP32 controls the input of the first panel, and\n    the display data continues from the first panel to the second one. In the software, both physical\n    panels are handled as one virtual 64 \u00d7 64 pixel display.\n  <\/p>\n\n  <div class=\"ebox-flow\">\n    <div class=\"ebox-flow-step\">Image file \u2192 converted to 64 \u00d7 64 RGB565 bitmap<\/div>\n    <div class=\"ebox-flow-step\">Bitmap header file \u2192 added to the Arduino sketch folder<\/div>\n    <div class=\"ebox-flow-step\">ESP32 \u2192 sends the pixel data to the chained HUB75 panels<\/div>\n    <div class=\"ebox-flow-step\">Two 64 \u00d7 32 panels \u2192 displayed as one 64 \u00d7 64 picture frame<\/div>\n  <\/div>\n\n  <h2>4. Designing the Mount<\/h2>\n\n  <p>\n    To align both LED matrix panels correctly, I designed a simple mounting plate. The plate keeps both\n    displays in the correct position and makes the complete frame more stable.\n  <\/p>\n\n  <p>\n    First, I measured the mounting holes and outer dimensions of the LED matrix panels. Then I designed\n    the back plate and prepared it for 3D printing. The design is kept simple, so it is easy to print\n    and modify for different panel sizes.\n  <\/p>\n\n  <h2>5. Connecting the LED Matrix Panels<\/h2>\n\n  <p>\n    The LED matrix panels use the HUB75 interface. Several signal wires are required for the RGB channels,\n    row selection, latch, output enable, and clock signal.\n  <\/p>\n\n  <p>\n    In the final version, I reused a leftover PCB from the ElektroClock project. This keeps the wiring\n    cleaner and more reliable. For a first prototype, jumper wires can also be used.\n  <\/p>\n\n  <div class=\"ebox-warning\">\n    <strong>Important:<\/strong>\n    The output connector of the first panel must be connected to the input connector of the second panel.\n    The ESP32 only controls the first panel directly.\n  <\/div>\n\n  <details class=\"ebox-details\">\n    <summary>Pin overview<\/summary>\n    <div class=\"ebox-details-content\">\n      <div class=\"ebox-code-block\">\n        <div class=\"ebox-code-header\">\n          <span class=\"ebox-code-title\">ESP32 to HUB75 matrix wiring<\/span>\n          <button class=\"ebox-copy-button\" onclick=\"eboxCopyCode('matrix-pin-overview', this)\">Copy code<\/button>\n        <\/div>\n        <textarea id=\"matrix-pin-overview\" class=\"ebox-code-textarea small\" readonly=\"\">ESP32 to HUB75 panel wiring used in this sketch:\n\nR1  -&gt; GPIO 25\nG1  -&gt; GPIO 26\nB1  -&gt; GPIO 27\nR2  -&gt; GPIO 14\nG2  -&gt; GPIO 12\nB2  -&gt; GPIO 13\n\nA   -&gt; GPIO 23\nB   -&gt; GPIO 19\nC   -&gt; GPIO 5\nD   -&gt; GPIO 17\nE   -&gt; not used \/ -1\n\nLAT -&gt; GPIO 4\nOE  -&gt; GPIO 15\nCLK -&gt; GPIO 16\n\nPanel setup:\nTwo 64 x 32 RGB matrix panels\nStacked vertically\nVirtual display size: 64 x 64 px\nChain type: CHAIN_BOTTOM_LEFT_UP\n<\/textarea>\n      <\/div>\n    <\/div>\n  <\/details>\n\n  <h2>6. Image Conversion<\/h2>\n\n  <p>\n    The ESP32 sketch does not load PNG or JPG files directly. The image first has to be resized to\n    64 \u00d7 64 pixels and converted to RGB565. The Python converter below creates two files:\n    a <code>.h<\/code> header file for the Arduino sketch and a <code>.bin<\/code> file for testing or reuse.\n  <\/p>\n\n  <div class=\"ebox-note\">\n    <strong>Offline converter:<\/strong>\n    The Python script runs locally on your computer. It does not use Wi-Fi, sockets, requests, a web server,\n    or any internet connection. This makes it firewall-friendly and avoids unnecessary network permission prompts. The code block is displayed as plain copyable text and is not executed by the website.\n  <\/div>\n\n  <details class=\"ebox-details\">\n    <summary>Install required Python package<\/summary>\n    <div class=\"ebox-details-content\">\n      <div class=\"ebox-code-block\">\n        <div class=\"ebox-code-header\">\n          <span class=\"ebox-code-title\">Install Pillow<\/span>\n          <button class=\"ebox-copy-button\" onclick=\"eboxCopyCode('python-install-code', this)\">Copy code<\/button>\n        <\/div>\n        <textarea id=\"python-install-code\" class=\"ebox-code-textarea small\" readonly=\"\">pip install pillow<\/textarea>\n      <\/div>\n    <\/div>\n  <\/details>\n\n  <details class=\"ebox-details\">\n    <summary>Python image to RGB565 converter<\/summary>\n    <div class=\"ebox-details-content\">\n      <p>\n        Save this script as <code>image_to_rgb565_converter.py<\/code>, run it, select your image, and copy the\n        generated header file into the same folder as your Arduino sketch.\n      <\/p>\n\n      <div class=\"ebox-code-block\">\n        <div class=\"ebox-code-header\">\n          <span class=\"ebox-code-title\">image_to_rgb565_converter.py<\/span>\n          <button class=\"ebox-copy-button\" onclick=\"eboxCopyCode('rgb565-python-converter', this)\">Copy code<\/button>\n        <\/div>\n        <textarea id=\"rgb565-python-converter\" class=\"ebox-code-textarea large\" readonly=\"\">from __future__ import annotations\n\nfrom pathlib import Path\nimport re\nimport tkinter as tk\nfrom tkinter import filedialog, messagebox\n\nfrom PIL import Image, ImageOps\n\n\nWIDTH = 64\nHEIGHT = 64\n\n\ndef rgb888_to_rgb565(r: int, g: int, b: int) -&gt; int:\n    &#8220;&#8221;&#8221;\n    Convert RGB888 to RGB565:\n    RRRRRGGGGGGBBBBB\n    &#8220;&#8221;&#8221;\n    return ((r &amp; 0xF8) &lt;&lt; 8) | ((g &amp; 0xFC) &lt;&lt; 3) | (b &gt;&gt; 3)\n\n\ndef make_c_identifier(name: str) -&gt; str:\n    &#8220;&#8221;&#8221;\n    Create a safe C\/Arduino identifier from the image file name.\n    Example: &#8220;my picture.png&#8221; -&gt; &#8220;my_picture&#8221;\n    &#8220;&#8221;&#8221;\n    name = re.sub(r&#8221;\\W+&#8221;, &#8220;_&#8221;, name).strip(&#8220;_&#8221;)\n\n    if not name:\n        name = &#8220;bitmap&#8221;\n\n    if name[0].isdigit():\n        name = &#8220;_&#8221; + name\n\n    return name\n\n\ndef convert_image(input_path: str | Path, crop: bool = True) -&gt; tuple[Path, Path]:\n    &#8220;&#8221;&#8221;\n    Convert an image to:\n    &#8211; a 64&#215;64 RGB565 Arduino header file\n    &#8211; a 64&#215;64 RGB565 binary file\n\n    This script is offline-only. It does not open a socket, start a server,\n    download anything, or contact the internet, so it should not trigger a\n    firewall network prompt.\n    &#8220;&#8221;&#8221;\n    input_path = Path(input_path)\n\n    output_name = make_c_identifier(input_path.stem) + &#8220;_64x64&#8221;\n    header_path = input_path.with_name(output_name + &#8220;.h&#8221;)\n    bin_path = input_path.with_name(output_name + &#8220;.bin&#8221;)\n\n    img = Image.open(input_path).convert(&#8220;RGBA&#8221;)\n\n    # Replace transparency with black background\n    background = Image.new(&#8220;RGBA&#8221;, img.size, (0, 0, 0, 255))\n    img = Image.alpha_composite(background, img).convert(&#8220;RGB&#8221;)\n\n    # Resize image to 64&#215;64\n    if crop:\n        img = ImageOps.fit(\n            img,\n            (WIDTH, HEIGHT),\n            method=Image.Resampling.LANCZOS\n        )\n    else:\n        img = ImageOps.pad(\n            img,\n            (WIDTH, HEIGHT),\n            method=Image.Resampling.LANCZOS,\n            color=(0, 0, 0)\n        )\n\n    pixels_rgb565: list[int] = []\n\n    for y in range(HEIGHT):\n        for x in range(WIDTH):\n            r, g, b = img.getpixel((x, y))\n            pixels_rgb565.append(rgb888_to_rgb565(r, g, b))\n\n    # Save binary file, little-endian RGB565\n    bin_data = bytearray()\n    for value in pixels_rgb565:\n        bin_data.extend(value.to_bytes(2, byteorder=&#8221;little&#8221;))\n\n    bin_path.write_bytes(bin_data)\n\n    # Save C \/ Arduino header file\n    lines: list[str] = []\n    lines.append(f&#8221;\/\/ Auto-generated from &#8216;{input_path.name}'&#8221;)\n    lines.append(f&#8221;\/\/ {WIDTH}x{HEIGHT} pixels, RGB565, row-major&#8221;)\n    lines.append(&#8220;#pragma once&#8221;)\n    lines.append(&#8220;#include &lt;stdint.h&gt;&#8221;)\n    lines.append(&#8220;#include &lt;pgmspace.h&gt;&#8221;)\n    lines.append(&#8220;&#8221;)\n    lines.append(f&#8221;const uint16_t {output_name}[{WIDTH * HEIGHT}] PROGMEM = {{&#8220;)\n\n    for i, value in enumerate(pixels_rgb565):\n        if i % 16 == 0:\n            lines.append(&#8221;  &#8220;)\n\n        lines[-1] += f&#8221;0x{value:04X}&#8221;\n\n        if i != len(pixels_rgb565) &#8211; 1:\n            lines[-1] += &#8220;, &#8221;\n\n        if i % 16 == 15:\n            continue\n\n    lines.append(&#8220;};&#8221;)\n    lines.append(&#8220;&#8221;)\n\n    header_path.write_text(&#8220;\\n&#8221;.join(lines), encoding=&#8221;utf-8&#8243;)\n\n    return header_path, bin_path\n\n\ndef select_file() -&gt; None:\n    file_path = filedialog.askopenfilename(\n        title=&#8221;Select image file&#8221;,\n        filetypes=[\n            (&#8220;Image files&#8221;, &#8220;*.png *.jpg *.jpeg *.bmp *.gif *.webp&#8221;),\n            (&#8220;All files&#8221;, &#8220;*.*&#8221;)\n        ]\n    )\n\n    if not file_path:\n        return\n\n    try:\n        crop = bool(crop_var.get())\n        header_path, bin_path = convert_image(file_path, crop=crop)\n\n        messagebox.showinfo(\n            &#8220;Conversion finished&#8221;,\n            &#8220;RGB565 bitmap created successfully!\\n\\n&#8221;\n            f&#8221;Header file:\\n{header_path}\\n\\n&#8221;\n            f&#8221;Binary file:\\n{bin_path}&#8221;\n        )\n\n    except Exception as exc:\n        messagebox.showerror(\n            &#8220;Error&#8221;,\n            f&#8221;Could not convert image:\\n\\n{exc}&#8221;\n        )\n\n\n# GUI setup\nroot = tk.Tk()\nroot.title(&#8220;Image to 64&#215;64 RGB565 Converter&#8221;)\nroot.geometry(&#8220;420&#215;220&#8243;)\nroot.resizable(False, False)\n\ntitle_label = tk.Label(\n    root,\n    text=&#8221;Image to 64&#215;64 RGB565 Converter&#8221;,\n    font=(&#8220;Arial&#8221;, 14, &#8220;bold&#8221;)\n)\ntitle_label.pack(pady=15)\n\ninfo_label = tk.Label(\n    root,\n    text=&#8221;Select an image file.\\nThe script creates a .h and .bin RGB565 bitmap.&#8221;,\n    font=(&#8220;Arial&#8221;, 10)\n)\ninfo_label.pack(pady=5)\n\ncrop_var = tk.BooleanVar(value=True)\n\ncrop_checkbox = tk.Checkbutton(\n    root,\n    text=&#8221;Crop image to fill 64&#215;64&#8243;,\n    variable=crop_var\n)\ncrop_checkbox.pack(pady=10)\n\nselect_button = tk.Button(\n    root,\n    text=&#8221;Select Image&#8221;,\n    command=select_file,\n    width=20,\n    height=2\n)\nselect_button.pack(pady=15)\n\nroot.mainloop()<\/textarea>\n      <\/div>\n    <\/div>\n  <\/details>\n\n  <details class=\"ebox-details\">\n    <summary>Generated bitmap header structure<\/summary>\n    <div class=\"ebox-details-content\">\n      <p>\n        The generated header file contains the 4096 RGB565 pixel values. The array name is based on the\n        image file name. If the generated array is called <code>mhf_64x64<\/code>, the Arduino sketch must use\n        the same name.\n      <\/p>\n\n      <div class=\"ebox-code-block\">\n        <div class=\"ebox-code-header\">\n          <span class=\"ebox-code-title\">Example RGB565 header structure<\/span>\n          <button class=\"ebox-copy-button\" onclick=\"eboxCopyCode('bitmap-header-example', this)\">Copy code<\/button>\n        <\/div>\n        <textarea id=\"bitmap-header-example\" class=\"ebox-code-textarea small\" readonly=\"\">\/\/ Auto-generated from &#8216;my_picture.png&#8217;\n\/\/ 64&#215;64 pixels, RGB565, row-major\n#pragma once\n#include &lt;stdint.h&gt;\n#include &lt;pgmspace.h&gt;\n\nconst uint16_t mhf_64x64[4096] PROGMEM = {\n  \/\/ 4096 RGB565 values are generated by the Python converter\n  \/\/ Example:\n  0x0000, 0x0000, 0xFFFF\n};<\/textarea>\n      <\/div>\n    <\/div>\n  <\/details>\n\n  <h2>7. Firmware Structure<\/h2>\n\n  <p>\n    The firmware initializes the matrix library, configures the HUB75 pins, creates the virtual 64 \u00d7 64\n    matrix, and draws the generated RGB565 bitmap from program memory.\n  <\/p>\n\n  <div class=\"ebox-warning\">\n    <strong>Name check:<\/strong>\n    The header file name and the array name must match your generated file. In the code below, the header is\n    <code>mhf_64x64.h<\/code> and the bitmap array is <code>mhf_64x64<\/code>. If your converter creates a different\n    name, change both places in the sketch.\n  <\/div>\n\n  <details class=\"ebox-details\" open=\"\">\n    <summary>Complete Arduino sketch<\/summary>\n    <div class=\"ebox-details-content\">\n      <div class=\"ebox-code-block\">\n        <div class=\"ebox-code-header\">\n          <span class=\"ebox-code-title\">ESP32 HUB75 LED matrix picture frame sketch<\/span>\n          <button class=\"ebox-copy-button\" onclick=\"eboxCopyCode('matrix-full-sketch', this)\">Copy code<\/button>\n        <\/div>\n        <textarea id=\"matrix-full-sketch\" class=\"ebox-code-textarea large\" readonly=\"\">#include &lt;Arduino.h&gt;\n#include &lt;ESP32-HUB75-MatrixPanel-I2S-DMA.h&gt;\n#include &lt;ESP32-VirtualMatrixPanel-I2S-DMA.h&gt;\n#include &#8220;mhf_64x64.h&#8221;\n\n\/*&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; Pins &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-*\/\n#define R1_PIN 25\n#define G1_PIN 26\n#define B1_PIN 27\n#define R2_PIN 14\n#define G2_PIN 12\n#define B2_PIN 13\n#define A_PIN 23\n#define B_PIN 19\n#define C_PIN 5\n#define D_PIN 17\n#define E_PIN -1\n#define LAT_PIN 4\n#define OE_PIN 15\n#define CLK_PIN 16\n\n\/*&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; Matrix config &#8212;&#8212;&#8212;&#8212;&#8212;-*\/\n#define PANEL_RES_X 64\n#define PANEL_RES_Y 32\n#define PANEL_CHAIN  2\n\n\/\/ Two 64&#215;32 panels stacked vertically = 64&#215;64\n#define NUM_ROWS 2\n#define NUM_COLS 1\n\n#define VIRTUAL_MATRIX_CHAIN_TYPE CHAIN_BOTTOM_LEFT_UP\n\nMatrixPanel_I2S_DMA *dma_display = nullptr;\nVirtualMatrixPanel  *vpanel = nullptr;\n\nHUB75_I2S_CFG mxconfig(PANEL_RES_X, PANEL_RES_Y, PANEL_CHAIN);\n\n\/*&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; Blit helper &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;*\/\nvoid drawRGB565Image_P(int x0, int y0, const uint16_t* img, int w, int h) {\n  for (int y = 0; y &lt; h; y++) {\n    for (int x = 0; x &lt; w; x++) {\n      uint16_t c = pgm_read_word(img + y * w + x);\n      vpanel-&gt;drawPixel(x0 + x, y0 + y, c);\n    }\n  }\n}\n\nvoid setup() {\n  Serial.begin(115200);\n  delay(150);\n\n  mxconfig.gpio.r1 = R1_PIN;\n  mxconfig.gpio.g1 = G1_PIN;\n  mxconfig.gpio.b1 = B1_PIN;\n  mxconfig.gpio.r2 = R2_PIN;\n  mxconfig.gpio.g2 = G2_PIN;\n  mxconfig.gpio.b2 = B2_PIN;\n\n  mxconfig.gpio.a = A_PIN;\n  mxconfig.gpio.b = B_PIN;\n  mxconfig.gpio.c = C_PIN;\n  mxconfig.gpio.d = D_PIN;\n  mxconfig.gpio.e = E_PIN;\n\n  mxconfig.gpio.lat = LAT_PIN;\n  mxconfig.gpio.oe  = OE_PIN;\n  mxconfig.gpio.clk = CLK_PIN;\n\n  \/\/ Important for chained panels with color\/data problems\n  mxconfig.clkphase = false;                 \/\/ Try false first. If worse, try true.\n  mxconfig.i2sspeed = HUB75_I2S_CFG::HZ_10M; \/\/ Slower and more stable for chained panels\n\n  dma_display = new MatrixPanel_I2S_DMA(mxconfig);\n\n  if (!dma_display-&gt;begin()) {\n    Serial.println(&#8220;Matrix begin failed!&#8221;);\n    return;\n  }\n\n  dma_display-&gt;setBrightness8(90); \/\/ Lower brightness reduces power\/noise problems\n\n  vpanel = new VirtualMatrixPanel(\n    *dma_display,\n    NUM_ROWS,\n    NUM_COLS,\n    PANEL_RES_X,\n    PANEL_RES_Y,\n    VIRTUAL_MATRIX_CHAIN_TYPE\n  );\n\n  vpanel-&gt;clearScreen();\n\n  drawRGB565Image_P(0, 0, mhf_64x64, 64, 64);\n}\n\nvoid loop() {\n  \/\/ Static picture frame: the bitmap only needs to be drawn once in setup().\n}<\/textarea>\n      <\/div>\n    <\/div>\n  <\/details>\n\n  <h2>8. Common Problems<\/h2>\n\n  <div class=\"ebox-faq-list\">\n    <details>\n      <summary>The second panel shows wrong colors<\/summary>\n      <div class=\"ebox-faq-content\">\n        <p>\n          Check the RGB pin mapping, scan pattern, panel type, and HUB75 library configuration.\n          For chained panels, the slower <code>HZ_10M<\/code> I2S speed and the correct clock phase can improve stability.\n        <\/p>\n      <\/div>\n    <\/details>\n\n    <details>\n      <summary>The image is mirrored or split incorrectly<\/summary>\n      <div class=\"ebox-faq-content\">\n        <p>\n          Check the virtual matrix chain type and the physical orientation of both matrix panels.\n          For two 64 \u00d7 32 panels stacked vertically, this project uses <code>CHAIN_BOTTOM_LEFT_UP<\/code>.\n        <\/p>\n      <\/div>\n    <\/details>\n\n    <details>\n      <summary>The display flickers or resets<\/summary>\n      <div class=\"ebox-faq-content\">\n        <p>\n          Use a stable 5 V power supply, short power wires, and a common ground between the ESP32 and panels.\n          Lowering the brightness can also reduce current peaks and noise problems.\n        <\/p>\n      <\/div>\n    <\/details>\n\n    <details>\n      <summary>The Arduino sketch does not compile because the bitmap name is missing<\/summary>\n      <div class=\"ebox-faq-content\">\n        <p>\n          Open the generated <code>.h<\/code> file and check the exact array name after <code>const uint16_t<\/code>.\n          Use exactly this name in <code>drawRGB565Image_P()<\/code>. C++ is case-sensitive.\n        <\/p>\n      <\/div>\n    <\/details>\n  <\/div>\n\n  <div class=\"ebox-final-box\">\n    <h2>9. Final Result<\/h2>\n    <p>\n      The final result is a compact LED matrix picture frame that displays a custom pixel-art image on\n      two chained RGB matrix panels. It is a useful project for reusing leftover display hardware and\n      testing RGB565 image workflows.\n    <\/p>\n\n    <div class=\"ebox-image-card\">\n      <img decoding=\"async\" src=\"https:\/\/elektrobox.ch\/wp-content\/uploads\/2026\/05\/IMG_2602-scaled.jpg\" alt=\"Final DIY LED Matrix Picture Frame\">\n    <\/div>\n  <\/div>\n\n<\/div>\n\n<script>\n  function eboxCopyCode(id, button) {\n    const textarea = document.getElementById(id);\n    if (!textarea) return;\n\n    textarea.focus();\n    textarea.select();\n    textarea.setSelectionRange(0, 999999);\n\n    const oldText = button.textContent;\n\n    function showCopied() {\n      button.textContent = 'Copied!';\n      setTimeout(function () {\n        button.textContent = oldText;\n      }, 1400);\n    }\n\n    if (navigator.clipboard && window.isSecureContext) {\n      navigator.clipboard.writeText(textarea.value).then(showCopied).catch(function () {\n        document.execCommand('copy');\n        showCopied();\n      });\n    } else {\n      document.execCommand('copy');\n      showCopied();\n    }\n  }\n<\/script>\n","protected":false},"excerpt":{"rendered":"<p>ESP32 RGB Matrix Project DIY LED Matrix Picture Frame In this ElektroBox project, I build a small LED matrix picture frame using an ESP32 and two chained RGB LED matrix panels. The picture frame displays a custom 64 \u00d7 64 pixel image stored as an RGB565 bitmap. The ESP32 reads the bitmap data from program [&hellip;]<\/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-856149","page","type-page","status-publish","hentry"],"blocksy_meta":{"styles_descriptor":{"styles":{"desktop":"","tablet":"","mobile":""},"google_fonts":[],"version":7}},"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>LED Matrix Picture Frame - ElektroBox<\/title>\n<meta name=\"description\" content=\"Build a DIY LED matrix picture frame with an ESP32, two chained RGB LED matrix panels, RGB565 bitmap images, and a Python image converter.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/elektrobox.ch\/index.php\/matrix-picture-frame\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"LED Matrix Picture Frame - ElektroBox\" \/>\n<meta property=\"og:description\" content=\"Build a DIY LED matrix picture frame with an ESP32, two chained RGB LED matrix panels, RGB565 bitmap images, and a Python image converter.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/elektrobox.ch\/index.php\/matrix-picture-frame\/\" \/>\n<meta property=\"og:site_name\" content=\"ElektroBox\" \/>\n<meta property=\"article:modified_time\" content=\"2026-06-03T19:25:18+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/elektrobox.ch\/wp-content\/uploads\/2026\/05\/IMG_2602-scaled.jpg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/elektrobox.ch\\\/index.php\\\/matrix-picture-frame\\\/\",\"url\":\"https:\\\/\\\/elektrobox.ch\\\/index.php\\\/matrix-picture-frame\\\/\",\"name\":\"LED Matrix Picture Frame - ElektroBox\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/elektrobox.ch\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/elektrobox.ch\\\/index.php\\\/matrix-picture-frame\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/elektrobox.ch\\\/index.php\\\/matrix-picture-frame\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/elektrobox.ch\\\/wp-content\\\/uploads\\\/2026\\\/05\\\/IMG_2602-scaled.jpg\",\"datePublished\":\"2026-05-23T21:12:52+00:00\",\"dateModified\":\"2026-06-03T19:25:18+00:00\",\"description\":\"Build a DIY LED matrix picture frame with an ESP32, two chained RGB LED matrix panels, RGB565 bitmap images, and a Python image converter.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/elektrobox.ch\\\/index.php\\\/matrix-picture-frame\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/elektrobox.ch\\\/index.php\\\/matrix-picture-frame\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/elektrobox.ch\\\/index.php\\\/matrix-picture-frame\\\/#primaryimage\",\"url\":\"https:\\\/\\\/elektrobox.ch\\\/wp-content\\\/uploads\\\/2026\\\/05\\\/IMG_2602-scaled.jpg\",\"contentUrl\":\"https:\\\/\\\/elektrobox.ch\\\/wp-content\\\/uploads\\\/2026\\\/05\\\/IMG_2602-scaled.jpg\",\"width\":2560,\"height\":1920},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/elektrobox.ch\\\/index.php\\\/matrix-picture-frame\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/elektrobox.ch\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"LED Matrix Picture Frame\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/elektrobox.ch\\\/#website\",\"url\":\"https:\\\/\\\/elektrobox.ch\\\/\",\"name\":\"ElektroBox\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/elektrobox.ch\\\/#\\\/schema\\\/person\\\/878bd55e17d9d0b1a53523fa5e90f6b2\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/elektrobox.ch\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/elektrobox.ch\\\/#\\\/schema\\\/person\\\/878bd55e17d9d0b1a53523fa5e90f6b2\",\"name\":\"Jacob Jarosz\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/elektrobox.ch\\\/wp-content\\\/uploads\\\/2026\\\/05\\\/Logo_Color-Kopie-scaled.png\",\"url\":\"https:\\\/\\\/elektrobox.ch\\\/wp-content\\\/uploads\\\/2026\\\/05\\\/Logo_Color-Kopie-scaled.png\",\"contentUrl\":\"https:\\\/\\\/elektrobox.ch\\\/wp-content\\\/uploads\\\/2026\\\/05\\\/Logo_Color-Kopie-scaled.png\",\"width\":2560,\"height\":2560,\"caption\":\"Jacob Jarosz\"},\"logo\":{\"@id\":\"https:\\\/\\\/elektrobox.ch\\\/wp-content\\\/uploads\\\/2026\\\/05\\\/Logo_Color-Kopie-scaled.png\"},\"sameAs\":[\"http:\\\/\\\/elektrobox.ch\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"LED Matrix Picture Frame - ElektroBox","description":"Build a DIY LED matrix picture frame with an ESP32, two chained RGB LED matrix panels, RGB565 bitmap images, and a Python image converter.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/elektrobox.ch\/index.php\/matrix-picture-frame\/","og_locale":"en_US","og_type":"article","og_title":"LED Matrix Picture Frame - ElektroBox","og_description":"Build a DIY LED matrix picture frame with an ESP32, two chained RGB LED matrix panels, RGB565 bitmap images, and a Python image converter.","og_url":"https:\/\/elektrobox.ch\/index.php\/matrix-picture-frame\/","og_site_name":"ElektroBox","article_modified_time":"2026-06-03T19:25:18+00:00","og_image":[{"url":"https:\/\/elektrobox.ch\/wp-content\/uploads\/2026\/05\/IMG_2602-scaled.jpg","type":"","width":"","height":""}],"twitter_card":"summary_large_image","twitter_misc":{"Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/elektrobox.ch\/index.php\/matrix-picture-frame\/","url":"https:\/\/elektrobox.ch\/index.php\/matrix-picture-frame\/","name":"LED Matrix Picture Frame - ElektroBox","isPartOf":{"@id":"https:\/\/elektrobox.ch\/#website"},"primaryImageOfPage":{"@id":"https:\/\/elektrobox.ch\/index.php\/matrix-picture-frame\/#primaryimage"},"image":{"@id":"https:\/\/elektrobox.ch\/index.php\/matrix-picture-frame\/#primaryimage"},"thumbnailUrl":"https:\/\/elektrobox.ch\/wp-content\/uploads\/2026\/05\/IMG_2602-scaled.jpg","datePublished":"2026-05-23T21:12:52+00:00","dateModified":"2026-06-03T19:25:18+00:00","description":"Build a DIY LED matrix picture frame with an ESP32, two chained RGB LED matrix panels, RGB565 bitmap images, and a Python image converter.","breadcrumb":{"@id":"https:\/\/elektrobox.ch\/index.php\/matrix-picture-frame\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/elektrobox.ch\/index.php\/matrix-picture-frame\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/elektrobox.ch\/index.php\/matrix-picture-frame\/#primaryimage","url":"https:\/\/elektrobox.ch\/wp-content\/uploads\/2026\/05\/IMG_2602-scaled.jpg","contentUrl":"https:\/\/elektrobox.ch\/wp-content\/uploads\/2026\/05\/IMG_2602-scaled.jpg","width":2560,"height":1920},{"@type":"BreadcrumbList","@id":"https:\/\/elektrobox.ch\/index.php\/matrix-picture-frame\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/elektrobox.ch\/"},{"@type":"ListItem","position":2,"name":"LED Matrix Picture Frame"}]},{"@type":"WebSite","@id":"https:\/\/elektrobox.ch\/#website","url":"https:\/\/elektrobox.ch\/","name":"ElektroBox","description":"","publisher":{"@id":"https:\/\/elektrobox.ch\/#\/schema\/person\/878bd55e17d9d0b1a53523fa5e90f6b2"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/elektrobox.ch\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/elektrobox.ch\/#\/schema\/person\/878bd55e17d9d0b1a53523fa5e90f6b2","name":"Jacob Jarosz","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/elektrobox.ch\/wp-content\/uploads\/2026\/05\/Logo_Color-Kopie-scaled.png","url":"https:\/\/elektrobox.ch\/wp-content\/uploads\/2026\/05\/Logo_Color-Kopie-scaled.png","contentUrl":"https:\/\/elektrobox.ch\/wp-content\/uploads\/2026\/05\/Logo_Color-Kopie-scaled.png","width":2560,"height":2560,"caption":"Jacob Jarosz"},"logo":{"@id":"https:\/\/elektrobox.ch\/wp-content\/uploads\/2026\/05\/Logo_Color-Kopie-scaled.png"},"sameAs":["http:\/\/elektrobox.ch"]}]}},"_links":{"self":[{"href":"https:\/\/elektrobox.ch\/index.php\/wp-json\/wp\/v2\/pages\/856149","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/elektrobox.ch\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/elektrobox.ch\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/elektrobox.ch\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/elektrobox.ch\/index.php\/wp-json\/wp\/v2\/comments?post=856149"}],"version-history":[{"count":13,"href":"https:\/\/elektrobox.ch\/index.php\/wp-json\/wp\/v2\/pages\/856149\/revisions"}],"predecessor-version":[{"id":856420,"href":"https:\/\/elektrobox.ch\/index.php\/wp-json\/wp\/v2\/pages\/856149\/revisions\/856420"}],"wp:attachment":[{"href":"https:\/\/elektrobox.ch\/index.php\/wp-json\/wp\/v2\/media?parent=856149"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}