This is a situation I encounter with relative frequency when I am playing with graphics. I scan an image which is composed of flat colors, like a logo or a map. No shades, just flat colors in the original but in the scanned image each pixel is slightly different from the neigbor. I want to reproduce the original “flat” image.
In BMP and JPG graphics each bit can take any value of the whole range while in palette graphics like GIF and PNG each pixel is assigned a color of the defined palette. These methods of compression only work well when you have large areas filled with the same palette value.
So I want to reproduce the original flat image. I can reduce the number of colors in the image to any number I like. No problem. The problem is that the flat areas then become a mosaic of pixels of different values. I have enlarged and posted en example here. You can see I had no problem getting the streets to be all white but the buildings have a lot of white pixels mixed with the orange.
I want a filter which will get rid of those white pixels. Now, remember we are already working with a defined palette. A regular “blur” filter will not work because it creates more problems than it solves, not least of which is that it does not stay within the defined palette. I need a simple blur filter which would stay within the confines of the palette.
Let us say each pixel is limited by four pixels (L1 to L4) and “surrounded” in the corners by another four pixels (S1 to S4). I guess the rule would be something like this: “If pixel is limited on three sides by the same color CX then the new pixel color is CX”. As long as there are no 4 pixels forming a square 2x2 this will get rid of them. I suppose the rule could be further refined but this is a good start.
Is there any graphic program which will do this? I use Irfanview, MSpaint and Photodeluxe and none of them can do it AFAIK.
If there is no graphic program which will do this is there some simple way of doing it? It seems that it should not be difficult to write a program which would do it. Give it a BMP and it gives you the new BMP.
ImageMagick will do what you’re asking for; the “-paint” option replaces each pixel by the most frequent color within a specified radius. I suspect GIMP and Photoshop have similar filters. Paint doesn’t; I don’t know about Irfanview or Photodeluxe though. You could also try a “despeckle” filter (ImageMagick has one of these too). Both of these options are attempts at correcting the original incorrect quantization; you could also apply some filtering to the original image (before hard quantization) to reduce the speckling: maybe a median filter (also possible in ImageMagick), or even a region-detecting algorithm. Other programs might use different color-quantization algorithms and produce better results than you’re getting, too.
The problem might also be with the scanning itself (scanning halftoned images is problematic, for example). You might try scanning at a higher resolution and then dithering and undersampling to get a smoother image to start with.
Another possibility* is to use Macromedia FreeHand’s AutoTrace feature – click on the AutoTrace tool and set the Color Mode to 16 (or however few) colors. The result should looks like paint-by-numbers, which, I believe, is what you’re after. You can download a free 30-day trial from Macromedia if you want to try this out.
Disclaimer: I haven’t tried this myself since I don’t have the right software; the technique comes from a design magazine.
Well, I can adjust the contrast so that it doesn’t happen but that messes up other parts of the graphic.
Omphaloskeptic, Thank you for the lead. I downloaded ImageMagick and have been playing with it. It sort of wrks but not too well. I would need to change only white pixels which are surrounded by orange. By changing any pixels it messes up slightly other parts of the image. Furthermore, while it correctly changes many white pixels to orange, it changes some orange to white so I have to run the filter several times and it makes the other parts of the image worse. nevertheless it is an interesting program to play with althouth I can’t say the command line interface. It seems command line interfaces are gaining in popularity or I am just seeing them more but I am accustomed to GUI and I find the command line to be a PITA. I often use Besweet (audio process) which also has a command line interface.
Or not dither at all, but map to the nearest color in the palette. “Dithering” means using a pattern of pixels to create the illusion of continuous gradient. Here the software is throwing a few white pixels in the orange part to simulate a lighter orange. If the software you are using has the option to quantize (convert from true color to palette) without dithering, you might want to try it.
I have looked at the printed original with a magnifying lens and it is composed of tiny dots of read and yellow ink which when looked at normal distance give the appearance of orange so that explains why the scan looks as it does. You also have to add the normal rugosity of the paper and the imperfections of the scanning process. I have posted a section of the original scan and three different adjustments of contrast for the same image. Note that only the last one gives a solid color but it messes up the green and the letters. I think my original idea is the only one that would work. Not a filter which applies the same rule to all pixels but one whixh would only process a pixel if that pixel had a certain value X and it was surrounded by pixels a value Y. But it seems there is no such filter already made. I am thinking it should not be difficult to write it for those who know about these things.
I’m not sure what you’re asking here. Are you saying that you only want to replace (say) white pixels surrounded by orange, or do you want to replace any small group of pixels surrounded by another color? Your new examples include bitmaps of text (not in the original example), which does require somewhat different processing from large fields of color (you probably want to allow the text to be dithered for smoother font shapes).
One ImageMagick tool that might help is the -map option, to explicitly choose a color palette. Create a file palette.bmp with all of the colors you want in the final image and the quantization will be done to this color set. In some cases you might need an intermediate palette to pull especially light or dark colors toward the desired final value.
You can also use the “-draw ‘image …’” operations to pull out individual color planes and operate on them, though this is kind of tedious. For example, use Difference with a solid-orange file to get an image that’s mostly black in the orange regions. Use “-fuzz ‘20%’ -transparent black” or similar to transfer this region to the opacity plane. Pull off this plane and mess with it: maybe blur and requantize to get rid of the speckles. You can now restrict all of your image changes to this region; this will avoid the problem of -blur messing up the other colors. (Then do some retouching by hand anyway; the human eye is an awful lot better than the best image-manipulation programs out there for most things.)
Reading and writing most bitmap/pixmap formats (like BMP) is not hard, either (Google for “BMP file format” for plenty of references). This allows you to tune your filter precisely for the image you’re playing with, at the expense of maybe having to redo it for each new set of images that comes along. You’ll still have some retouching to do.
As for the CLI/GUI interface problems, I think there are GUI interfaces to ImageMagick out there somewhere. Or you could try the GIMP.
I can process the scanned image well enough to get pretty much what I want except thos solid areas representing the buildings which, rather than a solid color are two colors. I have no problem manipulating the palette, reducing it etc. But now I get to the point where what should be solid (say) orange has (say) white pixels. I do not want to touch the rest of the image at all, only convert those specks of white to orange. Assume the white is P1 (palette#1) and the orange is P5. My algorithm would be:
10 Get next pixel
20 If not = P1 Go to 10
30 If it is not surrounded by 3 or more P5 pixels go to 10
40 Convert pixel to P5
this would only remove the white specks from the orange areas and leave the rest untouched and is pretty simple as far as an algorithm goes. I just don’t know the structure of a BMP file nor how to program in Visual Basic or whatever language one would use for this but this has to be the simplest of things to program so i am surprised it does not exist.
As I say, I can get to a point where it is all acceptable except the specks of white or yellow on the solid color.
This sounds interesting and I will study it but I can already do this with irfanview. in fact, that is pretty much what I have done. the problem is this: I want to process differently the white pixel surrounded by orange than the white pixel bordering with another color. the first one I want to change to orange while the second one I want to leave alone.
I will look into this out of curiosity but I find the command line unappealing and cumbersome and this process souns even more complicated. My filter is simple and would do it in one operation.
I’ll look into it. I can imagine a BMP image file is pretty simple in structure but I have not programmed anything in years and I would have to learn some language programming which could do it. I kind of miss the days when I would program (mainly basic) so I might consider learning some simple language for this kind of thing.
I used DOS until about 1997, long after WIN95 had come out. I used to say GUI was for dummies and intelligent people did not need the fancy colors and preferred the command line. Well, now I am used to the GUI and hate the command line. As I say, I have been using Besweet and hate it. It has a GUI which is plain awful so I use it from the command line. I takes me back to the days when I had to type every command five times before I got it right. With irfanview I can click here or there an see the result instantly. Click Ctrl-Z and undo it to try something else. Now compare that with typing the command line five times before it works. Then go open the resulting file to see the result. Forget it. I will use it if I have to but not if I can avoid it. For audio I mostly use Cool Edit (GUI) but for a few specific things I need to use BeSweet from the command line and it is a hassle. I realise many of these programs are written by nerds for nerds and they would rather put effort into the main program than into the GUI but for the user’s convenience GUI is the way to go. One that works, not like Besweet.
The solid are is perfect but it comes at the expense of the other parts. I think the despeckle is the closest to what I am looking for although it does not replace the pixel with the palette color of the next pixel a I would like, but rather it blurs the are and creates new colors. Still I am playing with the despeckle filter a it seems the closest to what I need.
>> In Photoshop, you could try the Smart Blur filter, that will blur an area but will stay within the lines, so to speak.
theclam, that won’t work. I am just playing around but that is a section of a large city map and it is not practical to retouch blocks one by one.
I am still thinking about this (although not too much). I cannot find a filter that will do what I want and I am thinking it would be extremely easy to program… if I knew how to program.
The 256 color palette BMP file has an extremely simple structure. Each byte represents one pixel and I am thinking of an algorithm sort of like this:
Assume the two colors involved are X and Y. For each byte (pixel) P do:
If value of P is not X then go to next pixel
If value of P is X then calculate variable V which has a value of +2 for every adjacent pixel = Y and, +1 for every corner pixel =Y (max 12, min 0).
If V>5 then make P=Y
Go on to next byte, pixel.
This seems very easy to program. I have not programmed in ages and I am totally out of practice. What would be a simple language for this? I have thought of taking up visual Basic but it seems much more complicated than the old Basic just for fumbling around with small things like this. Any advice? Anyone wanna help? I can program the whole thing in plain language but I need help coding in any specific language. Which one would be the easiest for me to do this?
I thought I posted some suggestions on this earlier [mostly stuff I’d looked up on writing filters for PSP, because I, too, was curious - alas, now mostly forgotten. I should have kept a copy]
However, you can probably accomplish this in VirtualDub (a nice freeware video program) There are a few free filters commonly used to despeckle cartoons and make the fields of color more uniform so they will compress better. The filters are open-source, and Virtual Dub also has a development kit for writing/modifying your own.
Also, I did a quit test run on your original scan in an old version of Photoshop 6 (I’m on an old Win2K PC in my bedroom, which isn’t set up for graphics, and I don’t want to go to my office computer, because my knee is recovering from a recent abuse). I got decent results with filters and palette changes alone. I’m sure you’d get better results with the current GIMP or whatever
convert to 16M colors (because PSP’s filters are 24bit)
apply the median cut filter repeatedly, until you see no change
reduce to a 16color “Optimized median cut” palette
increase pallete to 16M (24-bit colors) for more filter work
apply despeckle filter repeatedly intil you see no change
It’s not perfect (a few undesired solid color regions at edge interfaces), but pretty good for 2-3 minutes of experiments, and it completely preserves the original palette and legibility. At the very least, it is a good starting point for further experiments.
I find this problem interesting, and would appreciatefeedback on how this procedure works for you - specifically where it falls short for your application. I’m no expert in this field, but I love a good. I wish I could be more specific to the programs you are using, but as I said, this is an old computer, and I don’t do graphics on it.
Though I really should install a less ancient version of Paintshop Pro.
KP. thanks for the idea but I have been trying all sorts of things ans any changes to the other parts of the other parts just make them quite worse so i need something which will change what i want while not touching the rest.
I am feeling inclined to try to do it with the old QBasic. As I am planning some travel which will mean many hour to kill at airports I may just try it on my laptod during those hours to kill. It will surely be a good way to kill time.
It’s just that I have forgotten all I knew about QBASIC and I wonder if, rather than re-learning it, it might be a better idea to put a bit more effort into learning something a bit more up to date.
Oops, my Paintshop Pro v8 (from JASC, not Photoshop from Adobe) CD is in the office, but my old PSP 7 CD was here, and it has a built-in filter called “Edge Preserving Smooth” that does a nearly perfect job in one pass, if you crank the strength up all the way.
Considering this is a 2002 version, I think PSP 8 (from JASC) should be even more capable for your application. Photoshop (from Adobe) probably can too, but I don’t personally like it as much (but they are very similar, and can even use each other’s plug-ins)
MSPaint has always been rather rudimentary. IRfanview, IIRC, was mostly a viewer when I tried it. Photodeluxe might accept filter plugins, but not the versions that came with my scanners (I don’t even bother installing them anymore) Have you Googled for user-written ImageMagick filters that replicate this function? It’s always been a pretty common issue (even “way back when”), so if PSP had it licked in 2002, I’d guess ImageMagick has it by now.