| 495 | } // PngImage::writeMetadata |
| 496 | |
| 497 | void PngImage::doWriteMetadata(BasicIo& outIo) { |
| 498 | if (!io_->isopen()) |
| 499 | throw Error(ErrorCode::kerInputDataReadFailed); |
| 500 | if (!outIo.isopen()) |
| 501 | throw Error(ErrorCode::kerImageWriteFailed); |
| 502 | |
| 503 | #ifdef EXIV2_DEBUG_MESSAGES |
| 504 | std::cout << "Exiv2::PngImage::doWriteMetadata: Writing PNG file " << io_->path() << "\n"; |
| 505 | std::cout << "Exiv2::PngImage::doWriteMetadata: tmp file created " << outIo.path() << "\n"; |
| 506 | #endif |
| 507 | |
| 508 | if (!isPngType(*io_, true)) { |
| 509 | throw Error(ErrorCode::kerNoImageInInputData); |
| 510 | } |
| 511 | |
| 512 | // Write PNG Signature. |
| 513 | if (outIo.write(pngSignature, 8) != 8) |
| 514 | throw Error(ErrorCode::kerImageWriteFailed); |
| 515 | |
| 516 | DataBuf cheaderBuf(8); // Chunk header : 4 bytes (data size) + 4 bytes (chunk type). |
| 517 | |
| 518 | while (!io_->eof()) { |
| 519 | // Read chunk header. |
| 520 | size_t bufRead = io_->read(cheaderBuf.data(), 8); |
| 521 | if (io_->error()) |
| 522 | throw Error(ErrorCode::kerFailedToReadImageData); |
| 523 | if (bufRead != 8) |
| 524 | throw Error(ErrorCode::kerInputDataReadFailed); |
| 525 | |
| 526 | // Decode chunk data length. |
| 527 | |
| 528 | uint32_t dataOffset = cheaderBuf.read_uint32(0, Exiv2::bigEndian); |
| 529 | if (dataOffset > 0x7FFFFFFF) |
| 530 | throw Exiv2::Error(ErrorCode::kerFailedToReadImageData); |
| 531 | |
| 532 | // Read whole chunk : Chunk header + Chunk data (not fixed size - can be null) + CRC (4 bytes). |
| 533 | |
| 534 | DataBuf chunkBuf(8 + dataOffset + 4); // Chunk header (8 bytes) + Chunk data + CRC (4 bytes). |
| 535 | std::copy_n(cheaderBuf.begin(), 8, chunkBuf.begin()); // Copy header. |
| 536 | bufRead = io_->read(chunkBuf.data(8), dataOffset + 4); // Extract chunk data + CRC |
| 537 | if (io_->error()) |
| 538 | throw Error(ErrorCode::kerFailedToReadImageData); |
| 539 | if (bufRead != dataOffset + 4) |
| 540 | throw Error(ErrorCode::kerInputDataReadFailed); |
| 541 | |
| 542 | char szChunk[5]; |
| 543 | memcpy(szChunk, cheaderBuf.c_data(4), 4); |
| 544 | szChunk[4] = 0; |
| 545 | |
| 546 | if (!strcmp(szChunk, "IEND")) { |
| 547 | // Last chunk found: we write it and done. |
| 548 | #ifdef EXIV2_DEBUG_MESSAGES |
| 549 | std::cout << "Exiv2::PngImage::doWriteMetadata: Write IEND chunk (length: " << dataOffset << ")\n"; |
| 550 | #endif |
| 551 | if (outIo.write(chunkBuf.data(), chunkBuf.size()) != chunkBuf.size()) |
| 552 | throw Error(ErrorCode::kerImageWriteFailed); |
| 553 | return; |
| 554 | } |
nothing calls this directly
no test coverage detected