diff --git a/.changeset/stale-games-float.md b/.changeset/stale-games-float.md
new file mode 100644
index 0000000..db98601
--- /dev/null
+++ b/.changeset/stale-games-float.md
@@ -0,0 +1,5 @@
+---
+'@viamrobotics/test-widgets': minor
+---
+
+support 360 camera images with special XMP metadata
diff --git a/src/lib/components/widgets/camera/__tests__/get-xmp-json-from-image.spec.ts b/src/lib/components/widgets/camera/__tests__/get-xmp-json-from-image.spec.ts
new file mode 100644
index 0000000..b56c373
--- /dev/null
+++ b/src/lib/components/widgets/camera/__tests__/get-xmp-json-from-image.spec.ts
@@ -0,0 +1,51 @@
+import { describe, expect, it } from 'vitest'
+
+import { getXmpJsonFromImageBytes } from '../get-xmp-json-from-image'
+
+const buildJpegWithXmp = (xmpXml: string): Uint8Array => {
+ const identifier = new TextEncoder().encode('http://ns.adobe.com/xap/1.0/\0')
+ const xmpBytes = new TextEncoder().encode(xmpXml)
+ const app1Length = 2 + identifier.length + xmpBytes.length
+ const app1Segment = new Uint8Array(2 + app1Length)
+
+ app1Segment[0] = 0xff
+ app1Segment[1] = 0xe1
+ app1Segment[2] = (app1Length >> 8) & 0xff
+ app1Segment[3] = app1Length & 0xff
+ app1Segment.set(identifier, 4)
+ app1Segment.set(xmpBytes, 4 + identifier.length)
+
+ return new Uint8Array([0xff, 0xd8, ...app1Segment, 0xff, 0xd9])
+}
+
+describe('getXmpJsonFromImageBytes', () => {
+ it('returns null when the image has no XMP segment', () => {
+ const jpeg = new Uint8Array([0xff, 0xd8, 0xff, 0xd9])
+
+ expect(getXmpJsonFromImageBytes(jpeg)).toBeNull()
+ })
+
+ it('parses viam:is360 from a JPEG XMP packet', () => {
+ const xmpXml = `
+
+
+
+
+
+`
+
+ const jpeg = buildJpegWithXmp(xmpXml)
+ const xmpJson = getXmpJsonFromImageBytes(jpeg, 'image/jpeg')
+
+ expect(xmpJson).toEqual({
+ 'viam:is360': 'true',
+ 'xmlns:rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
+ 'xmlns:viam': 'https://www.viam.com/',
+ 'xmlns:x': 'adobe:ns:meta/',
+ })
+ })
+})
diff --git a/src/lib/components/widgets/camera/camera.svelte b/src/lib/components/widgets/camera/camera.svelte
index 32c7d79..d4203c4 100644
--- a/src/lib/components/widgets/camera/camera.svelte
+++ b/src/lib/components/widgets/camera/camera.svelte
@@ -1,4 +1,5 @@
+
+
+
+
+
+{#if $texture}
+ {#await texture then map}
+
+
+
+
+ {/await}
+{/if}
+
+
+