3
$\begingroup$

Mathematica language newbie here. I wrote the following code to quantize an image:

basepath = "~"
SetDirectory[basepath]
jpgpath = FileNameJoin[{basepath, "jpg"}]
pngpath = FileNameJoin[{basepath, "png"}]

domquant[path_, n_] := 
 Image[{List @@@ 
    DominantColors[Image[ColorQuantize[Import[path], n]], n]}]

(*Convert each jpg in path to its 256-color quantized sample*)
Scan[( \
 img = domquant[#, 24];
    Print[#, " ", img];
Export[
    FileNameJoin[{pngpath, StringJoin[FileBaseName[#], ".jpg"]}],
    img,
    "JPEG", ImageResolution -> 300, 
ImageSize -> {8192, 512}]) &, {FileNames[
"*.jpg", {jpgpath}][[1]]}]

If I change the 24 in the domquant call to a higher value I get what looks like a rasterized image (I think). Specifically, a gradient is applied. For example, here's the result of domquant[#, 256]:

wtf

However, if I leave the value as n = 24 or some other smaller number, I get a nice image like this which has discrete boundaries between each value of n, and is actually what I am trying to achieve:

enter image description here

So, why is 24 the magic number beyond which the blur effect takes place? How can I get an image with nice discrete colors using a higher value of n?

In response to Szabolcs, if I remove the ImageResolution and ImageSize options, I get this image:

enter image description here

Not what I'm looking for. I want to create an image like the second one above, where each of 256 colors is represented discretely, and is of arbitrary size.

In response to Simon Woods, if I add Resampling -> "Nearest" to Export, I ge this image with n=256, again blurry:

enter image description here

Thanks to everyone who commented, the following comment from SimonWoods helped me understand. Here's the final (working) code and the resulting (quite beautiful) image.

basepath = "~"
SetDirectory[basepath]
jpgpath = FileNameJoin[{basepath, "jpg"}]
pngpath = FileNameJoin[{basepath, "png"}]

domquant[path_, n_] := 
 Image[{List @@@ 
    DominantColors[Image[ColorQuantize[Import[path], n]], n]}]

(*Convert each jpg in path to its 256-color quantized sample*)
Scan[(
   img = domquant[#, 256];
   img = ImageResize[img, {8152, 512}, Resampling -> "Nearest"];
   Print[#, " ", img];
   Export[
    FileNameJoin[{pngpath, StringJoin[FileBaseName[#], ".png"]}],
        img, "PNG"]) &, {FileNames["*.jpg", {jpgpath}][[1]]}]

enter image description here

$\endgroup$
11
  • 1
    $\begingroup$ The settings ImageResolution -> 300, ImageSize -> {8192, 512} trigger resampling. Don't use these settings. If you do need to resample the image, do it explicitly using ImageResize, then export the resized image at 1-to-1 pixel size. Also, don't export such a quantized image to JPEG. The lossy compression will introduce colours that you did not originally put in the image. Use PNG instead. $\endgroup$
    – Szabolcs
    Commented Mar 8, 2013 at 1:57
  • $\begingroup$ @Szabolcs answer? $\endgroup$
    – Yves Klett
    Commented Mar 8, 2013 at 13:33
  • $\begingroup$ @Yves I was waiting for the OP to react $\endgroup$
    – Szabolcs
    Commented Mar 8, 2013 at 13:34
  • 2
    $\begingroup$ @Szabolcs, in v8 at least, the Automatic setting for the Resampling option in ImageResize uses nearest neighbour only if both image dimensions are <=24, and one of the interpolating methods for images larger than that. So the OP will need to specify Resampling->"Nearest" to get the desired result. $\endgroup$ Commented Mar 8, 2013 at 16:43
  • 1
    $\begingroup$ @g33kz0r, it's an option for ImageResize, not for Export. The idea is you remove the options from Export and use img = ImageResize[img, {8152,512}, Resampling -> "Nearest"] to change the image size. $\endgroup$ Commented Mar 8, 2013 at 16:58

1 Answer 1

1
$\begingroup$

To prevent interpolation between adjacent pixels requires the option Resampling -> "Nearest" in ImageResize. This is the default setting for images smaller than $24\times24$ pixels, but larger images will use one of the other resampling methods (I'm not sure which). The desired result can therefore be obtained with:

img = ImageResize[img, {8152,512}, Resampling -> "Nearest"] 
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.