| 5451 | }; |
| 5452 | |
| 5453 | int32_t imageWritePng(bx::WriterI* _writer, uint32_t _width, uint32_t _height, uint32_t _srcPitch, const void* _src, TextureFormat::Enum _format, bool _yflip, bx::Error* _err) |
| 5454 | { |
| 5455 | BX_ERROR_SCOPE(_err); |
| 5456 | |
| 5457 | switch (_format) |
| 5458 | { |
| 5459 | case TextureFormat::R8: |
| 5460 | case TextureFormat::RGBA8: |
| 5461 | case TextureFormat::BGRA8: |
| 5462 | break; |
| 5463 | |
| 5464 | default: |
| 5465 | BX_ERROR_SET(_err, BIMG_ERROR, "PNG: Unsupported texture format."); |
| 5466 | return 0; |
| 5467 | } |
| 5468 | |
| 5469 | const bool grayscale = TextureFormat::R8 == _format; |
| 5470 | const bool bgra = TextureFormat::BGRA8 == _format; |
| 5471 | |
| 5472 | int32_t total = 0; |
| 5473 | total += bx::write(_writer, "\x89PNG\r\n\x1a\n", _err); |
| 5474 | total += bx::write(_writer, bx::toBigEndian<uint32_t>(13), _err); |
| 5475 | |
| 5476 | HashWriter<bx::HashCrc32> writerC(_writer); |
| 5477 | total += bx::write(&writerC, "IHDR", _err); |
| 5478 | total += bx::write(&writerC, bx::toBigEndian(_width), _err); |
| 5479 | total += bx::write(&writerC, bx::toBigEndian(_height), _err); |
| 5480 | total += bx::write(&writerC, "\x08\x06", _err); |
| 5481 | total += bx::writeRep(&writerC, 0, 3, _err); |
| 5482 | total += bx::write(_writer, bx::toBigEndian(writerC.end() ), _err); |
| 5483 | |
| 5484 | const uint32_t bpp = grayscale ? 8 : 32; |
| 5485 | const uint32_t stride = _width*bpp/8; |
| 5486 | const uint16_t zlen = bx::toLittleEndian<uint16_t>(uint16_t(stride + 1) ); |
| 5487 | const uint16_t zlenC = bx::toLittleEndian<uint16_t>(~zlen); |
| 5488 | |
| 5489 | total += bx::write(_writer, bx::toBigEndian<uint32_t>(_height*(stride+6)+6), _err); |
| 5490 | |
| 5491 | writerC.begin(); |
| 5492 | total += bx::write(&writerC, "IDAT", _err); |
| 5493 | total += bx::write(&writerC, "\x78\x9c", _err); |
| 5494 | |
| 5495 | const uint8_t* data = (const uint8_t*)_src; |
| 5496 | int32_t step = int32_t(_srcPitch); |
| 5497 | if (_yflip) |
| 5498 | { |
| 5499 | data += _srcPitch*_height - _srcPitch; |
| 5500 | step = -step; |
| 5501 | } |
| 5502 | |
| 5503 | HashWriter<bx::HashAdler32> writerA(&writerC); |
| 5504 | |
| 5505 | for (uint32_t ii = 0; ii < _height && _err->isOk(); ++ii) |
| 5506 | { |
| 5507 | total += bx::write(&writerC, uint8_t(ii == _height-1 ? 1 : 0), _err); |
| 5508 | total += bx::write(&writerC, zlen, _err); |
| 5509 | total += bx::write(&writerC, zlenC, _err); |
| 5510 |
no test coverage detected