How to get a dithered color image

7 views (last 30 days)
elham sa
elham sa on 31 Jul 2015
Commented: DGM on 27 Sep 2023
I know that
X = dither(RGB, map);
returns an indexed image approximation to the given RGB image. I have two questions:
(1) Is there a second step that converts the indexed image to an RGB image using the provided colormap?
(2) How to design a colormap that matches the original colors of the image?
Note: I want a dithered color image not an indexed image.
Any hint/help is appreciated!

Accepted Answer

Image Analyst
Image Analyst on 31 Jul 2015
I've never used dither() so I don't know what it does. But to answer your questions:
(1) Yes. It's called ind2rgb().
rgbImage = ind2rgb(indexedImage, customColorMap);
(2) Call rgb2ind():
[indexedImage, customColorMap] = rgb2ind(grayImage, numColors);
  2 Comments
elham sa
elham sa on 31 Jul 2015
Edited: elham sa on 31 Jul 2015
Thank you very much image analyst!
The rgb2ind() function was really helpful, now I know how to get the colormap that matches the image.
However, the ind2rgb() returns an RGB continuous image, not a dithered one (I mean the color image with the dots!)
I tried dithering in each separate color channel and it did the trick.
Thanks!
DGM
DGM on 27 Sep 2023
If you don't already have a map appropriate for a given RGB image, then I don't see that there's any reason to be using dither() at all.
% the inputs
nlevels = 16; % maximum number of unique colors
inpict = imread('peppers.png');
% rgb2ind() defaults are dithered already
% if you need to use rgb2ind() to get the optimized map
% then there's no point in ever calling dither()
[idx map] = rgb2ind(inpict,nlevels);
imshow(idx,map,'border','tight')
xlim([242 388]); ylim([155 274]) % zoom in
% ind2rgb() cannot change the presence or absence of dithering
% so if the output isn't dithered, then either the input was never dithered
% or it's simply being displayed incorrectly somehow
outpict = ind2rgb(idx,map);
imshow(outpict,'border','tight')
xlim([242 388]); ylim([155 274]) % zoom in
% there are at most (nlevels) colors
allcolors = unique(reshape(outpict,[],3),'rows');
numcolors = size(allcolors,1)
numcolors = 16
There's no way that dithering channels independently returns an appropriate result, or a result compatible with any optimized color table. I have no idea what was attempted, but I can guess.
% create an effectively 3-bit color image by
% naively calling dither() on each channel
junk3b = zeros(size(inpict),'uint8');
for c = 1:3
junk3b(:,:,c) = im2uint8(dither(inpict(:,:,c)));
end
imshow(junk3b,'border','tight')
xlim([242 388]); ylim([155 274]) % zoom in
% there are at most 8 colors
allcolors = unique(reshape(junk3b,[],3),'rows');
numcolors = size(allcolors,1)
numcolors = 8
Or less likely:
% do graylevel dithering on each channel
% dither() doesn't really have a good way to do this
junkgl = zeros(size(inpict),'uint8');
CT = gray(nlevels); % dummy map
for c = 1:3
thischannel = repmat(inpict(:,:,c),[1 1 3]); % expand
junkgl(:,:,c) = dither(thischannel,CT);
end
junkgl = im2uint8(double(junkgl)/(nlevels-1)); % rescale
imshow(junkgl,'border','tight')
xlim([242 388]); ylim([155 274]) % zoom in
% ... and there are far more unique colors than specified (at most nlevels^3)
allcolors = unique(reshape(junkgl,[],3),'rows');
numcolors = size(allcolors,1)
numcolors = 1079

Sign in to comment.

More Answers (0)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!