벡터가 u8
바이트 (픽셀 당 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 이미지의 쓰기 기능의 순수한 녹 구현입니다.
내 파이썬 대답은 here을 기반으로합니다.
참고 : 녹는 ZLIB를 노출하지 않기 때문에
이- 이 원래 파이썬 코드보다 꽤 크다.
- 이렇게하면 압축되지 않은 이미지를 작성하여 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. Pymaging PNG 이미지를 저장하는 방법은 무엇입니까?
- 2. 이미지를 PNG 형식으로 저장하는 방법은 무엇입니까?
- 3. 히스토그램의 이미지를 저장하는 방법은 무엇입니까?
- 4. 행별로 이미지를 저장하는 방법은 무엇입니까?
- 5. 투명도가있는 png 파일을 저장하는 방법은 무엇입니까?
- 6. 캔버스에서 PNG 파일로 뷰를 저장하는 방법은 무엇입니까?
- 7. UITableView의 내용을 PNG 파일로 저장하는 방법은 무엇입니까?
- 8. CGContextRef를 .PNG 파일로 저장하는 방법은 무엇입니까?
- 9. 캔버스 이미지를 디스크에 저장하는 방법은 무엇입니까?
- 10. 이미지를 백그라운드로 삽입하고 Java로 저장하는 방법은 무엇입니까?
- 11. PictureBox 이미지를 다양한 형식으로 저장하는 방법은 무엇입니까?
- 12. 축소판 이미지를 데이터베이스에 저장하는 방법은 무엇입니까?
- 13. 이미지를 그린 다음 파일로 저장하는 방법은 무엇입니까?
- 14. 이미지를 cms에 저장하는 방법은 무엇입니까?
- 15. 이미지를 캐시에 저장하는 방법은 무엇입니까?
- 16. wxImage로 이미지를 저장하는 방법은 무엇입니까?
- 17. 데이터베이스에 이미지를 저장하는 방법은 무엇입니까?
- 18. 데이터베이스에 이미지를 저장하는 방법은 무엇입니까?
- 19. mongoDB에 이미지를 저장하는 방법은 무엇입니까?
- 20. .pvr.ccz 파일에서 PNG 이미지를 복구하는 방법은 무엇입니까?
- 21. iOS에서 PNG 이미지를 CMYK로 변환하는 방법은 무엇입니까?
- 22. PNG 이미지를 바이트 배열로 변환하는 방법은 무엇입니까?
- 23. base64 이미지를 더 빠르게 저장하는 방법은 무엇입니까?
- 24. 서비스를 사용하여 SDCard에 이미지를 저장하는 방법은 무엇입니까?
- 25. 캔버스 요소를 php 및 ajax로 png 파일에 저장하는 방법은 무엇입니까?
- 26. PNG 또는 JPG 파일에 pcl :: Histogram을 저장하는 방법은 무엇입니까?
- 27. Xaml에서 PNG 이미지를 제어합니다.
- 28. JPanel에 그려진 이미지를 저장하는 방법은 무엇입니까?
- 29. 녹에 사용되는 default_type_params 기능은 무엇입니까?
- 30. 안드로이드에 이미지를 저장하는 가장 좋은 방법은 무엇입니까?
[귀하의 시도는 어떤 연구입니까?] (http://meta.stackoverflow.com/q/261592/155423) – Shepmaster
@Shepmaster, 공정한 지적, 사실 내 대답을 쓰려는 의도로 물었습니다. (여전히 계획), 여러 유용한 답변을 가지고이 질문과 유사 - http://stackoverflow.com/questions/902761 (나는 파이썬에서 녹이기까지 내 자신의 대답을 포팅 찾고 있어요). – ideasman42
부적절한 질문을 게시하기 전에 언제든지 자기 대답이 준비 될 때까지 기다릴 수 있습니다. – Shepmaster