Skip to content

Commit 0daf6c8

Browse files
naushirdavidplowman
authored andcommitted
libcamera-apps: Switch all modules to use the new StreamInfo structure.
All internal modules (encoder, image, preview, postprocessing) have now switched to using StreamInfo to pass the stream parameters. Signed-off-by: Naushir Patuck <[email protected]>
1 parent 0e1a01e commit 0daf6c8

24 files changed

+205
-222
lines changed

apps/libcamera_detect.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,7 @@ static void event_loop(LibcameraDetectApp &app)
105105
filename[sizeof(filename) - 1] = 0;
106106
options->framestart++;
107107
std::cerr << "Save image " << filename << std::endl;
108-
jpeg_save(mem, info.width, info.height, info.stride, stream->configuration().pixelFormat, completed_request->metadata,
109-
std::string(filename), app.CameraId(), options);
108+
jpeg_save(mem, info, completed_request->metadata, std::string(filename), app.CameraId(), options);
110109

111110
// Restart camera in preview mode.
112111
app.Teardown();

apps/libcamera_jpeg.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,7 @@ static void event_loop(LibcameraJpegApp &app)
7575
StreamInfo info = app.GetStreamInfo(stream);
7676
CompletedRequestPtr &payload = std::get<CompletedRequestPtr>(msg.payload);
7777
const std::vector<libcamera::Span<uint8_t>> mem = app.Mmap(payload->buffers[stream]);
78-
jpeg_save(mem, info.width, info.height, info.stride, stream->configuration().pixelFormat,
79-
payload->metadata, options->output, app.CameraId(), options);
78+
jpeg_save(mem, info, payload->metadata, options->output, app.CameraId(), options);
8079
return;
8180
}
8281
}

apps/libcamera_still.cpp

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -75,20 +75,17 @@ static void save_image(LibcameraStillApp &app, CompletedRequestPtr &payload, Str
7575
{
7676
StillOptions const *options = app.GetOptions();
7777
StreamInfo info = app.GetStreamInfo(stream);
78-
libcamera::PixelFormat const &pixel_format = stream->configuration().pixelFormat;
7978
const std::vector<libcamera::Span<uint8_t>> mem = app.Mmap(payload->buffers[stream]);
8079
if (stream == app.RawStream())
81-
dng_save(mem, info.width, info.height, info.stride, pixel_format, payload->metadata, filename,
82-
app.CameraId(), options);
80+
dng_save(mem, info, payload->metadata, filename, app.CameraId(), options);
8381
else if (options->encoding == "jpg")
84-
jpeg_save(mem, info.width, info.height, info.stride, pixel_format, payload->metadata, filename,
85-
app.CameraId(), options);
82+
jpeg_save(mem, info, payload->metadata, filename, app.CameraId(), options);
8683
else if (options->encoding == "png")
87-
png_save(mem, info.width, info.height, info.stride, pixel_format, filename, options);
84+
png_save(mem, info, filename, options);
8885
else if (options->encoding == "bmp")
89-
bmp_save(mem, info.width, info.height, info.stride, pixel_format, filename, options);
86+
bmp_save(mem, info, filename, options);
9087
else
91-
yuv_save(mem, info.width, info.height, info.stride, pixel_format, filename, options);
88+
yuv_save(mem, info, filename, options);
9289
if (options->verbose)
9390
std::cerr << "Saved image " << info.width << " x " << info.height << " to file " << filename << std::endl;
9491
}

core/libcamera_app.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,7 @@ StreamInfo LibcameraApp::GetStreamInfo(Stream const *stream) const
628628
info.width = cfg.size.width;
629629
info.height = cfg.size.height;
630630
info.stride = cfg.stride;
631+
info.pixel_format = stream->configuration().pixelFormat;
631632
return info;
632633
}
633634

@@ -809,7 +810,7 @@ void LibcameraApp::previewThread()
809810
msg_queue_.Post(Msg(MsgType::Quit));
810811
}
811812
preview_frames_displayed_++;
812-
preview_->Show(fd, span, info.width, info.height, info.stride);
813+
preview_->Show(fd, span, info);
813814
if (!options_->info_text.empty())
814815
{
815816
std::string s = frame_info.ToString(options_->info_text);

core/libcamera_encoder.hpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,7 @@ class LibcameraEncoder : public LibcameraApp
4141
std::lock_guard<std::mutex> lock(encode_buffer_queue_mutex_);
4242
encode_buffer_queue_.push(completed_request); // creates a new reference
4343
}
44-
encoder_->EncodeBuffer(buffer->planes()[0].fd.get(), span.size(), mem, info.width, info.height, info.stride,
45-
timestamp_ns / 1000);
44+
encoder_->EncodeBuffer(buffer->planes()[0].fd.get(), span.size(), mem, info, timestamp_ns / 1000);
4645
}
4746
VideoOptions *GetOptions() const { return static_cast<VideoOptions *>(options_.get()); }
4847
void StopEncoder() { encoder_.reset(); }

encoder/encoder.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include <functional>
1111

12+
#include "core/stream_info.hpp"
1213
#include "core/video_options.hpp"
1314

1415
typedef std::function<void(void *)> InputDoneCallback;
@@ -30,8 +31,7 @@ class Encoder
3031
void SetOutputReadyCallback(OutputReadyCallback callback) { output_ready_callback_ = callback; }
3132
// Encode the given buffer. The buffer is specified both by an fd and size
3233
// describing a DMABUF, and by a mmapped userland pointer.
33-
virtual void EncodeBuffer(int fd, size_t size, void *mem, unsigned int width, unsigned int height,
34-
unsigned int stride, int64_t timestamp_us) = 0;
34+
virtual void EncodeBuffer(int fd, size_t size, void *mem, StreamInfo const &info, int64_t timestamp_us) = 0;
3535

3636
protected:
3737
InputDoneCallback input_done_callback_;

encoder/h264_encoder.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,7 @@ H264Encoder::~H264Encoder()
223223
std::cerr << "H264Encoder closed" << std::endl;
224224
}
225225

226-
void H264Encoder::EncodeBuffer(int fd, size_t size, void *mem, unsigned int width, unsigned int height,
227-
unsigned int stride, int64_t timestamp_us)
226+
void H264Encoder::EncodeBuffer(int fd, size_t size, void *mem, StreamInfo const &info, int64_t timestamp_us)
228227
{
229228
int index;
230229
{

encoder/h264_encoder.hpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ class H264Encoder : public Encoder
2020
H264Encoder(VideoOptions const *options);
2121
~H264Encoder();
2222
// Encode the given DMABUF.
23-
void EncodeBuffer(int fd, size_t size, void *mem, unsigned int width, unsigned int height, unsigned int stride,
24-
int64_t timestamp_us) override;
23+
void EncodeBuffer(int fd, size_t size, void *mem, StreamInfo const &info, int64_t timestamp_us) override;
2524

2625
private:
2726
// We want at least as many output buffers as there are in the camera queue

encoder/mjpeg_encoder.cpp

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,10 @@ MjpegEncoder::~MjpegEncoder()
3939
std::cerr << "MjpegEncoder closed" << std::endl;
4040
}
4141

42-
void MjpegEncoder::EncodeBuffer(int fd, size_t size, void *mem, unsigned int width, unsigned int height,
43-
unsigned int stride, int64_t timestamp_us)
42+
void MjpegEncoder::EncodeBuffer(int fd, size_t size, void *mem, StreamInfo const &info, int64_t timestamp_us)
4443
{
4544
std::lock_guard<std::mutex> lock(encode_mutex_);
46-
EncodeItem item = { mem, width, height, stride, timestamp_us, index_++ };
45+
EncodeItem item = { mem, info, timestamp_us, index_++ };
4746
encode_queue_.push(item);
4847
encode_cond_var_.notify_all();
4948
}
@@ -52,8 +51,8 @@ void MjpegEncoder::encodeJPEG(struct jpeg_compress_struct &cinfo, EncodeItem &it
5251
size_t &buffer_len)
5352
{
5453
// Copied from YUV420_to_JPEG_fast in jpeg.cpp.
55-
cinfo.image_width = item.width;
56-
cinfo.image_height = item.height;
54+
cinfo.image_width = item.info.width;
55+
cinfo.image_height = item.info.height;
5756
cinfo.input_components = 3;
5857
cinfo.in_color_space = JCS_YCbCr;
5958
cinfo.restart_interval = 0;
@@ -67,21 +66,21 @@ void MjpegEncoder::encodeJPEG(struct jpeg_compress_struct &cinfo, EncodeItem &it
6766
jpeg_mem_dest(&cinfo, &encoded_buffer, &jpeg_mem_len);
6867
jpeg_start_compress(&cinfo, TRUE);
6968

70-
int stride2 = item.stride / 2;
69+
int stride2 = item.info.stride / 2;
7170
uint8_t *Y = (uint8_t *)item.mem;
72-
uint8_t *U = (uint8_t *)Y + item.stride * item.height;
73-
uint8_t *V = (uint8_t *)U + stride2 * (item.height / 2);
74-
uint8_t *Y_max = U - item.stride;
71+
uint8_t *U = (uint8_t *)Y + item.info.stride * item.info.height;
72+
uint8_t *V = (uint8_t *)U + stride2 * (item.info.height / 2);
73+
uint8_t *Y_max = U - item.info.stride;
7574
uint8_t *U_max = V - stride2;
76-
uint8_t *V_max = U_max + stride2 * (item.height / 2);
75+
uint8_t *V_max = U_max + stride2 * (item.info.height / 2);
7776

7877
JSAMPROW y_rows[16];
7978
JSAMPROW u_rows[8];
8079
JSAMPROW v_rows[8];
8180

82-
for (uint8_t *Y_row = Y, *U_row = U, *V_row = V; cinfo.next_scanline < item.height;)
81+
for (uint8_t *Y_row = Y, *U_row = U, *V_row = V; cinfo.next_scanline < item.info.height;)
8382
{
84-
for (int i = 0; i < 16; i++, Y_row += item.stride)
83+
for (int i = 0; i < 16; i++, Y_row += item.info.stride)
8584
y_rows[i] = std::min(Y_row, Y_max);
8685
for (int i = 0; i < 8; i++, U_row += stride2, V_row += stride2)
8786
u_rows[i] = std::min(U_row, U_max), v_rows[i] = std::min(V_row, V_max);

encoder/mjpeg_encoder.hpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ class MjpegEncoder : public Encoder
2222
MjpegEncoder(VideoOptions const *options);
2323
~MjpegEncoder();
2424
// Encode the given buffer.
25-
void EncodeBuffer(int fd, size_t size, void *mem, unsigned int width, unsigned int height, unsigned int stride,
26-
int64_t timestamp_us) override;
25+
void EncodeBuffer(int fd, size_t size, void *mem, StreamInfo const &info, int64_t timestamp_us) override;
2726

2827
private:
2928
// How many threads to use. Whichever thread is idle will pick up the next frame.
@@ -44,9 +43,7 @@ class MjpegEncoder : public Encoder
4443
struct EncodeItem
4544
{
4645
void *mem;
47-
unsigned int width;
48-
unsigned int height;
49-
unsigned int stride;
46+
StreamInfo info;
5047
int64_t timestamp_us;
5148
uint64_t index;
5249
};

encoder/null_encoder.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,7 @@ NullEncoder::~NullEncoder()
2727
}
2828

2929
// Push the buffer onto the output queue to be "encoded" and returned.
30-
void NullEncoder::EncodeBuffer(int fd, size_t size, void *mem, unsigned int width, unsigned int height,
31-
unsigned int stride, int64_t timestamp_us)
30+
void NullEncoder::EncodeBuffer(int fd, size_t size, void *mem, StreamInfo const &info, int64_t timestamp_us)
3231
{
3332
std::lock_guard<std::mutex> lock(output_mutex_);
3433
OutputItem item = { mem, size, timestamp_us };

encoder/null_encoder.hpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ class NullEncoder : public Encoder
2020
public:
2121
NullEncoder(VideoOptions const *options);
2222
~NullEncoder();
23-
void EncodeBuffer(int fd, size_t size, void *mem, unsigned int width, unsigned int height, unsigned int stride,
24-
int64_t timestamp_us) override;
23+
void EncodeBuffer(int fd, size_t size, void *mem, StreamInfo const &info, int64_t timestamp_us) override;
2524

2625
private:
2726
void outputThread();

image/bmp.cpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <libcamera/formats.h>
1212

1313
#include "core/still_options.hpp"
14+
#include "core/stream_info.hpp"
1415

1516
struct ImageHeader
1617
{
@@ -40,10 +41,10 @@ struct FileHeader
4041
};
4142
static_assert(sizeof(FileHeader) == 16, "FileHeader size wrong");
4243

43-
void bmp_save(std::vector<libcamera::Span<uint8_t>> const &mem, unsigned int w, unsigned int h, unsigned int stride,
44-
libcamera::PixelFormat const &pixel_format, std::string const &filename, StillOptions const *options)
44+
void bmp_save(std::vector<libcamera::Span<uint8_t>> const &mem, StreamInfo const &info,
45+
std::string const &filename, StillOptions const *options)
4546
{
46-
if (pixel_format != libcamera::formats::RGB888)
47+
if (info.pixel_format != libcamera::formats::RGB888)
4748
throw std::runtime_error("pixel format for bmp should be RGB");
4849

4950
FILE *fp = filename == "-" ? stdout : fopen(filename.c_str(), "wb");
@@ -53,24 +54,24 @@ void bmp_save(std::vector<libcamera::Span<uint8_t>> const &mem, unsigned int w,
5354

5455
try
5556
{
56-
unsigned int line = w * 3;
57+
unsigned int line = info.width * 3;
5758
unsigned int pitch = (line + 3) & ~3; // lines are multiples of 4 bytes
5859
unsigned int pad = pitch - line;
5960
uint8_t padding[3] = {};
6061
uint8_t *ptr = (uint8_t *)mem[0].data();
6162

6263
FileHeader file_header;
6364
ImageHeader image_header;
64-
file_header.filesize = file_header.offset + h * pitch;
65-
image_header.width = w;
66-
image_header.height = -h; // make image come out the right way up
65+
file_header.filesize = file_header.offset + info.height * pitch;
66+
image_header.width = info.width;
67+
image_header.height = -info.height; // make image come out the right way up
6768

6869
// Don't write the file header's 2 dummy bytes
6970
if (fwrite((uint8_t *)&file_header + 2, sizeof(file_header) - 2, 1, fp) != 1 ||
7071
fwrite(&image_header, sizeof(image_header), 1, fp) != 1)
7172
throw std::runtime_error("failed to write BMP file");
7273

73-
for (unsigned int i = 0; i < h; i++, ptr += stride)
74+
for (unsigned int i = 0; i < info.height; i++, ptr += info.stride)
7475
{
7576
if (fwrite(ptr, line, 1, fp) != 1 || (pad != 0 && fwrite(padding, pad, 1, fp) != 1))
7677
throw std::runtime_error("failed to write BMP file, row " + std::to_string(i));

image/dng.cpp

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@
99

1010
#include <libcamera/control_ids.h>
1111
#include <libcamera/formats.h>
12-
#include <libcamera/pixel_format.h>
1312

1413
#include <tiffio.h>
1514

1615
#include "core/still_options.hpp"
16+
#include "core/stream_info.hpp"
1717

1818
using namespace libcamera;
1919

@@ -41,10 +41,10 @@ static const std::map<PixelFormat, BayerFormat> bayer_formats =
4141
{ formats::SGBRG12_CSI2P, { "GBRG-12", 12, TIFF_GBRG } },
4242
};
4343

44-
static void unpack_10bit(uint8_t *src, unsigned int w, unsigned int h, unsigned int stride, uint16_t *dest)
44+
static void unpack_10bit(uint8_t *src, StreamInfo const &info, uint16_t *dest)
4545
{
46-
unsigned int w_align = w & ~3;
47-
for (unsigned int y = 0; y < h; y++, src += stride)
46+
unsigned int w_align = info.width & ~3;
47+
for (unsigned int y = 0; y < info.height; y++, src += info.stride)
4848
{
4949
uint8_t *ptr = src;
5050
unsigned int x;
@@ -55,15 +55,15 @@ static void unpack_10bit(uint8_t *src, unsigned int w, unsigned int h, unsigned
5555
*dest++ = (ptr[2] << 2) | ((ptr[4] >> 4) & 3);
5656
*dest++ = (ptr[3] << 2) | ((ptr[4] >> 6) & 3);
5757
}
58-
for (; x < w; x++)
58+
for (; x < info.width; x++)
5959
*dest++ = (ptr[x & 3] << 2) | ((ptr[4] >> ((x & 3) << 1)) & 3);
6060
}
6161
}
6262

63-
static void unpack_12bit(uint8_t *src, unsigned int w, unsigned int h, unsigned int stride, uint16_t *dest)
63+
static void unpack_12bit(uint8_t *src, StreamInfo const &info, uint16_t *dest)
6464
{
65-
unsigned int w_align = w & ~1;
66-
for (unsigned int y = 0; y < h; y++, src += stride)
65+
unsigned int w_align = info.width & ~1;
66+
for (unsigned int y = 0; y < info.height; y++, src += info.stride)
6767
{
6868
uint8_t *ptr = src;
6969
unsigned int x;
@@ -72,7 +72,7 @@ static void unpack_12bit(uint8_t *src, unsigned int w, unsigned int h, unsigned
7272
*dest++ = (ptr[0] << 4) | ((ptr[2] >> 0) & 15);
7373
*dest++ = (ptr[1] << 4) | ((ptr[2] >> 4) & 15);
7474
}
75-
if (x < w)
75+
if (x < info.width)
7676
*dest++ = (ptr[x & 1] << 4) | ((ptr[2] >> ((x & 1) << 2)) & 15);
7777
}
7878
}
@@ -126,23 +126,23 @@ Matrix(float m0, float m1, float m2,
126126
}
127127
};
128128

129-
void dng_save(std::vector<libcamera::Span<uint8_t>> const &mem, unsigned int w, unsigned int h, unsigned int stride,
130-
PixelFormat const &pixel_format, ControlList const &metadata, std::string const &filename,
129+
void dng_save(std::vector<libcamera::Span<uint8_t>> const &mem, StreamInfo const &info,
130+
ControlList const &metadata, std::string const &filename,
131131
std::string const &cam_name, StillOptions const *options)
132132
{
133133
// Check the Bayer format and unpack it to u16.
134134

135-
auto it = bayer_formats.find(pixel_format);
135+
auto it = bayer_formats.find(info.pixel_format);
136136
if (it == bayer_formats.end())
137137
throw std::runtime_error("unsupported Bayer format");
138138
BayerFormat const &bayer_format = it->second;
139139
std::cerr << "Bayer format is " << bayer_format.name << "\n";
140140

141-
std::vector<uint16_t> buf(w * h);
141+
std::vector<uint16_t> buf(info.width * info.height);
142142
if (bayer_format.bits == 10)
143-
unpack_10bit((uint8_t *)mem[0].data(), w, h, stride, &buf[0]);
143+
unpack_10bit((uint8_t *)mem[0].data(), info, &buf[0]);
144144
else if (bayer_format.bits == 12)
145-
unpack_12bit((uint8_t *)mem[0].data(), w, h, stride, &buf[0]);
145+
unpack_12bit((uint8_t *)mem[0].data(), info, &buf[0]);
146146
else
147147
throw std::runtime_error("unsupported bit depth " + std::to_string(bayer_format.bits));
148148

@@ -233,8 +233,8 @@ void dng_save(std::vector<libcamera::Span<uint8_t>> const &mem, unsigned int w,
233233
// This is just the thumbnail, but put it first to help software that only
234234
// reads the first IFD.
235235
TIFFSetField(tif, TIFFTAG_SUBFILETYPE, 1);
236-
TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, w >> 4);
237-
TIFFSetField(tif, TIFFTAG_IMAGELENGTH, h >> 4);
236+
TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, info.width >> 4);
237+
TIFFSetField(tif, TIFFTAG_IMAGELENGTH, info.height >> 4);
238238
TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
239239
TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
240240
TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
@@ -254,14 +254,14 @@ void dng_save(std::vector<libcamera::Span<uint8_t>> const &mem, unsigned int w,
254254
TIFFSetField(tif, TIFFTAG_EXIFIFD, offset_exififd);
255255

256256
// Make a small greyscale thumbnail, just to give some clue what's in here.
257-
std::vector<uint8_t> thumb_buf((w >> 4) * 3);
257+
std::vector<uint8_t> thumb_buf((info.width >> 4) * 3);
258258

259-
for (unsigned int y = 0; y < (h >> 4); y++)
259+
for (unsigned int y = 0; y < (info.height >> 4); y++)
260260
{
261-
for (unsigned int x = 0; x < (w >> 4); x++)
261+
for (unsigned int x = 0; x < (info.width >> 4); x++)
262262
{
263-
unsigned int off = (y * w + x) << 4;
264-
int grey = buf[off] + buf[off + 1] + buf[off + w] + buf[off + w + 1];
263+
unsigned int off = (y * info.width + x) << 4;
264+
int grey = buf[off] + buf[off + 1] + buf[off + info.width] + buf[off + info.width + 1];
265265
grey = white * sqrt(grey / (double)white); // fake "gamma"
266266
thumb_buf[3 * x] = thumb_buf[3 * x + 1] = thumb_buf[3 * x + 2] = grey >> (bayer_format.bits - 6);
267267
}
@@ -273,8 +273,8 @@ void dng_save(std::vector<libcamera::Span<uint8_t>> const &mem, unsigned int w,
273273

274274
// The main image (actually tends to show up as "sub-image 1").
275275
TIFFSetField(tif, TIFFTAG_SUBFILETYPE, 0);
276-
TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, w);
277-
TIFFSetField(tif, TIFFTAG_IMAGELENGTH, h);
276+
TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, info.width);
277+
TIFFSetField(tif, TIFFTAG_IMAGELENGTH, info.height);
278278
TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16);
279279
TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_CFA);
280280
TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
@@ -290,9 +290,9 @@ void dng_save(std::vector<libcamera::Span<uint8_t>> const &mem, unsigned int w,
290290
TIFFSetField(tif, TIFFTAG_BLACKLEVELREPEATDIM, &black_level_repeat_dim);
291291
TIFFSetField(tif, TIFFTAG_BLACKLEVEL, 4, &black_levels);
292292

293-
for (unsigned int y = 0; y < h; y++)
293+
for (unsigned int y = 0; y < info.height; y++)
294294
{
295-
if (TIFFWriteScanline(tif, &buf[w * y], y, 0) != 1)
295+
if (TIFFWriteScanline(tif, &buf[info.width * y], y, 0) != 1)
296296
throw std::runtime_error("error writing DNG image data");
297297
}
298298

0 commit comments

Comments
 (0)