truncate is a good tool. You need to shrink the image, so it contains every partition defined in the partition table. In other words, if the end sector of the partition closest to the end is
N (note it doesn't have to be the partition with the highest number), you need
N+1 sectors of the image (
+1 because numbering starts at
gdisk -l image to know the
Most likely the card uses 512-byte sectors and the partition table is valid when interpreted in terms of 512-byte sectors (for comparison: see what happens when this assumption does not hold). So you need
(N+1)*512 bytes (or more, having more is not fatal).
Reading this number of bytes directly from the card in the first place would give you the same result. An easy way (although non-POSIX, see this) is
head -c number-of-bytes-here /dev/sdx > image.
Then you need 33 additional logical sectors for a secondary (backup) GPT. Use
truncate again and add
33*512 bytes to the file (
truncate -s +16896 image). We could have shrunk the image to the desired final size with the first
truncate (or read more with
head), but doing this in two steps causes these additional 33 sectors to contain zeros instead of garbage that might interfere in a moment.
The first truncating (or creating a partial image) discarded the original secondary GPT. Use
gdisk image and let it fix the problem. It will tell you that
disk size is smaller than the main header indicates and
invalid backup GPT header, but valid main header; regenerating backup header from main header. Thanks to the second
truncate there is room for the backup GPT. All you need is to "
write table to disk and exit"; the tool will rewrite GPT, including the backup one.
gunzip -c image.gz |dd of=/dev/sdx(adapt to your card's device file)