MATLAB: Convert indexed image to rgb and back without losing data

Image Processing Toolboxind2rgbrgb2indsteganography

I am having trouble converting an indexed image to RGB and then back from RGB to an indexed image. For some reason, the result is different from the original. I am doing steganography so it can't work if the data is changed. This is my code and this is the sample image:
[J map]=imread('RoFox.gif');
[rows cols color nframe]=size(J);
for frame = 1:nframe
Jrgb(:,:,:,frame)=ind2rgb(J(:,:,1,frame),map);
Jind(:,:,1,frame)=rgb2ind(Jrgb(:,:,:,frame),map);
end
for frame = 1:nframe
isequal(Jind(:,:,1,frame),J(:,:,1,frame))
end
This image has no transparancy and the colormap is unique. Variables J and Jind are supposed to be equal. Why are they being detected as being different?

Best Answer

One of the issue is that you're using rgb2ind with the default option, so it does colour dithering. You should be calling it with the 'nodither' option.
Unfortunately, it's not enough in your case probably because internally rgb2ind does a conversion from double to uint8 and that is enough to cause precision error.
You could bypass rgb2ind and do the conversion yourself directly:
for frame = 1:nframe
Jrgb(:,:,:,frame)=ind2rgb(J(:,:,1,frame),map);
tmprgb = reshape(Jrgb(:, :, :, frame), [], 3); %reshape rgb image into a column of rgb values
[~, tmpind] = ismember(tmprgb, map, 'rows'); %find rgb triplet in map
assert(all(tmpind > 0), 'an rgb triplet was not found in the map');
Jind(:, :, 1, frame) = reshape(tempind-1, size(Jrgb, 1), size(Jrgb, 2));
end
Note that if you're going to manipulate rgb intensities any slight imprecision in the pixel intensity may result in the rgb triplet not being found in the map. In which case, you may have to use ismembertol instead of ismember.