问题
I'm developing a custom thin-client server that serves rendered webpages to its clients. Server is running on multicore Linux box, with Webkit providing the html rendering engine.
The only problem is the fact that clients display is limited with a 4bit (16 colors) grayscale palette. I'm currently using LibGraphicsMagick to dither images (RGB->4bit grayscale), which is an apparent bottleneck in the server performance. Profiling shows that more than 70% of time is spent running GraphicsMagick dithering functions.
I've explored stackoverflow and the Interwebs for a good high performance solution, but it seems that nobody did any benchmarks on various image manipulation libraries and dithering solutions.
I would be more that happy to find out:
- What are the highest performance libraries in regards to dithering / halftoning / quantizing RGB images to 4bit grayscale.
- Are there any specilized dithering libs or any public domain code snippets that you could point me to?
- What libraries do you prefer for manipulating graphics in regards to high performance?
C language libraries are prefered.
回答1:
Dithering is going to take quite a bit of time depending on the algorithm chosen.
It's fairly trivial to implement Bayer (Matrix) and Floyd-Steinberg (Diffusion) dithering.
Bayer filtering can be made extremely fast when coded with with MMX/SSE to process parallel pixels. You may also be able to do the dithering / conversion using a GPU shader.
FWIW, you're already using GraphicsMagick but there's an entire list of OSS graphics libraries here
回答2:
From the list provided by Adisak, without any testing, I would bet on AfterImage. The Afterstep people are obsessed with speed, and also described a clever algorithm.
You could take an alternative approach, if your server could be equipped with a decent PCI-express graphics card featuring OpenGL. Here are some specs from Nvidia. Search for "index mode". What you could do is select a 16 or 256 color display mode, render your image as a texture on a flat polygon (like the side of cube) and then read the frame back.
When reading a frame from an OpenGL card, it is important that bandwidth is good from the card, hence the need for PCI-express. As the documentation says, you also have to choose your colors in indexed mode for decent effects.
回答3:
I know it's not a C library, but this got me curious about what's available for .NET to do error-diffusion which I used some 20 years ago on a project. I found this and specifically this method.
But to try be helpful :) I found this C library.
回答4:
Here is an implementation of the Floyd-Steinberg method for half-toning:
#include <opencv2/opencv.hpp>
using namespace cv;
int main(){
uchar scale = 128; // change this parameter to 8, 32, 64, 128 to change the dot size
Mat img = imread("../halftone/tom.jpg", CV_LOAD_IMAGE_GRAYSCALE);
for (int r=1; r<img.rows-1; r++) {
for (int c=1; c<img.cols-1; c++) {
uchar oldPixel = img.at<uchar>(r,c);
uchar newPixel = oldPixel / scale * scale;
img.at<uchar>(r,c) = newPixel;
int quantError = oldPixel - newPixel;
img.at<uchar>(r+1,c) += 7./16. * quantError;
img.at<uchar>(r-1,c+1) += 3./16. * quantError;
img.at<uchar>(r,c+1) += 5./16. * quantError;
img.at<uchar>(r+1,c+1) += 1./16. * quantError;
}
}
imshow("halftone", img);
waitKey();
}
来源:https://stackoverflow.com/questions/1487517/fastest-dithering-halftoning-library-in-c