将BMP图像转换为绘图仪的指令集?

我有一个这样的绘图仪: PloterXY设备。

我必须执行的任务是将24位BMP转换为该绘图仪的一组指令。 在绘图仪中,我可以改变16种常见的颜色。 我面临的第一个复杂性就是颜色的减less。 我面对的第二个复杂性是如何将像素转换成绘图指令集。

因为使用油漆的绘画工具刷将被使用。 这意味着绘图机的绘制线不会太小,而且会比较短。

请提出可以用来解决这个图像数据转换问题的algorithm?

一些初步结果:

花1-颜色减少。

花2  - 颜色减少。

花3  - 颜色减少。

抖动

那么今天我得到了一些这样的结果。 你没有提供你的绘图仪调色板,所以我从你的结果图像中提取,但你可以使用任何。 抖动背后的想法很简单,我们的理解是将颜色集中在区域而不是单个像素上,所以您必须使用渲染的颜色差异累加器和应该渲染的颜色差异,并将其添加到下一个像素中。

这样,该区域具有大致相同的颜色,但实际上仅使用离散数量的颜色。 如何更新此信息的forms可以将分支抖动的结果与许多方法区分开来。 简单明了的是这样的:

  1. 将颜色累加器重置为零
  2. 处理所有像素
    1. 为每个像素添加颜色到累加器
    2. 在调色板中find最接近的匹配结果
    3. 渲染选定的调色板颜色
    4. 从累加器中减去选定的调色板颜色

在这里你的input图像(我把它们放在一起):

输入

这里的结果图像为您的来源:

结果

左上angular的颜色方块就是我用过的调色板(从图像中提取)。

这里代码( C ++ )我这样做:

picture pic0,pic1,pic2; // pic0 - source img // pic1 - source pal // pic2 - output img int x,y,i,j,d,d0,e; int r,g,b,r0,g0,b0; color c; List<color> pal; // resize output to source image size clear with black pic2=pic0; pic2.clear(0); // create distinct colors pal[] list from palette image for (y=0;y<pic1.ys;y++) for (x=0;x<pic1.xs;x++) { c=pic1.p[y][x]; for (i=0;i<pal.num;i++) if (pal[i].dd==c.dd) { i=-1; break; } if (i>=0) pal.add(c); } // dithering r0=0; g0=0; b0=0; // no leftovers for (y=0;y<pic0.ys;y++) for (x=0;x<pic0.xs;x++) { // get source pixel color c=pic0.p[y][x]; // add to leftovers r0+=WORD(c.db[picture::_r]); g0+=WORD(c.db[picture::_g]); b0+=WORD(c.db[picture::_b]); // find closest color from pal[] for (i=0,j=-1;i<pal.num;i++) { c=pal[i]; r=WORD(c.db[picture::_r]); g=WORD(c.db[picture::_g]); b=WORD(c.db[picture::_b]); e=(r-r0); e*=e; d =e; e=(g-g0); e*=e; d+=e; e=(b-b0); e*=e; d+=e; if ((j<0)||(d0>d)) { d0=d; j=i; } } // get selected palette color c=pal[j]; // sub from leftovers r0-=WORD(c.db[picture::_r]); g0-=WORD(c.db[picture::_g]); b0-=WORD(c.db[picture::_b]); // copy to destination image pic2.p[y][x]=c; } // render found palette pal[] (visual check/debug) x=0; y=0; r=16; g=pic2.xs/r; if (g>pal.num) g=pal.num; for (y=0;y<r;y++) for (i=0;i<g;i++) for (c=pal[i],x=0;x<r;x++) pic2.p[y][x+(i*r)]=c; 

picture是我的图片类,所以这里有一些成员:

  • xs,ys分辨率
  • color p[ys][xs]直接像素访问(32位像素格式,因此每个通道8位)
  • clear(DWORD c)用图像填充图像c

color只是DWORD ddBYTE db[4]的简单通道访问的联合。

List<>是我的模板(dynamic数组/列表)

  • List<int> aint a[]相同。
  • add(b)在列表的末尾添加b
  • 数量是列表中的项目数量

现在为了避免太多的点(为了你的绘图仪的寿命),你可以使用不同的线条模式等,但是这需要大量的试验/错误…例如,你可以计算某个区域使用了多less次颜色并从这个比例使用不同的填充模式(基于线)。 您需要在图像质量和渲染速度/耐久性之间进行select…

如果没有关于绘图仪function(速度,换刀方法,颜色组合行为)的更多信息,很难确定形成控制stream的最佳方法。 我敢打赌,你手动改变颜色,所以你会一次呈现每种颜色。 因此,提取所有像素与第一个工具的颜色合并相邻像素线/曲线和渲染…然后移动到下一个工具颜色…