Matrix Size | Value Range Generated by bluenoiseex() | File Size | Value Range Generated by bluenoise() |
---|---|---|---|
256×256 | 0–0x0000ffff (0–65,535) | Embedded data, no file | 0–0x00007fff (0–32,767) |
512×512 | 0–0x0003ffff (0–262,143) | 1 MB | 0–0x00007fff (0–32,767) |
1024×1024 | 0–0x000fffff (0–1,048,575) Sufficient as a substitute for random sequences | 4 MB | 0–0x00007fff (0–32,767) |
2048×2048 | 0–0x003fffff (0–4,194,303) | 16 MB | 0–0x00007fff (0–32,767) |
4096×4096 | 0–0x00ffffff (0–16,777,215) 24-bit color image range | 64 MB | 0–0x00007fff (0–32,767) |
8192×8192 | 0–0x03ffffff (0–67,108,863) Used for wide-format printers (e.g., national archive projects) | 256 MB | 0–0x00007fff (0–32,767) |
16384×16384 | 0–0x0fffffff (0–268,435,455) No known use cases (possible splitting for CYMK matrices) | 1024 MB (1 GB) | 0–0x00007fff (0–32,767) |
/////////////////////////////// // Set the seed for the blue noise sequence // int seed; seed value // Return Value // Negative....Error (INITIALIZE_ERROR...Initialization error (failed to create class instance: insufficient memory)) typedef int (__stdcall* SBLUENOISE)(int seed); extern SBLUENOISE sbluenoise; ///////////////////////// // Retrieve the blue noise sequence (0–RAND_MAX) // RAND_MAX is 0x7fff (32767), so it is coarse // Return Value // Negative....Error (INITIALIZE_ERROR...Initialization error (failed to create class instance: insufficient memory)) // Blue noise sequence typedef int (__stdcall* BLUENOISE)(); extern BLUENOISE bluenoise; ///////////////////////// // Retrieve a high-precision blue noise sequence (0–size*size) // Even without using files, sizes (256*256) provide 0–65535, which is detailed // 256* 256 0–0x0000ffff (0–65535-1) Without using files // 512* 512 0–0x0003ffff (0–262143-1) 1 MB // 1024* 1024 0–0x000fffff (0–1048575-1) 4 MB // 2048* 2048 0–0x003fffff (0–4194304-1) 16 MB // 4096* 4096 0–0x00ffffff (0–16777216-1) 64 MB // 8192* 8192 0–0x03ffffff (0–67108864-1) 256 MB // 16384*16384 0–0x0fffffff (0–268435456-1) 1024 MB (1 GB) // Return Value // Negative....Error (INITIALIZE_ERROR...Initialization error (failed to create class instance: insufficient memory)) // Blue noise sequence typedef int (__stdcall* BLUENOISEEX)(); extern BLUENOISEEX bluenoiseex; ///////////////////////// // Set the folder for saving/loading the blue noise matrix and set the matrix size // This is not set for generating normal blue noise in the range of 0–RAND_MAX // It is set for retrieving high-precision blue noise with bluenoiseex() // Input // const char* pfolder; Folder name where the matrix file exists/is generated // If pointing to NULL or "", the built-in 256×256 matrix is used // int size; Matrix size (512/1024/2048/4096/8192/16384) // If 1024, a 1024×1024 blue noise matrix is generated. File size is 4 MB // Return Value // Negative....Error (INITIALIZE_ERROR...Initialization error (failed to create class instance: insufficient memory)) // Negative....Error (FILE_OPEN_ERROR...Unable to save or read the file) // (MEMORY_SHORTAGE...Insufficient memory) // Reads the file named sizexsizeraw.dat in the specified folder // If size is 1024, the file name is 1024x1024raw.dat // If the file does not exist, it is created // Larger sizes generate higher-quality blue noise typedef int (__stdcall* SETBLUENOISEMATRIX)(const char* pfolder,int size); extern SETBLUENOISEMATRIX setbluenoisematrix;The loading and releasing of the DLL are as follows:
#include "bluenoisecallback.h" HINSTANCE bn_dllinstance; // DLL instance // DLL Entry Points SBLUENOISE sbluenoise; BLUENOISE bluenoise; BLUENOISEEX bluenoiseex; SETBLUENOISEMATRIX setbluenoisematrix; ORDEREDDITHER2 ordereddither2; ORDEREDDITHER4 ordereddither4; ORDEREDDITHERLINE2 orderedditherline2; ORDEREDDITHERLINE4 orderedditherline4; { // .... // Load // gmodulepath contains the path of the executable file. // Assume "bluenoisedll.dll" is in the executable path char filename[FILENAME_MAX]; sprintf(filename,"%sbluenoisedll.dll",gmodulepath); bn_dllinstance = LoadLibrary(filename); if(bn_dllinstance == NULL) { char buffer[512]; sprintf(buffer,"Failed to load DLL file bluenoisedll.dll"); AfxMessageBox(buffer,MB_OK | MB_ICONEXCLAMATION); return(2); } sbluenoise = (SBLUENOISE)GetProcAddress(bn_dllinstance,"sbluenoise"); bluenoise = (BLUENOISE)GetProcAddress(bn_dllinstance,"bluenoise"); bluenoiseex = (BLUENOISEEX)GetProcAddress(bn_dllinstance,"bluenoiseex"); setbluenoisematrix = (SETBLUENOISEMATRIX)GetProcAddress(bn_dllinstance,"setbluenoisematrix"); if(sbluenoise == NULL || bluenoise == NULL || bluenoiseex == NULL || setbluenoisematrix == NULL) { char buffer[512]; sprintf(buffer,"Version mismatch for DLL file bluenoisedll.dll(or bluenoiseutf8dll)"); AfxMessageBox(buffer,MB_OK | MB_ICONEXCLAMATION); FreeLibrary(bn_dllinstance); return(2); } ordereddither2 = (ORDEREDDITHER2)GetProcAddress(bn_dllinstance,"ordereddither2"); ordereddither4 = (ORDEREDDITHER2)GetProcAddress(bn_dllinstance,"ordereddither4"); orderedditherline2 = (ORDEREDDITHERLINE2)GetProcAddress(bn_dllinstance,"orderedditherline2"); orderedditherline4 = (ORDEREDDITHERLINE4)GetProcAddress(bn_dllinstance,"orderedditherline4"); if(ordereddither2 == NULL || ordereddither4 == NULL || orderedditherline2 == NULL || orderedditherline4 == NULL) { char buffer[512]; sprintf(buffer,"Version mismatch for DLL file bluenoisedll.dll(or bluenoiseutf8dll)"); AfxMessageBox(buffer,MB_OK | MB_ICONEXCLAMATION); FreeLibrary(bn_dllinstance); return(2); } // .... // Release FreeLibrary(bn_dllinstance); }
// Set 1000 bluenoise sequences in m_editresult and display them in an edit box or similar void CDlgBluenoise::OnBnClickedMakebluenoise100() { m_editresult = ""; char buffer[1024]; for(int i = 0 ; i < 1000 ; i++) { if(i % 10 == 0) { sprintf(buffer,"(%03d)",i / 10); m_editresult += buffer; } if(i % 10 == 9) { sprintf(buffer,"%10d\r\n",bluenoise()); } else { sprintf(buffer,"%10d, ",bluenoise()); } m_editresult += buffer; } UpdateData(FALSE); }The call to setbluenoisematrix() for creating a new matrix (usually larger than the initial size of 256×256) is as follows.
// In the sample program below, the folder is "g:/tmp/", but normally a different folder is specified.
// m_editsize contains a value in the range of 512 to 16384 void CDlgBluenoise::OnBnClickedSetsize() { UpdateData(TRUE); if(m_editsize == 256) { setbluenoisematrix("",m_editsize); } else { setbluenoisematrix("g:\\tmp\\",m_editsize); } UpdateData(FALSE); }
// 1...ordered dither utility // do ordered dither (for grayscale image only) // for multiplane image (e.g., RGB, CMYK), use class library or add API to this library. // input // int width; image width (pixel) // int height; image height (pixel) // int scanlinesize1; scanline size (byte count) of one line image // unsigned char* pdata1; 256 level image // int scanlinesize2; scanline size (byte count) of 2 or 4 level image // output // unsigned char* pdata2; 2 or 4 level image (one pixel is one byte) // 2 levels have values (0, 255) // 4 levels have values (0, 85, 170, 255) // return value // Negative value...error (INITIALIZE_ERROR...Initialization error (failed to create class instance: memory shortage) // error (FILE_OPEN_ERROR...Failed to save or load blue noise matrix data) // error (MEMORY_SHORTAGE...Memory shortage)) // This library reads "sizexsizeraw.dat" in the folder specified by setbluenoisematrix(). // If "size" is 1024, the file name is "1024x1024raw.dat". // If "sizexsizeraw.dat" does not exist, setbluenoisematrix() API generates the file automatically. // Larger "size" values result in higher dithering quality. typedef int (__stdcall* ORDEREDDITHER2)(int width, int height, int scanlinesize1, unsigned char* pdata1, int scanlinesize2, unsigned char* pdata2); extern ORDEREDDITHER2 ordereddither2; typedef int (__stdcall* ORDEREDDITHER4)(int width, int height, int scanlinesize1, unsigned char* pdata1, int scanlinesize2, unsigned char* pdata2); extern ORDEREDDITHER4 ordereddither4; // ordered dither utility // line-by-line process // INPUT // int y; line number (0, ..., height - 1) typedef int (__stdcall* ORDEREDDITHERLINE2)(int width, int y, unsigned char* pdata1, unsigned char* pdata2); extern ORDEREDDITHERLINE2 orderedditherline2; typedef int (__stdcall* ORDEREDDITHERLINE4)(int width, int y, unsigned char* pdata1, unsigned char* pdata2); #extern ORDEREDDITHERLINE4 orderedditherline4;
// 1...Structured Dithering Utility // Performs structured dithering for grayscale images // Structured dithering for multiplane images (e.g., RGB, CMYK) is supported in the C++ class library. // For multiplane images, use the class library or extend this library’s API. // INPUT // int width; Image width (pixel) // int height; Image height (pixel) // int scanlinesize1; Scanline size of pdata1 (bytes per line of image) // unsigned char* pdata1; 256-level image (1 pixel per byte) // int scanlinesize2; Scanline size of pdata2 (bytes per line of image) // OUTPUT // unsigned char* pdata2; 2 or 4-level image (1 pixel per byte) // 2 levels: (0/255) // 4 levels: (0/85/170/255) // RETURN VALUE // Negative value...error (INITIALIZE_ERROR...Initialization error (failed to create class instance: memory shortage)) // error (FILE_OPEN_ERROR...Failed to save or load blue noise data) // error (MEMORY_SHORTAGE...Memory shortage)) // This library saves/loads files with the name "sizexsizeraw.dat" in the folder specified by setbluenoisematrix(). // For example, if "size" is 1024, the file name is "1024x1024raw.dat". // If the file does not exist, setbluenoisematrix() automatically creates blue noise and saves it with the name "sizexsizeraw.dat". // Larger "size" values result in higher dithering quality. typedef int (__stdcall* ORDEREDDITHER2)(int width, int height, int scanlinesize1, unsigned char* pdata1, int scanlinesize2, unsigned char* pdata2); extern ORDEREDDITHER2 ordereddither2; typedef int (__stdcall* ORDEREDDITHER4)(int width, int height, int scanlinesize1, unsigned char* pdata1, int scanlinesize2, unsigned char* pdata2); extern ORDEREDDITHER4 ordereddither4; // Structured Dithering // Line-by-line dithering (e.g., for printer drivers processing one line at a time) // INPUT // int y; Line number (0 to height - 1) typedef int (__stdcall* ORDEREDDITHERLINE2)(int width, int y, unsigned char* pdata1, unsigned char* pdata2); extern ORDEREDDITHERLINE2 orderedditherline2; typedef int (__stdcall* ORDEREDDITHERLINE4)(int width, int y, unsigned char* pdata1, unsigned char* pdata2); #extern ORDEREDDITHERLINE4 orderedditherline4;
int width = mppimage[0]->mgetrawwidth(); // Width of the original 256-level grayscale image (pixels) int height = mppimage[0]->mgetrawheight(); // Height of the original 256-level grayscale image (pixels) int scanlinesize = mppimage[0]->mgetrawscanlinesize(); // Scanline size of the original 256-level grayscale image (bytes) unsigned char* pdata1 = mppimage[0]->mgetrawdata(); // Original 256-level grayscale image (scanlinesize * height bytes) unsigned char* pdata2 = (unsigned char*)malloc(scanlinesize * height); // 2/4-level dithered grayscale image (scanlinesize * height bytes) // For 2 levels, luminance values are 0/255 // For 4 levels, luminance values are 0/85/170/255 if(pdata2 != NULL) { ordereddither2(0, width, height, scanlinesize, pdata1, scanlinesize, pdata2); free(pdata2); }Line Processing Sample Program
int width = mppimage[0]->mgetrawwidth(); // Width of the original 256-level grayscale image (pixels) int height = mppimage[0]->mgetrawheight(); // Height of the original 256-level grayscale image (pixels) int scanlinesize = mppimage[0]->mgetrawscanlinesize(); // Scanline size of the original 256-level grayscale image (bytes) unsigned char* pdata1 = mppimage[0]->mgetrawdata(); // Original 256-level grayscale image (scanlinesize * height bytes) unsigned char* pdata2 = (unsigned char*)malloc(scanlinesize * height); // 2/4-level dithered grayscale image (scanlinesize * height bytes) // For 2 levels, luminance values are 0/255 // For 4 levels, luminance values are 0/85/170/255 if(pdata2 != NULL) { for(int i = 0 ; i < height ; i++) { unsigned char* ps1 = pdata1 + i * scanlinesize; unsigned char* ps2 = pdata2 + i * scanlinesize; orderedditherline4(0, width, i, ps1, ps2); } free(pdata2); }