
[Ruby] Enregistrer des images Ecrit par Zeus
Petit bout de code permettant d'exporter des images RGSS 1 et 2 au format BMP ou PNG.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| # Bitmap export v 3.0 by Zeus81 class Bitmap RtlMoveMemory_pi = Win32API.new('kernel32', 'RtlMoveMemory', 'pii', 'i') RtlMoveMemory_ip = Win32API.new('kernel32', 'RtlMoveMemory', 'ipi', 'i') def address RtlMoveMemory_pi.call(a="\0"*4, __id__*2+16, 4) RtlMoveMemory_pi.call(a, a.unpack('L')[0]+8, 4) RtlMoveMemory_pi.call(a, a.unpack('L')[0]+16, 4) a.unpack('L')[0] end def export(filename) file = File.open(filename, 'wb') case format=File.extname(filename) when '.bmp' data, size = String.new, width*height*4 RtlMoveMemory_ip.call(data.__id__*2+8, [size,address].pack('L2'), 8) file.write(['BM',size+54,0,54,40,width,height,1,32,0,size,0,0,0,0].pack('a2L6S2L6')) file.write(data) RtlMoveMemory_ip.call(data.__id__*2+8, "\0"*8, 8) when '.png' def file.write_chunk(chunk) write([chunk.size-4].pack('N')) write(chunk) write([Zlib.crc32(chunk)].pack('N')) end file.write("\211PNG\r\n\32\n") file.write_chunk("IHDR#{[width,height,8,6,0,0,0].pack('N2C5')}") RtlMoveMemory_pi.call(data="\0"*(width*height*4), address, data.size) (width*height).times {|i| data[i<<=2,3] = data[i,3].reverse!} deflate, null_char, w4 = Zlib::Deflate.new(9), "\0", width*4 (height-1).downto(0) {|i| deflate << null_char << data[i*w4,w4]} file.write_chunk("IDAT#{deflate.finish}") deflate.close file.write_chunk('IEND') when ''; print("Export format missing for '#{filename}'.") else print("Export format '#{format}' not supported.") end file.close end end |
Il n'y a qu'une fonction 'export' et on l'appelle en précisant l'extension :
> bitmap.export("prout.png")
ou
> bitmap.export("prout.bmp")
Je sais que c'est pas nouveau mais l'intérêt de ma version est qu'elle est très rapide !
Par exemple si on compare avec ce fameux script :
> b = Bitmap.new(1280, 960)
> b.make_png("prout") # => 10.2 secondes
Avec le mien :
> b.export("prout.png") # => 3.7 secondes
> b.export("prout.bmp") # => 0.04 secondes
L'enregistrement d'un PNG est 60% plus rapide.
Et celui d'un BMP est quasi-instantané, en fait ça prend juste le temps de copier la mémoire sur le disque.
Et c'est du BMP 32bit ! c'est à dire que ça gère la transparence, par contre c'est compatible avec rien si ce n'est RM et Gimp (c'est tout ce qui importe de toute façon).
Je pense pas qu'on puisse faire plus performant juste en Ruby mais plus tard j'essaierai d'en faire une nouvelle version avec une dll C qui sera plus rapide et avec plus de formats.
|
|
Zeus81 - posté le 16/04/2012 à 22:48:07. (8650 messages postés)
|

Ero-Maker | Micro update :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
| # Bitmap export v3.1 by Zeus81
class Bitmap
RtlMoveMemory_pi = Win32API.new('kernel32', 'RtlMoveMemory', 'pii', 'i')
RtlMoveMemory_ip = Win32API.new('kernel32', 'RtlMoveMemory', 'ipi', 'i')
def address
@address ||= (
RtlMoveMemory_pi.call(a="\0"*4, __id__*2+16, 4)
RtlMoveMemory_pi.call(a, a.unpack('L')[0]+8, 4)
RtlMoveMemory_pi.call(a, a.unpack('L')[0]+16, 4)
a.unpack('L')[0]
)
end
def export(filename)
file, size = File.open(filename, 'wb'), width*height*4
case format=File.extname(filename)
when '.bmp'
data = String.new
RtlMoveMemory_ip.call(data.__id__*2+8, [size,address].pack('L2'), 8)
file.write("BM#{[size+54,0,54,40,width,height,1,32,0,size,0,0,0,0].pack('a2L6S2L6')}")
file.write(data)
RtlMoveMemory_ip.call(data.__id__*2+8, "\0"*8, 8)
when '.png'
def file.write_chunk(chunk)
write([chunk.size-4].pack('N'))
write(chunk)
write([Zlib.crc32(chunk)].pack('N'))
end
deflate, null_char, w4, i = Zlib::Deflate.new(9), "\0", width*4, 0
RtlMoveMemory_pi.call(data=null_char*size, address, size)
(width*height).times {|i| data[i<<=2,3] = data[i,3].reverse!}
(height-1).downto(0) {|i| deflate << null_char << data[i*w4,w4]}
file.write("\211PNG\r\n\32\n")
file.write_chunk("IHDR#{[width,height,8,6,0,0,0].pack('N2C5')}")
file.write_chunk("IDAT#{deflate.finish}")
file.write_chunk('IEND')
deflate.close
when ''; print("Export format missing for '#{filename}'.")
else print("Export format '#{format}' not supported.")
end
file.close
end
end |
Et nouvelle version pour VX Ace :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
| # Bitmap export v2.5 VXAce by Zeus81
class Bitmap
RtlMoveMemory_pi = Win32API.new('kernel32', 'RtlMoveMemory', 'pii', 'i')
def address
@address ||= (
RtlMoveMemory_pi.call(a="\0"*4, __id__*2+16, 4)
RtlMoveMemory_pi.call(a, a.unpack('L')[0]+8, 4)
RtlMoveMemory_pi.call(a, a.unpack('L')[0]+16, 4)
a.unpack('L')[0]
)
end
def export(filename)
file, size = File.open(filename, 'wb'), width*height*4
RtlMoveMemory_pi.call(data="\0"*size, address, size)
case format=File.extname(filename)
when '.bmp'
file.write("BM#{[size+54,0,54,40,width,height,1,32,0,size,0,0,0,0].pack('L6S2L6')}")
file.write(data)
when '.png'
def file.write_chunk(chunk)
write([chunk.bytesize-4].pack('N'))
write(chunk)
write([Zlib.crc32(chunk)].pack('N'))
end
data.force_encoding('ASCII-8BIT')
deflate, null_char, w4, i, j = Zlib::Deflate.new(9), "\0", width*4, 0, 0
(width*height).times do |i|
j = data.getbyte(i<<=2)
data.setbyte(i, data.getbyte(i+=2))
data.setbyte(i, j)
end
(height-1).downto(0) {|i| deflate << null_char << data[i*w4,w4]}
file.write("\211PNG\r\n\32\n")
file.write_chunk("IHDR#{[width,height,8,6,0,0,0].pack('N2C5')}")
file.write_chunk("IDAT#{deflate.finish}")
file.write_chunk('IEND')
deflate.close
when ''; print("Export format missing for '#{filename}'.")
else print("Export format '#{format}' not supported.")
end
file.close
end
end |
|
The Ark of Gladoria - Mes scripts et autres - Oniro Paradise - Gemini - Fan de Némausus & Ddken | 
|