请问,如何把一张图片每个点的像素保存为一个数组?

fxyfx 2011-03-10 05:34:45
RT,Point的方式太慢了,有没有其他办法能快速的保存呢?
...全文
990 44 打赏 收藏 转发到动态 举报
写回复
用AI写文章
44 条回复
切换为时间正序
请发表友善的回复…
发表回复
fxyfx 2011-03-14
  • 打赏
  • 举报
回复
恩,周六周日没上网,没有回复!
同意楼上,现在也我是这么做的,定义一个三维数组,用GetDIBits这个函数取点,第一维是蓝,第二位是绿,第三维是红。现在结贴了
zjl1234567 2011-03-12
  • 打赏
  • 举报
回复
VB区高手已经不在。这个问题我3年前遇到过。而当时参考的是一个叫“zy910”的大大5年前的帖子。

楼主去补习一下设备无关位图和设备相关位图的知识吧。

另外其实不用管文件的格式。用stdpicture对象(也可用picturebox控件),可直接加载常见图像,然后

使用GetDIBits(设备无关)或GetBitmapBits(设备相关)函数就能得到整个图像的像素了
fxyfx 2011-03-11
  • 打赏
  • 举报
回复
打开的BMP就是24位的图片,也是每个像素也是占2个字节!
andy95800 2011-03-11
  • 打赏
  • 举报
回复
那就跟图像的色深有关系了 建议你拿个标准的24位真彩bmp试试
fxyfx 2011-03-11
  • 打赏
  • 举报
回复
十分感谢楼上的代码,不过我现在也需求jpg文件,也可以打开后再保存成bmp格式然后再处理!

现在在困惑的是GetBitmapBits取到的结果怎么跟大家说的不一样!
无·法 2011-03-11
  • 打赏
  • 举报
回复
如果是bmp格式的话我这里有个直接读取的方法。

下面代码是直接将bmp图片读取并显示到picturebox中的,稍稍修改下就是你要的了。

窗体form1代码:

'添加一个picturebox1,按钮command1,防止一个bmp文件 c:\1.bmp
Option Explicit

Dim bfh As BitFileHeader
Dim colornumber As Byte, thisrgbw As rgbw, thiscolor As Long
Dim x As Long, y As Long
Dim cols As Integer, rows As Integer

Private Sub Command1_Click()
Dim strInfo As String

Open "c:\1.bmp" For Binary As #1
Get #1, 1, bfh

strInfo = "文件参数:" & vbCrLf & vbCrLf & _
"bfsize = " & bfh.bfsize & vbCrLf & _
"bfoffbits = " & bfh.bfoffbits & vbCrLf & _
"biwidth = " & bfh.biwidth & vbCrLf & _
"biheight = " & bfh.biheight & vbCrLf & _
"调色板数 = " & bfh.biplanes & vbCrLf & _
"颜色位数 = " & bfh.bibitcount & vbCrLf & _
"bicompress = " & bfh.bicompress & vbCrLf & _
"bisizeimage = " & bfh.bisizeimage & vbCrLf & _
"bixpixelpermeter = " & bfh.bixpixelpermeter & vbCrLf & _
"biypixelspermeter = " & bfh.biypixelspermeter & vbCrLf & _
"bilrused = " & bfh.bilrused & vbCrLf & _
"biclrinportant = " & bfh.biclrinportant

MsgBox strInfo

Picture1.Width = bfh.biwidth
Picture1.Height = bfh.biheight
DoEvents

Select Case bfh.bibitcount
Case 1
Call deal2bmp
Case 4
Call deal16bmp
Case 8
Call deal256bmp
Case 24
Call deal24bitbmp
End Select
Close #1
End Sub
Sub deal2bmp()
Dim i As Integer, thisbit As Integer
cols = (bfh.biwidth + 7) \ 8 '八个点共一个字节
cols = IIf(cols Mod 4 = 0, cols, (cols \ 4 + 1) * 4) '凑成4有倍数
rows = bfh.biheight
For y = 0 To rows - 1
For x = 0 To cols - 1
Get #1, bfh.bfoffbits + 1 + y * cols + x, colornumber
For i = 7 To 0 Step -1
thisbit = colornumber \ (2 ^ i) Mod 2 '滤出一个字节中的某一位作为一个点的颜色号
Get #1, 55 + thisbit * 4, thisrgbw

thiscolor = RGB(thisrgbw.r, thisrgbw.g, thisrgbw.b)
If x < (bfh.biwidth + 7) \ 8 Then
Picture1.PSet (8 * x + 7 - i, rows - 1 - y), thiscolor
End If
Next i
Next x
Next y
End Sub

Sub deal16bmp()
cols = (bfh.biwidth + 1) \ 2 '两个点共一个字节
cols = IIf(cols Mod 4 = 0, cols, (cols \ 4 + 1) * 4) '凑成4有倍数
rows = bfh.biheight
For y = 0 To rows - 1
For x = 0 To cols - 1
Get #1, bfh.bfoffbits + 1 + y * cols + x, colornumber
Get #1, 55 + (colornumber \ 16) * 4, thisrgbw '读取左4位作为第一个点的颜色号
thiscolor = RGB(thisrgbw.r, thisrgbw.g, thisrgbw.b)
If x < (bfh.biwidth + 1) \ 2 Then Picture1.PSet (2 * x, rows - 1 - y), thiscolor

Get #1, 55 + (colornumber Mod 16) * 4, thisrgbw '读取右4位作为第二个点的颜色号
thiscolor = RGB(thisrgbw.r, thisrgbw.g, thisrgbw.b)
If x < (bfh.biwidth + 1) \ 2 Then Picture1.PSet (2 * x + 1, rows - 1 - y), thiscolor
Next x
Next y
End Sub

Sub deal256bmp()
cols = IIf(bfh.biwidth Mod 4 = 0, bfh.biwidth, (bfh.biwidth \ 4 + 1) * 4) '每点占一个字节,每行字节数凑成4的倍数
rows = bfh.biheight
For y = 0 To rows - 1
For x = 0 To cols - 1
Get #1, bfh.bfoffbits + 1 + y * cols + x, colornumber
Get #1, 55 + colornumber * 4, thisrgbw
thiscolor = RGB(thisrgbw.r, thisrgbw.g, thisrgbw.b)
If x < bfh.biwidth Then Picture1.PSet (x, rows - 1 - y), thiscolor
Next x
Next y
End Sub

Sub deal24bitbmp()
Dim r As Byte, g As Byte, b As Byte
cols = IIf(3 * bfh.biwidth Mod 4 = 0, 3 * bfh.biwidth, (3 * bfh.biwidth \ 4 + 1) * 4) '每点占三个字节,每行字节数凑成4的倍数
rows = bfh.biheight
For y = 0 To rows - 1
For x = 0 To cols - 1
Get #1, bfh.bfoffbits + 1 + y * cols + x, thisrgbw
thiscolor = RGB(thisrgbw.r, thisrgbw.g, thisrgbw.b)
If x Mod 3 = 0 And x < 3 * bfh.biwidth Then Picture1.PSet (x \ 3, rows - 1 - y), thiscolor
Next x
Next y
End Sub


module模块代码:
Option Explicit

Public Type BitFileHeader
bftype As String * 2 '2
bfsize As Long '4
bfreserved1 As Integer '2
bfreserved2 As Integer '2
bfoffbits As Long '4
bisize As Long '4
biwidth As Long '4
biheight As Long '4
biplanes As Integer '2
bibitcount As Integer '2
bicompress As Long '4
bisizeimage As Long '4
bixpixelpermeter As Long '4
biypixelspermeter As Long '4
bilrused As Long '4
biclrinportant As Long '4
End Type

Public Type rgbw
b As Byte
g As Byte
r As Byte
w As Byte
End Type
fxyfx 2011-03-11
  • 打赏
  • 举报
回复
楼上的,是表示用几位吧?
lyserver 2011-03-11
  • 打赏
  • 举报
回复
Private Type BITMAP '14 bytes
bmType As Long
bmWidth As Long
bmHeight As Long
bmWidthBytes As Long
bmPlanes As Integer
bmBitsPixel As Integer
bmBits As Long
End Type
以上结构中bmBitsPixel成员表示每像素用几个字节来表示。
andy95800 2011-03-11
  • 打赏
  • 举报
回复
Dim b() As Byte
andy95800 2011-03-11
  • 打赏
  • 举报
回复
自己试试就行了 对你来说问题不大了
fxyfx 2011-03-11
  • 打赏
  • 举报
回复
b()定义的是字节数组
fxyfx 2011-03-11
  • 打赏
  • 举报
回复
Dim map As BitMap
GetObject p.Image, Len(map), map
ReDim b( map.bmWidthBytes * map.bmHeight- 1)
GetBitmapBits p.Image, map.bmWidthBytes * map.bmHeight, b(0)

代码就是这样的
andy95800 2011-03-11
  • 打赏
  • 举报
回复
那就只能看你代码说话了,变量声明不同 代码不同可能都有不同的结果
t=timer
这里t的类型不同 取得的值的精度也不同,可能一样的道理
fxyfx 2011-03-11
  • 打赏
  • 举报
回复
哦,感谢楼上,现在我主要是想知道为什么我取出来的数组是每个点占两位,会不会有其他可能?
andy95800 2011-03-11
  • 打赏
  • 举报
回复
要想弄明白 你先看看你能不能成功复制一张图吧 如果按你的2位一点来打印
andy95800 2011-03-11
  • 打赏
  • 举报
回复
                  GetObject Picture1.Image, Len(PicInfo), PicInfo
BytesPerPixel = PicInfo.bmBitsPixel \ 8
Dim pp() As Long
ReDim pp(PicInfo.bmWidth - 1, PicInfo.bmHeight - 1)
For i = 0 To UBound(PicBits) \ BytesPerPixel - 1
b = PicBits(i * BytesPerPixel + 1)
G = PicBits(i * BytesPerPixel + 2)
R = PicBits(i * BytesPerPixel + 3)
k = Int(i / PicInfo.bmHeight)
j = i - k * PicInfo.bmHeight
pp(j, k) = RGB(R, G, b)
Next i

pp(j, k)就是直观的各个点了
fxyfx 2011-03-11
  • 打赏
  • 举报
回复
哦,有一点,我PictureBox的ScaleMode是Pixel
fxyfx 2011-03-11
  • 打赏
  • 举报
回复
我用PictureBox打开的,一个BMP文件,一个JPG文件,两个大小一样,所得数组位数一样,我重新用PSet打印到另外一个图片上,只打印红色,也没错。
然后我打开了另外一张比较大的BMP文件,每个点也是占两位,打印红色出来也没错,所以我就比较奇怪。
andy95800 2011-03-11
  • 打赏
  • 举报
回复
BMP都是用RGB表示图像像素 每个点只占两位 的结论哪里得来的 分析错了吧
fxyfx 2011-03-11
  • 打赏
  • 举报
回复
可根据我取出来的数组,每个点只占两位,前面是红色,后面是黑色。还会有其他情况吗?比如1个,4个之类的。如果是这些,每位表示什么意思呢?
加载更多回复(24)
没有积分的私聊我 看到消息百分百发给你 1、算法核心: 1、读取图片A,获得其RGB三个通道数据并转换成三个矩阵a1,a2,a3。 2、读取文件B,将其转换成比特流b。 3、遍历b,得到比特b1,b2,b3,b4,b5,b6等等,将b1代替a1第一个元素的最低位,将b2代替a2第一个元素的最低位,将b3代替a3第一个元素的最低位,将b4代替a1第二个元素的最低位,以此类推。 2、具体实现: 1、隐写: 1、使用java ImageIO读取图片,获取其RGB通道信息。 2、使用java NIO读取被嵌入的文件,将其转换为byte数组,需要特别指出的是原生方法得到是byte类型的数组,但是算法实现需要更加精细的操作,所以还需要对得到的byte数组进行进一步的转换封装,将其转换成形如10101的数组。例如,读取文件得到byte数组的第一个元素为63,需将63转换为00111111数组。并且保存好文件的长度。 3、按照算法,遍历形如10101的数组 1、如果遍历到的值为0,将矩阵对应的矩阵元素与0xfe进行与运算,将最低位置为0 2、如果遍历到的值为1,将矩阵对应的矩阵元素与0x01进行或运算,将最低位置为1 4、将步骤3得到的经过经过隐写的矩阵写为一张新的图片。 3、读取 1、使用java ImageIO读取图片,获取其RGB通道信息。 2、使用隐写步骤3得到的文件长度,遍历图片像素矩阵,需要特别指出的是因为后续步骤还需要进行进一步的转化,所以这一步是将得到的“100100......”序列每八位封装为一个数组,最终得到一些数组集合,每个数组包含八位二进制序列。 3、将步骤2得到的数组进行转换,例如00111111应该转换为byte类型数值为63的数字,10111111转换为-63。这一步会得到一个byte类型的数组。 4、将步骤3得到的byte类型数组写入文件,需要指出的是写入的文件形式应该和隐写模块步骤二中读入的文件形式一致。 3、程序使用方法 1、安装Java8 2、使用命令行进入jar文件所在目录下,使用命令 java -jar 2016115130.jar 3、安装提示输入嵌入和被嵌入的文件名字,注意路径问题

1,486

社区成员

发帖
与我相关
我的任务
社区描述
VB API
社区管理员
  • API
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧