基本上我需要将位图图像转换为字符串,但这不是常见的。
困境是这个字符串由两部分组成:
1)积分 2)行
我需要将图像转换为由*。
分隔的两个部分我给出的一个例子是:
"221A*221A270A270A2503250320072007171617160D2A0D2A07380738073F073F0B3E0B3E15311531222122212C182C183016301631173117311A311A302230222E272E272D2C2D2C2C2F2C2F2C312C312C2F2C2F2E2B2E2B3126312633223322371D371D381C381C3B1B3B1B3C1C3C1C3D1F3D1F3D243D243C2D3C2D3A333A333A363A36393939393B383B383D363D36412E412E46264626492049204B1B4B1B4E184E184F174F175017501751185118511D511D51225122502450244F294F294F2C4F2C4E2F4E2F4F314F315030503052305230552C552C582958295D225D22601E601E611C611C621B621B621A621A601A601A5D1B5D1B5B1E5B1E5723572353285328512B512B502E502E502F502F513151315231523154305430582E582E592D592D5C2C5C2C5F2A5F2A6428642865286528692669266D246D247122712275207520791D791D7D1B7D1B81198119841884188618861887198719881A881A891B891B881C881C871E871E861F861F852085208421842182228222812481247F257F257E257E257D257D257C247C247C217C217D1F7D1F7E1C7E1C801A801A81198119821782178317831784188418851A851A851C851C86208620862286228625862587278727872B872B882E882E893289328A338A338E348E349033903393329332972F972F9A2D9A2D9F299F29A426A426AB20AB20AF1CAF1CB517B517B716B716B716"
所以我所知道的是,221A是点,而另一个字符串是线,但需要能够实现这一点。
你以前有没有遇到过这个?
我尝试将位图转换为Base64String,但这并不能让我的任何东西靠近。
如果它帮助我只在VB中反向,即从字符串到图像:
Private Sub unpackBMP(ByVal BITMAP As String)
Dim points As String
Dim lines As String
Dim x As Long
Dim y As Long
Dim x1 As Long
Dim y1 As Long
points = firstItem(BITMAP, "*")
lines = BITMAP
While Len(points) > 0
x = "&H" & Mid(points, 1, 2)
y = "&H" & Mid(points, 3, 2)
points = Mid(points, 5, Len(points) - 4)
'picDraw.PSet (Val(x), Val(y)), vbBlack
'Call picDraw.DrawPoint(CDbl(x), CDbl(y))
'picDraw.Refresh
Wend
While Len(lines) > 0
x = "&H" & Mid(lines, 1, 2)
y = "&H" & Mid(lines, 3, 2)
x1 = "&H" & Mid(lines, 5, 2)
y1 = "&H" & Mid(lines, 7, 2)
lines = Mid(lines, 9, Len(lines) - 8)
'picDraw.Line (Val(x), Val(y))-(Val(x1), Val(y1)), vbBlack
'Call picDraw.DrawLine(CDbl(x), CDbl(y), CDbl(x1), CDbl(y1), 0)
'picDraw.Refresh
Wend
'Call picDraw.DrawLine(lines(1, tmp), lines(2, tmp), lines(3, tmp), lines(4, tmp), 0)
End Sub
Public Function firstItem(pstrItems As String, pstrDelim As String) As String
Dim lngPos As Long
Dim strRes As String
'Dim strDelim As String
strRes = ""
lngPos = InStr(pstrItems, pstrDelim)
If lngPos > 0 Then
strRes = Left$(pstrItems, lngPos - 1)
pstrItems = Mid$(pstrItems, lngPos + 1)
Else
strRes = pstrItems
pstrItems = ""
End If
firstItem = strRes
End Function
如果您需要任何进一步的详细信息,请与我们联系。
背景:这是Windows Mobile 6.5设备上的图片框中的签名。请参阅下面的图像及其相关字符串。希望这会有所帮助。
String for SIGNATURE 280172:
3711*371127152715103510351F2C1F2C312231223C1C3C1C3D203D20352D352D333233323D2E3D2E52225222671A671A6C196C196D1A6D1A6D1D6D1D69226922652665266428642864296429652965296E236E23781E781E8718871891179117961896189A199A199B1B9B1B9D1E9D1E9F209F20A021A021A021
添加附件堆栈使其成为png但它是bmp文件,但它是204 x 64 1位深度图像。
重新排序的字符串(由Spektre提供)
3711*3711
2715 2715
1035 1035
1F2C 1F2C
3122 3122
3C1C 3C1C
3D20 3D20
352D 352D
3332 3332
3D2E 3D2E
5222 5222
671A 671A
6C19 6C19
6D1A 6D1A
6D1D 6D1D
6922 6922
6526 6526
6428 6428
6429 6429
6529 6529
6E23 6E23
781E 781E
8718 8718
9117 9117
9618 9618
9A19 9A19
9B1B 9B1B
9D1E 9D1E
9F20 9F20
A021 A021 A021
单个水平线会生成以下字符串:
101F*101F
1D21 1D21
2121 2121
2820 2820
2C20 2C20
3120 3120
3921 3921
3F21 3F21
4521 4521
4A21 4A21
5122 5122
5822 5822
6121 6121
6421 6421
6721 6721
6A20 6A20
6C20 6C20
6F20 6F20
7220 7220
7520 7520
7720 7720
7920 7920
7D20 7D20
8020 8020
8120 8120
8320 8320
861F 861F
871F 871F
891F 891F
8A1F 8A1F
8D1F 8D1F
8F1F 8F1F
931F 931F
961F 961F
971F 971F
9A1F 9A1F
9C1F 9C1F
9D1E 9D1E
A11E A11E
A31E A31E
A51D A51D
A71D A71D
A91D A91D
AA1C AA1C
AB1C AB1C
AD1C AD1C
AE1C AE1C
B01C B01C
B11B B11B
B21B B21B
B41B B41B
B51A B51A
B61A B61A
B81A B81A
B919 B919
BB19 BB19
BC19 BC19
BD19 BD19
BE19 BE19
BF19 BF19
C019 C019
C11A C11A
C31A C31A
C41A C41A
C51A C51A
C61B C61B
C71B C71B
C81C C81C
C81C
因此,这就是使PictureBox签名成为字符串的原因:
'signature
Public gSigPoints() As Long
Public gSigLines() As Long
Public gSigPointCount As Long
Public gSigLinesCount As Long
Public Function PackBMP() As String
Dim tmpStr1 As String
Dim tmpStr2 As String
Dim tmpStr3 As String
Dim tmpStr4 As String
Dim tmp As Long
gJob_Signature = ""
For tmp = 1 To gSigPointCount
tmpStr1 = CStr(Hex(gSigPoints(1, tmp)))
tmpStr2 = CStr(Hex(gSigPoints(2, tmp)))
If Len(tmpStr1) = 2 And Len(tmpStr2) = 2 Then
gJob_Signature = gJob_Signature & tmpStr1 & tmpStr2 '& ";" & ";"
Else
If Len(tmpStr1) = 1 Then tmpStr1 = "0" & tmpStr1
If Len(tmpStr2) = 1 Then tmpStr2 = "0" & tmpStr2
If Len(tmpStr1) = 2 And Len(tmpStr2) = 2 Then
gJob_Signature = gJob_Signature & tmpStr1 & tmpStr2 '& ";"& ";"
End If
End If
Next 'tmp
gJob_Signature = gJob_Signature & "*"
For tmp = 1 To gSigLinesCount
tmpStr1 = CStr(Hex(gSigLines(1, tmp)))
tmpStr2 = CStr(Hex(gSigLines(2, tmp)))
tmpStr3 = CStr(Hex(gSigLines(3, tmp)))
tmpStr4 = CStr(Hex(gSigLines(4, tmp)))
If Len(tmpStr1) = 2 And Len(tmpStr2) = 2 And Len(tmpStr3) = 2 And Len(tmpStr4) = 2 Then
gJob_Signature = gJob_Signature & tmpStr1 & tmpStr2 & tmpStr3 & tmpStr4 '& ";"
Else
If Len(tmpStr1) = 1 Then tmpStr1 = "0" & tmpStr1
If Len(tmpStr2) = 1 Then tmpStr2 = "0" & tmpStr2
If Len(tmpStr3) = 1 Then tmpStr3 = "0" & tmpStr3
If Len(tmpStr4) = 1 Then tmpStr4 = "0" & tmpStr4
If Len(tmpStr1) = 2 And Len(tmpStr2) = 2 And Len(tmpStr3) = 2 And Len(tmpStr4) = 2 Then
gJob_Signature = gJob_Signature & tmpStr1 & tmpStr2 & tmpStr3 & tmpStr4 '& ";"
End If
End If
Next 'tmp
End Function
Public Sub DrawBMP(ByRef pic As PictureBox)
Dim x As Long
pic.Cls
For x = 1 To gSigPointCount
Call pic.DrawPoint(gSigPoints(1, x), gSigPoints(2, x))
Next x
For x = 1 To gSigLinesCount
Call pic.DrawLine(gSigLines(1, x), gSigLines(2, x), gSigLines(3, x), gSigLines(4, x), 0)
Next x
pic.Refresh
End Sub
Public Sub AddPoint(x As Long, Y As Long)
gSigPointCount = gSigPointCount + 1
ReDim Preserve gSigPoints(2, gSigPointCount)
gSigPoints(1, gSigPointCount) = x
gSigPoints(2, gSigPointCount) = Y
End Sub
Public Sub AddLine(x As Long, Y As Long, x1 As Long, y1 As Long)
gSigLinesCount = gSigLinesCount + 1
ReDim Preserve gSigLines(4, gSigLinesCount)
gSigLines(1, gSigLinesCount) = x
gSigLines(2, gSigLinesCount) = Y
gSigLines(3, gSigLinesCount) = x1
gSigLines(4, gSigLinesCount) = y1
End Sub
'********signature
Private miX As Double
Private miY As Double
Private isup As Boolean
'*********end of signature
'@@ singnatures
Private Sub picDraw_MouseDown(Button As Long, Shift As Long, x As Double, Y As Double)
picDraw.DrawPoint x, Y, 0
picDraw.Refresh
Call AddPoint(x, Y)
miX = x
miY = Y
isup = False
End Sub
Private Sub picDraw_MouseMove(Button As Long, Shift As Long, x As Double, Y As Double)
If isup Then
miX = x
miY = Y
isup = False
Else
If Button = 1 Then
picDraw.DrawLine miX, miY, x, Y, 0
picDraw.Refresh
Call AddLine(miX, miY, x, Y)
miX = x
miY = Y
End If
End If
End Sub
Private Sub picDraw_MouseUp(ByVal Button As Long, ByVal Shift As Long, ByVal x As Double, ByVal Y As Double)
isup = True
End Sub
这是关于签名图片框的全部内容。
答案 0 :(得分:0)
我从您发布的代码中找出了编码(不得不将其移植到C ++),所以编码:
字符串以点列表开头
每个点都以4位十六进制数表示。前2个十六进制数字是x
坐标,后2个数字是y
坐标点。 (可能标记每个鼠标按下事件,因此它保存有关连续绘制图像的数量的信息)
然后分隔符*
跟随
每行包含2个点,因此每行总共有8位十六进制数。序列是x0,y0,x1,y1
每个坐标的2位十六进制数。如果字符串仅包含4位十六进制数字(结尾),则标记签名字符串的结尾。
因此,当您想制作自己的签名代码时:
清除点列表和行列表
将当前鼠标/笔位置添加到点列表中,并作为行列表的起点
首先查看鼠标按钮是否仍然被点击或笔仍然敲击打击垫。如果不忽略此事件。如果是,则将当前鼠标位置添加到行列表两次(这就是为什么它们重复第一个结束当前行,第二个开始新行)
关闭实际行,然后将当前鼠标位置添加到行列表
复制行列表中的最后一个点以标记字符串结尾
就是这样。如果您需要转换已经绘制的图像(光栅),那么您可能会遇到比较问题,因为您不太可能以与作者签名相同的方式对图像进行矢量化。导致相同图像的错过匹配。另外三倍的最后一点很可能是因为鼠标/笔上事件的编码错误,同时在mouse move
和mouse up
事件中添加相同的点
以这种方式编码的图像限制为256x256像素。
这是第一个签名字符串的解码图像示例:
signature="221A*221A270A270A2503250320072007171617160D2A0D2A07380738073F073F0B3E0B3E15311531222122212C182C183016301631173117311A311A302230222E272E272D2C2D2C2C2F2C2F2C312C312C2F2C2F2E2B2E2B3126312633223322371D371D381C381C3B1B3B1B3C1C3C1C3D1F3D1F3D243D243C2D3C2D3A333A333A363A36393939393B383B383D363D36412E412E46264626492049204B1B4B1B4E184E184F174F175017501751185118511D511D51225122502450244F294F294F2C4F2C4E2F4E2F4F314F315030503052305230552C552C582958295D225D22601E601E611C611C621B621B621A621A601A601A5D1B5D1B5B1E5B1E5723572353285328512B512B502E502E502F502F513151315231523154305430582E582E592D592D5C2C5C2C5F2A5F2A6428642865286528692669266D246D247122712275207520791D791D7D1B7D1B81198119841884188618861887198719881A881A891B891B881C881C871E871E861F861F852085208421842182228222812481247F257F257E257E257D257D257C247C247C217C217D1F7D1F7E1C7E1C801A801A81198119821782178317831784188418851A851A851C851C86208620862286228625862587278727872B872B882E882E893289328A338A338E348E349033903393329332972F972F9A2D9A2D9F299F29A426A426AB20AB20AF1CAF1CB517B517B716B716B716";
此处为方形示例
signature="0808*080820082008202020200820082008080808";
所以重新订购时:
0808 // point(8h,8h);
* // separator
08 08 20 08 // line( 8h, 8h,20h, 8h)
20 08 20 20 // line(20h, 8h,20h,20h)
20 20 08 20 // line(20h,20h, 8h,20h)
08 20 08 08 // line( 8h,20h, 8h, 8h)
08 08 // not enough points -> end of string
[Edit1]光栅图像到字符串转换
首先,您需要将图像转换为矢量形式。有许多复杂的方法可以将栅格图像多边形化为矢量形式,但它们通常使用来自数学,图像处理,结构等的高级内容......需要有关该主题的广泛知识。我假设你需要这个只是为了在设备上可视化,所以相反我会使用非常简单的转换导致不合理的大结果(与高级方法相比)。如果你的设备对字符串大小没有太小的限制那么你应该没问题,否则你需要使用更先进的东西:
清除您的矢量表示
点数列表和行列表
遍历图像的所有水平线
处理每一行
x0
找到第一个设置的像素x1
找到第一个未设置的像素如果找到x0,x1
(x0,y)
(x0,y,x1-1,y)
整个图像处理后将矢量形式转换为字符串
*
添加到字符串这就是它在C ++中的样子:
// load input 2D BW (binary) image
backbuffer in;
in.bmp->LoadFromFile("in.bmp");
in.resize(in.bmp->Width,in.bmp->Height);
int x0,x1,x,y;
// clear signature vecor represenytation
gSigPoints.num=0;
gSigLines.num=0;
for (y=0;y<in.ys;y++)
for (x=0;x<in.xs;)
{
for (;(x<in.xs)&&(!in.pyx[y][x]);x++); x0=x; // find start of V-line
for (;(x<in.xs)&&( in.pyx[y][x]);x++) x1=x; // find end of V-line
if (x0<in.xs) // add pnt,line to signature
{
gSigPoints.add(x0);
gSigPoints.add(y );
gSigLines.add(x0);
gSigLines.add(y );
gSigLines.add(x1);
gSigLines.add(y );
}
}
// update string and screen
txt=PackBMP();
draw();
in.xs,in.ys
是输入图像分辨率in.pyx[y][x]
是图像像素访问txt
是签名字符串gSigPoints,gSigLines
是包含签名点和行.num
项目数,.add(a)
将a
添加到列表末尾从VB代码移植的打包/解压缩包如下所示:
//---------------------------------------------------------------------------
#include "list.h"
//---------------------------------------------------------------------------
List<DWORD> gSigPoints;
List<DWORD> gSigLines;
// some test examples:
//AnsiString txt="221A*221A270A270A2503250320072007171617160D2A0D2A07380738073F073F0B3E0B3E15311531222122212C182C183016301631173117311A311A302230222E272E272D2C2D2C2C2F2C2F2C312C312C2F2C2F2E2B2E2B3126312633223322371D371D381C381C3B1B3B1B3C1C3C1C3D1F3D1F3D243D243C2D3C2D3A333A333A363A36393939393B383B383D363D36412E412E46264626492049204B1B4B1B4E184E184F174F175017501751185118511D511D51225122502450244F294F294F2C4F2C4E2F4E2F4F314F315030503052305230552C552C582958295D225D22601E601E611C611C621B621B621A621A601A601A5D1B5D1B5B1E5B1E5723572353285328512B512B502E502E502F502F513151315231523154305430582E582E592D592D5C2C5C2C5F2A5F2A6428642865286528692669266D246D247122712275207520791D791D7D1B7D1B81198119841884188618861887198719881A881A891B891B881C881C871E871E861F861F852085208421842182228222812481247F257F257E257E257D257D257C247C247C217C217D1F7D1F7E1C7E1C801A801A81198119821782178317831784188418851A851A851C851C86208620862286228625862587278727872B872B882E882E893289328A338A338E348E349033903393329332972F972F9A2D9A2D9F299F29A426A426AB20AB20AF1CAF1CB517B517B716B716B716";
//AnsiString txt="3711*371127152715103510351F2C1F2C312231223C1C3C1C3D203D20352D352D333233323D2E3D2E52225222671A671A6C196C196D1A6D1A6D1D6D1D69226922652665266428642864296429652965296E236E23781E781E8718871891179117961896189A199A199B1B9B1B9D1E9D1E9F209F20A021A021A021";
AnsiString txt="0808*08082008200820202020082008200808";
//---------------------------------------------------------------------------
AnsiString Hex(DWORD x,DWORD digits)
{
int i;
char *tab="0123456789ABCDEF";
AnsiString s="";
if (digits>8) digits=8;
s.SetLength(digits);
for (i=digits;i>0;i--,x>>=4) s[i]=tab[x&15];
return s;
}
//---------------------------------------------------------------------------
AnsiString PackBMP()
{
DWORD i;
AnsiString sig="";
// all points
for (i=0;i+1<gSigPoints.num;)
{
sig+=Hex(gSigPoints[i],2); i++; // x
sig+=Hex(gSigPoints[i],2); i++; // y
}
// separator
sig+="*";
// all lines
for (i=0;i+3<gSigLines.num;i++)
{
sig+=Hex(gSigLines[i],2); i++; // x0
sig+=Hex(gSigLines[i],2); i++; // y0
sig+=Hex(gSigLines[i],2); i++; // x1
sig+=Hex(gSigLines[i],2); i++; // y1
}
return sig;
}
//---------------------------------------------------------------------------
void UnpackBMP(AnsiString &sig)
{
DWORD a,x,y;
int i=1,l=sig.Length();
// all points
for(gSigPoints.num=0;(i+3<=l)&&(sig[i]!='*');)
{
a=sig[i]-'0'; if (a>9) a+='0'-'A'+10; x =a; i++;
a=sig[i]-'0'; if (a>9) a+='0'-'A'+10; x<<=4; x|=a; i++;
a=sig[i]-'0'; if (a>9) a+='0'-'A'+10; y =a; i++;
a=sig[i]-'0'; if (a>9) a+='0'-'A'+10; y<<=4; y|=a; i++;
gSigPoints.add(x);
gSigPoints.add(y);
}
// separator
i++;
// all lines
for(gSigLines.num=0;i+7<=l;)
{
a=sig[i]-'0'; if (a>9) a+='0'-'A'+10; x =a; i++;
a=sig[i]-'0'; if (a>9) a+='0'-'A'+10; x<<=4; x|=a; i++;
a=sig[i]-'0'; if (a>9) a+='0'-'A'+10; y =a; i++;
a=sig[i]-'0'; if (a>9) a+='0'-'A'+10; y<<=4; y|=a; i++;
gSigLines.add(x);
gSigLines.add(y);
a=sig[i]-'0'; if (a>9) a+='0'-'A'+10; x =a; i++;
a=sig[i]-'0'; if (a>9) a+='0'-'A'+10; x<<=4; x|=a; i++;
a=sig[i]-'0'; if (a>9) a+='0'-'A'+10; y =a; i++;
a=sig[i]-'0'; if (a>9) a+='0'-'A'+10; y<<=4; y|=a; i++;
gSigLines.add(x);
gSigLines.add(y);
}
}
//---------------------------------------------------------------------------
void DrawBMP(TCanvas *can)
{
DWORD i,x,y;
// all points
for (i=0;i+1<gSigPoints.num;)
{
x=gSigPoints[i]; i++;
y=gSigPoints[i]; i++;
can->Pixels[x][y]=can->Pen->Color;
}
// all lines
for (i=0;i+3<gSigLines.num;)
{
x=gSigLines[i]; i++;
y=gSigLines[i]; i++;
can->MoveTo(x,y);
x=gSigLines[i]; i++;
y=gSigLines[i]; i++;
can->LineTo(x,y);
}
}
//---------------------------------------------------------------------------
void signature_on_mouse(backbuffer &scr)
{
DWORD x,y;
// mouse left button last and actual
bool q0=scr.sh0.Contains(ssLeft);
bool q1=scr.sh1.Contains(ssLeft);
bool _redraw=false;
// actual mouse position
x=scr.mx1;
y=scr.my1;
// on mouse down event
if ((!q0)&&(q1))
{
gSigPoints.add(x); gSigLines.add(x);
gSigPoints.add(y); gSigLines.add(y);
_redraw=true;
}
// on mouse move event
if ((q0)&&(q1))
{
gSigLines.add(x);
gSigLines.add(y);
gSigLines.add(x);
gSigLines.add(y);
_redraw=true;
}
// mouse mouse up event
if ((q0)&&(!q1))
{
gSigLines.add(x);
gSigLines.add(y);
_redraw=true;
txt=PackBMP();
}
// right mouse button clears signature
if (scr.sh1.Contains(ssRight))
{
gSigPoints.num=0;
gSigLines.num=0;
_redraw=true;
}
if ((_redraw)&&(scr.win)) scr.win->Repaint();
scr.rfs_mouse();
}
//---------------------------------------------------------------------------
List<>,AnsiString,Backbuffer
更改为您的平台样式。这可以处理任何栅格二进制图像,而不仅仅是签名:
但是你可以看到签名字符串的大小是〜13.9 KByte