u8
バイト(1ピクセルあたり4バイト - RGBA)のベクトルが与えられた場合、これをどのようにしてPNGファイルに保存できますか?錆にPNG画像を保存するには?
3
A
答えて
12
生のバッファをディスクに保存するには、use the image crate in the Piston repositoryを使用できます。ページの一番下に
の例では、これを行う方法を示します..:
extern crate image;
fn main() {
let buffer: &[u8] = ...; // Generate the image data
// Save the buffer as "image.png"
image::save_buffer(&Path::new("image.png"), buffer, 800, 600, image::RGBA(8))
}
3
これは、PNG形式の画像書き込み機能の自己完結型、純粋な錆の実装です。
私のPythonの回答hereに基づいています。
注
- 錆がZLIBを露出しないので、これは元のPythonコードよりもかなり大きいです。
- これにより、圧縮されていないイメージを書き込むことによってzlibを使用することが回避されます。
crc32
およびadler32
チェックサム実装がモジュールとして含まれています。- チェックするキー機能は
write
で、書き込み可能なタイプ(通常はファイル)を使用します。
例:これは、基本的に、このスニペットと同じであるpng_encode_mini crate、になされたものであり、
mod crc32 {
// https://github.com/ledbettj/crc32/blob/master/rust/src/crc32.rs
pub struct Crc32 {
table: [u32; 256],
value: u32,
}
const CRC32_INITIAL: u32 = 0xedb88320;
impl Crc32 {
pub fn new() -> Crc32 {
let mut c = Crc32 {
table: [0; 256],
value: 0xffffffff,
};
for i in 0..256 {
let mut v = i as u32;
for _ in 0..8 {
v = if v & 1 != 0 {
CRC32_INITIAL^(v >> 1)
} else {
v >> 1
}
}
c.table[i] = v;
}
return c;
}
pub fn start(&mut self) {
self.value = 0xffffffff;
}
pub fn update(&mut self, buf: &[u8]) {
for &i in buf {
self.value = self.table[((self.value^(i as u32)) & 0xff) as usize]^
(self.value >> 8);
}
}
pub fn finalize(&mut self) -> u32 {
self.value^0xffffffff_u32
}
#[allow(dead_code)]
pub fn crc(&mut self, buf: &[u8]) -> u32 {
self.start();
self.update(buf);
self.finalize()
}
}
}
mod adler32 {
// https://en.wikipedia.org/wiki/Adler-32
pub struct Adler32 {
a: u32,
b: u32,
}
const MOD_ADLER: u32 = 65521;
impl Adler32 {
pub fn new() -> Adler32 {
Adler32 { a: 1, b: 0 }
}
pub fn start(&mut self) {
self.a = 1;
self.b = 0;
}
pub fn update(&mut self, buf: &[u8]) {
for &i in buf {
self.a = (self.a + i as u32) % MOD_ADLER;
self.b = (self.a + self.b) % MOD_ADLER;
}
}
pub fn finalize(&self) -> u32 {
return (self.b << 16) | self.a;
}
#[allow(dead_code)]
pub fn crc(&mut self, buf: &[u8]) -> u32 {
self.start();
self.update(buf);
self.finalize()
}
}
}
// big endian
#[inline]
fn u32_to_u8_be(v: u32) -> [u8; 4] {
[(v >> 24) as u8, (v >> 16) as u8, (v >> 8) as u8, v as u8]
}
mod fake_zlib {
use super::adler32;
use super::u32_to_u8_be;
// Use 'none' compression
pub fn compress(data: &[u8]) -> Vec<u8> {
const CHUNK_SIZE: usize = 65530;
let final_len =
// header
2 +
// every chunk adds 5 bytes [1:type, 4:size].
(5 * {
let n = data.len()/CHUNK_SIZE;
// include an extra chunk when we don't fit exactly into CHUNK_SIZE
(n + {if data.len() == n * CHUNK_SIZE && data.len() != 0 { 0 } else { 1 }})
}) +
// data
data.len() +
// crc
4
;
let mut raw_data = Vec::with_capacity(final_len);
// header
raw_data.extend(&[120, 1]);
let mut pos_curr = 0_usize;
let mut crc = adler32::Adler32::new();
loop {
let pos_next = ::std::cmp::min(data.len(), pos_curr + CHUNK_SIZE);
let chunk_len = (pos_next - pos_curr) as u32;
let is_last = pos_next == data.len();
raw_data.extend(&[
// type
if is_last { 1 } else { 0 },
// size
(chunk_len & 0xff) as u8,
((chunk_len >> 8) & 0xff) as u8,
(0xff - (chunk_len & 0xff)) as u8,
(0xff - ((chunk_len >> 8) & 0xff)) as u8,
]);
raw_data.extend(&data[pos_curr..pos_next]);
crc.update(&data[pos_curr..pos_next]);
if is_last {
break;
}
pos_curr = pos_next;
}
raw_data.extend(&u32_to_u8_be(crc.finalize()));
assert_eq!(final_len, raw_data.len());
return raw_data;
}
}
///
/// Write RGBA pixels to uncompressed PNG.
///
pub fn write<W: ::std::io::Write>(
file: &mut W,
image: &[u8],
w: u32,
h: u32,
) -> Result<(), ::std::io::Error> {
assert!(w as usize * h as usize * 4 == image.len());
fn png_pack<W: ::std::io::Write>(
file: &mut W,
png_tag: &[u8; 4],
data: &[u8],
) -> Result<(), ::std::io::Error> {
file.write(&u32_to_u8_be(data.len() as u32))?;
file.write(png_tag)?;
file.write(data)?;
{
let mut crc = crc32::Crc32::new();
crc.start();
crc.update(png_tag);
crc.update(data);
file.write(&u32_to_u8_be(crc.finalize()))?;
}
Ok(())
}
file.write(b"\x89PNG\r\n\x1a\n")?;
{
let wb = u32_to_u8_be(w);
let hb = u32_to_u8_be(h);
let data = [wb[0], wb[1], wb[2], wb[3],
hb[0], hb[1], hb[2], hb[3],
8, 6, 0, 0, 0];
png_pack(file, b"IHDR", &data)?;
}
{
let width_byte_4 = w * 4;
let final_len = (width_byte_4 + 1) * h;
let mut raw_data = Vec::with_capacity(final_len as usize);
let mut span: u32 = (h - 1) * width_byte_4;
loop {
raw_data.push(0);
raw_data.extend((&image[(span as usize)..(span + width_byte_4) as usize]));
if span == 0 {
break;
}
span -= width_byte_4;
}
assert!(final_len == (raw_data.len() as u32));
png_pack(file, b"IDAT", &fake_zlib::compress(&raw_data))?;
}
png_pack(file, b"IEND", &[])?;
Ok(())
}
fn main() {
let mut f = std::fs::File::create("test.png").unwrap();
// image from bottom to top 3x2
let image_width = 3;
let image_height = 2;
let image = vec!(
// R G B A
0xff, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff,
0x80, 0x00, 0x00, 0xff,
0x00, 0x80, 0x00, 0xff,
0x00, 0x00, 0x80, 0xff,
);
match write(&mut f, &image, image_width, image_height) {
Ok(_) => println!("Written image!"),
Err(e) => println!("Error {:?}", e),
}
}
。
関連する問題
- 1. Fiware-Orion画像.pngファイルをorionに保存する方法
- 2. JavaのPNG画像にテキストを保存する
- 3. 画像の2チャンネルの画像をpng形式で保存する
- 4. カメラロールにPNG画像としてSKSpriteNodeを保存する方法は?
- 5. 保存base64でエンコードされた画像の代わりに、PNG
- 6. HDFSに画像ファイル(jpeg、png)を保存するための入力フォーマット
- 7. iOSスウィフト3でPNG画像ファイルにOpenGL ES図面を保存する
- 8. png画像をGIF画像にするには?
- 9. ギャラリーに画像を保存
- 10. 画像をレルムデータベースに保存
- 11. mysqlに画像を保存
- 12. ギャラリーに画像を保存
- 13. 画像をコアデータに保存
- 14. 画像をデータベースに保存
- 15. サーバーに画像を保存
- 16. ヘッダーに画像を保存
- 17. ファイルシステムに画像を保存
- 18. 画像ファイル(.JPG、.PNG、.BMPなど)としてJFrameを保存
- 19. processing.jsを使用して画像をpngファイルに保存します
- 20. 画像をクッキーに保存する
- 21. MongoDB GridFSに画像を保存する
- 22. matlabに画像を保存する
- 23. JavaFX:画像をペインに保存する
- 24. 画像をファイルに保存するandroid
- 25. Androidアプリに画像を保存する
- 26. SQLサーバに画像を保存する
- 27. Neo4Jに画像を保存する
- 28. ギャラリーに画像を保存する
- 29. リストに画像を保存する
- 30. フォトフォルダに画像を保存するホロレンズアプリ
[あなたの試みはどこですか?](http://meta.stackoverflow.com/q/261592/155423) – Shepmaster
@Shepmaster、公正なポイント、実際に私は自分の答えを書く意図で尋ねた(まだ計画されています)、この質問に似ていますが、これは複数の有益な答えを持っています - http://stackoverflow.com/questions/902761(私自身の答えをPythonからRustに移植しようとしています) – ideasman42
あなたは自分の自己回答が準備が整うまで待ってから、それほど素晴らしい質問を投稿することはできません。 – Shepmaster