Optimal parity embedding
• In a palette image, each pixel stores an index pointing to a color in the palette.
• Normally, LSB embedding modifies the least significant bit of the index. This may map a
pixel to a very different palette color (large distortion).
• Optimal parity embedding:
o Assigns parities (0/1) to each palette entry.
o Ensures that the closest neighbor of any color has the opposite parity.
o To embed a bit, we just swap the pixel’s color to its nearest opposite-parity
neighbor, minimizing visual distortion.
Example
Number the palette colors 𝑐[1] … 𝑐[6] with RGB triples:
• 𝑐[1] = (10, 10, 10)
• 𝑐[2] = (12, 12, 12)
• 𝑐[3] = (200, 50, 50)
• 𝑐[4] = (202, 52, 52)
• 𝑐[5] = (50, 200, 50)
• 𝑐[6] = (55, 195, 55)
Let us use the squared Euclidean distance in RGB:
𝑑RGB (𝑐[𝑘], 𝑐[ℓ]) = (𝑟! − 𝑟ℓ )# + (𝑔! − 𝑔ℓ )# + (𝑏! − 𝑏ℓ )# .
Step 1 — Compute pairwise distances (showing the small ones first)
Computing distances for obvious near neighbours:
1. 𝑑(𝑐[1], 𝑐[2])
differences (10 − 12,10 − 12,10 − 12) = (−2, −2, −2) → squared sum = 4 + 4 +
4 = 12.
2. 𝑑(𝑐[3], 𝑐[4])
differences (200 − 202,50 − 52,50 − 52) = (−2, −2, −2) → squared sum = 12.
3. 𝑑(𝑐[5], 𝑐[6])
differences (50 − 55,200 − 195,50 − 55) = (−5,5, −5) → squared sum = 25 +
25 + 25 = 75.
Some cross-cluster distances (large):
• 𝑑(𝑐[1], 𝑐[3]): diffs (10 − 200, −190), (10 − 50, −40), (10 − 50, −40) →
squares 36100 + 1600 + 1600 = 39300.
• 𝑑(𝑐[2], 𝑐[4]): similarly large, etc.
So the smallest distances (non-decreasing) are:
D={12 (c1,c2), 12 (c3,c4), 75 (c5,c6), (then many ∼39,000 more)
Step 2 — Run the parity assignment algorithm
Initialize 𝒫 = ∅
Process distances in nondecreasing order:
Distance 𝟏𝟐 for pair (𝒄[𝟏], 𝒄[𝟐])
• Neither 𝑐[1] nor 𝑐[2] ∈ 𝒫.
• Rule 4.a applies → assign opposite parities, e.g. 𝑃[1] = 0, 𝑃[2] = 1.
• Update 𝒫 ← {𝑐[1], 𝑐[2]}.
Next distance 𝟏𝟐 for (𝒄[𝟑], 𝒄[𝟒])
• Neither 𝑐[3] nor 𝑐[4] ∈ 𝒫.
• Apply 4.a → assign opposite parities, e.g. 𝑃[3] = 0, 𝑃[4] = 1.
• Update 𝑃 ← {𝑐[1], 𝑐[2], 𝑐[3], 𝑐[4]}.
Next distance 𝟕𝟓 for (𝒄[𝟓], 𝒄[𝟔])
• Neither 𝑐[5] nor 𝑐[6] ∈ 𝒫.
• Apply 4.a → assign opposite parities, e.g. 𝑃[5] = 0, 𝑃[6] = 1.
• Update 𝒫 ← {𝑐[1], … , 𝑐[6]}.
Now all 𝑁$ = 6 colours are assigned, algorithm stops.
Final parity assignment table:
Index 𝑗 Color 𝑐[𝑗] Parity 𝑃[𝑗]
1 (10,10,10) 0
2 (12,12,12) 1
3 (200,50,50) 0
4 (202,52,52) 1
5 (50,200,50) 0
6 (55,195,55) 1
Each colour’s closest neighbour has the opposite parity. Thus swapping to the closest
opposite-parity colour yields minimal distortion.
Step 3 - Hiding a message with optimal-parity embedding:
• Original pixel indices (scan order):
[ 1, 2, 3, 5, 1, 6, 4, 2 ] — eight pixels.
• Secret bitstream to embed (one bit per pixel):
[ 1, 0, 1, 1, 0, 1, 0, 1 ].
For each pixel:
1. Read current palette index 𝑗 and its parity 𝑃[𝑗].
2. If 𝑃[𝑗] equals the message bit; do nothing.
3. If 𝑃[𝑗] differs; replace the pixel’s color by the closest palette color with opposite
parity (i.e., swap to the paired color). This yields minimal local distortion.
Embedding (per pixel):
original original color 𝑃[o msg bit action new new color Distortion
index rig] to index (Euclid)
embed
1 (10,10,10) 0 1 parity ≠ bit → swap to closest 2 (12,12,12) √12 ≈ 3.4641
opposite parity (index 2)
2 (12,12,12) 1 0 parity ≠ bit → swap to closest 1 (10,10,10) √12 ≈ 3.4641
opposite parity (index 1)
3 (200,50,50) 0 1 swap → index 4 4 (202,52,52) √12 ≈ 3.4641
5 (50,200,50) 0 1 swap → index 6 6 (55,195,55) √75 ≈ 8.6603
1 (10,10,10) 0 0 parity = bit → no change 1 (10,10,10) 0
6 (55,195,55) 1 1 parity = bit → no change 6 (55,195,55) 0
4 (202,52,52) 1 0 swap → index 3 3 (200,50,50) √12 ≈ 3.4641
2 (12,12,12) 1 1 parity = bit → no change 2 (12,12,12) 0
Final embedded image:
• Final palette indices: [ 2, 1, 4, 6, 1, 6, 3, 2 ]
• Final colors: [(12,12,12),(10,10,10),(202,52,52),(55,195,55),(10,10,10),(55,195,55),
(200,50,50),(12,12,12)]
• Sum of Euclidean distortions = 4 ⋅ √12 + √75 ≈ 22.51666
• Average distortion per pixel (over all 8 pixels) ≈ 22.51666/8 ≈ 2.8146.
Extraction (how the receiver reads the hidden bits):
For each final pixel, the receiver reads the parity of the palette index:
• Final indices [2,1,4,6,1,6,3,2] → parities [1,0,1,1,0,1,0,1].
This exactly recovers the original secret message.
inprotected.com