Add the sequence of images specified by ith_image to the summary. Factoring this loop out into a helper function lets ith_image behave differently in the float and uint8 cases: the float case needs a temporary buffer which can be shared across calls to ith_image, but the uint8 case does not.
| 71 | // buffer which can be shared across calls to ith_image, but the uint8 case |
| 72 | // does not. |
| 73 | Status AddImages(const string& tag, int max_images, int batch_size, int w, |
| 74 | int h, int depth, |
| 75 | const std::function<Uint8Image(int)>& ith_image, Summary* s) { |
| 76 | const int N = std::min<int>(max_images, batch_size); |
| 77 | for (int i = 0; i < N; ++i) { |
| 78 | Summary::Value* v = s->add_value(); |
| 79 | // The tag depends on the number of requested images (not the number |
| 80 | // produced.) |
| 81 | // |
| 82 | // Note that later on avisu uses "/" to figure out a consistent naming |
| 83 | // convention for display, so we append "/image" to guarantee that the |
| 84 | // image(s) won't be displayed in the global scope with no name. |
| 85 | if (max_images > 1) { |
| 86 | v->set_tag(strings::StrCat(tag, "/image/", i)); |
| 87 | } else { |
| 88 | v->set_tag(strings::StrCat(tag, "/image")); |
| 89 | } |
| 90 | |
| 91 | const auto image = ith_image(i); |
| 92 | Summary::Image* si = v->mutable_image(); |
| 93 | si->set_height(h); |
| 94 | si->set_width(w); |
| 95 | si->set_colorspace(depth); |
| 96 | const int channel_bits = 8; |
| 97 | const int compression = -1; // Use zlib default |
| 98 | if (!png::WriteImageToBuffer(image.data(), w, h, w * depth, depth, |
| 99 | channel_bits, compression, |
| 100 | si->mutable_encoded_image_string(), nullptr)) { |
| 101 | return errors::Internal("PNG encoding failed"); |
| 102 | } |
| 103 | } |
| 104 | return Status::OK(); |
| 105 | } |
| 106 | |
| 107 | template <class T> |
| 108 | void NormalizeFloatImage(int hw, int depth, |
no test coverage detected