File: 300-raw.t

package info (click to toggle)
libimager-perl 1.019%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 6,824 kB
  • sloc: perl: 32,886; ansic: 28,193; makefile: 52; cpp: 4
file content (427 lines) | stat: -rw-r--r-- 12,623 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
#!perl -w
use strict;
use Test::More tests => 56;
use Imager qw(:all);
use Imager::Test qw/is_color3 is_color4 test_image test_image_mono is_image/;

-d "testout" or mkdir "testout";

Imager->open_log(log => "testout/t103raw.log");

$| = 1;

my $green=i_color_new(0,255,0,255);
my $blue=i_color_new(0,0,255,255);
my $red=i_color_new(255,0,0,255);

my $img=Imager::ImgRaw::new(150,150,3);
my $cmpimg=Imager::ImgRaw::new(150,150,3);

i_box_filled($img,70,25,130,125,$green);
i_box_filled($img,20,25,80,125,$blue);
i_arc($img,75,75,30,0,361,$red);
i_conv($img,[0.1, 0.2, 0.4, 0.2, 0.1]);

my $timg = Imager::ImgRaw::new(20, 20, 4);
my $trans = i_color_new(255, 0, 0, 127);
i_box_filled($timg, 0, 0, 20, 20, $green);
i_box_filled($timg, 2, 2, 18, 18, $trans);

open(FH,">testout/t103.raw") || die "Cannot open testout/t103.raw for writing\n";
binmode(FH);
my $IO = Imager::io_new_fd( fileno(FH) );
ok(i_writeraw_wiol($img, $IO), "write raw low") or
  print "# Cannot write testout/t103.raw\n";
close(FH);

open(FH,"testout/t103.raw") || die "Cannot open testout/t103.raw\n";
binmode(FH);
$IO = Imager::io_new_fd( fileno(FH) );
$cmpimg = i_readraw_wiol($IO, 150, 150, 3, 3, 0);
ok($cmpimg, "read raw low")
  or print "# Cannot read testout/t103.raw\n";
close(FH);

print "# raw average mean square pixel difference: ",sqrt(i_img_diff($img,$cmpimg))/150*150,"\n";

# I could have kept the raw images for these tests in binary files in
# testimg/, but I think keeping them as hex encoded data in here makes
# it simpler to add more if necessary
# Later we may change this to read from a scalar instead
save_data('testout/t103_base.raw');
save_data('testout/t103_3to4.raw');
save_data('testout/t103_line_int.raw');
save_data('testout/t103_img_int.raw');

# load the base image
open FH, "testout/t103_base.raw" 
  or die "Cannot open testout/t103_base.raw: $!";
binmode FH;
$IO = Imager::io_new_fd( fileno(FH) );

my $baseimg = i_readraw_wiol( $IO, 4, 4, 3, 3, 0);
ok($baseimg, "read base raw image")
  or die "Cannot read base raw image";
close FH;

# the actual read tests
# each read_test() call does 2 tests:
#  - check if the read succeeds
#  - check if it matches $baseimg
read_test('testout/t103_3to4.raw', 4, 4, 4, 3, 0, $baseimg);
read_test('testout/t103_line_int.raw', 4, 4, 3, 3, 1, $baseimg);
# intrl==2 is documented in raw.c but doesn't seem to be implemented
#read_test('testout/t103_img_int.raw', 4, 4, 3, 3, 2, $baseimg, 7);

# paletted images
SKIP:
{
  my $palim = Imager::i_img_pal_new(20, 20, 3, 256);
  ok($palim, "make paletted image")
    or skip("couldn't make paletted image", 2);
  my $redindex = Imager::i_addcolors($palim, $red);
  my $blueindex = Imager::i_addcolors($palim, $blue);
  for my $y (0..9) {
    Imager::i_ppal($palim, 0, $y, ($redindex) x 20);
  }
  for my $y (10..19) {
    Imager::i_ppal($palim, 0, $y, ($blueindex) x 20);
  }
  open FH, "> testout/t103_pal.raw"
    or die "Cannot create testout/t103_pal.raw: $!";
  binmode FH;
  $IO = Imager::io_new_fd(fileno(FH));
  ok(i_writeraw_wiol($palim, $IO), "write low paletted");
  close FH;
  
  open FH, "testout/t103_pal.raw"
    or die "Cannot open testout/t103_pal.raw: $!";
  binmode FH;
  my $data = do { local $/; <FH> };
  is($data, "\x0" x 200 . "\x1" x 200, "compare paletted data written");
  close FH;
}

# 16-bit image
# we don't have 16-bit reads yet
SKIP:
{
  my $img16 = Imager::i_img_16_new(150, 150, 3);
  ok($img16, "make 16-bit/sample image")
    or skip("couldn't make 16 bit/sample image", 1);
  i_box_filled($img16,70,25,130,125,$green);
  i_box_filled($img16,20,25,80,125,$blue);
  i_arc($img16,75,75,30,0,361,$red);
  i_conv($img16,[0.1, 0.2, 0.4, 0.2, 0.1]);
  
  open FH, "> testout/t103_16.raw" 
    or die "Cannot create testout/t103_16.raw: $!";
  binmode FH;
  $IO = Imager::io_new_fd(fileno(FH));
  ok(i_writeraw_wiol($img16, $IO), "write low 16 bit image");
  close FH;
}

# try a simple virtual image
SKIP:
{
  my $maskimg = Imager::i_img_masked_new($img, undef, 0, 0, 150, 150);
  ok($maskimg, "make masked image")
    or skip("couldn't make masked image", 3);

  open FH, "> testout/t103_virt.raw" 
    or die "Cannot create testout/t103_virt.raw: $!";
  binmode FH;
  $IO = Imager::io_new_fd(fileno(FH));
  ok(i_writeraw_wiol($maskimg, $IO), "write virtual raw");
  close FH;

  open FH, "testout/t103_virt.raw"
    or die "Cannot open testout/t103_virt.raw: $!";
  binmode FH;
  $IO = Imager::io_new_fd(fileno(FH));
  my $cmpimgmask = i_readraw_wiol($IO, 150, 150, 3, 3, 0);
  ok($cmpimgmask, "read result of masked write");
  my $diff = i_img_diff($maskimg, $cmpimgmask);
  print "# difference for virtual image $diff\n";
  is($diff, 0, "compare masked to read");

  # check that i_format is set correctly
  my $index = Imager::i_tags_find($cmpimgmask, 'i_format', 0);
  if ($index) {
    my $value = Imager::i_tags_get($cmpimgmask, $index);
    is($value, 'raw', "check i_format value");
  }
  else {
    fail("couldn't find i_format tag");
  }
}

{ # error handling checks
  # should get an error writing to a open for read file
  # make a empty file
  open RAW, "> testout/t103_empty.raw"
    or die "Cannot create testout/t103_empty.raw: $!";
  close RAW;
  open RAW, "< testout/t103_empty.raw"
    or die "Cannot open testout/t103_empty.raw: $!";
  my $im = Imager->new(xsize => 50, ysize=>50);
  ok(!$im->write(fh => \*RAW, type => 'raw', buffered => 0),
     "write to open for read handle");
  cmp_ok($im->errstr, '=~', '^Could not write to file: write\(\) failure', 
	 "check error message");
  close RAW;

  # should get an error reading an empty file
  ok(!$im->read(file => 'testout/t103_empty.raw', xsize => 50, ysize=>50, type=>'raw', interleave => 1),
     'read an empty file');
  is($im->errstr, 'premature end of file', "check message");
 SKIP:
  {
    # see 862083f7e40bc2a9e3b94aedce56c1336e7bdb25 in perl5 git
    $] >= 5.010
      or skip "5.8.x and earlier don't treat a read on a WRONLY file as an error", 2;
    open RAW, "> testout/t103_empty.raw"
      or die "Cannot create testout/t103_empty.raw: $!";
    ok(!$im->read(fh => \*RAW, , xsize => 50, ysize=>50, type=>'raw', interleave => 1),
       'read a file open for write');
    cmp_ok($im->errstr, '=~', '^error reading file: read\(\) failure', "check message");
    close RAW; # avoid a message on 5.22+
  }
}


{
  ok(grep($_ eq 'raw', Imager->read_types), "check raw in read types");
  ok(grep($_ eq 'raw', Imager->write_types), "check raw in write types");
}


{ # OO no interleave warning
  my $im = Imager->new;
  my $msg;
  local $SIG{__WARN__} = sub { $msg = "@_" };
  ok($im->read(file => "testout/t103_line_int.raw", xsize => 4, ysize => 4,
	       type => "raw"),
     "read without interleave parameter")
    or print "# ", $im->errstr, "\n";
  ok($msg, "should have warned");
  like($msg, qr/interleave/, "check warning is ok");
  # check we got the right value
  is_color3($im->getpixel(x => 0, y => 0), 0x00, 0x11, 0x22,
	    "check the image was read correctly");

  # check no warning if either is supplied
  $im = Imager->new;
  undef $msg;
  ok($im->read(file => "testout/t103_base.raw", xsize => 4, ysize => 4, type => "raw", interleave => 0), 
     "read with interleave 0");
  is($msg, undef, "no warning");
  is_color3($im->getpixel(x => 0, y => 0), 0x00, 0x11, 0x22,
	    "check read non-interleave");

  $im = Imager->new;
  undef $msg;
  ok($im->read(file => "testout/t103_base.raw", xsize => 4, ysize => 4, type => "raw", raw_interleave => 0), 
     "read with raw_interleave 0");
  is($msg, undef, "no warning");
  is_color3($im->getpixel(x => 1, y => 0), 0x01, 0x12, 0x23,
	    "check read non-interleave");

  # make sure set to 1 is sane
  $im = Imager->new;
  undef $msg;
  ok($im->read(file => "testout/t103_line_int.raw", xsize => 4, ysize => 4, type => "raw", raw_interleave => 1), 
     "read with raw_interleave 1");
  is($msg, undef, "no warning");
  is_color3($im->getpixel(x => 2, y => 0), 0x02, 0x13, 0x24,
	    "check read interleave = 1");
}

{ # invalid interleave error handling
  my $im = Imager->new;
  ok(!$im->read(file => "testout/t103_base.raw", raw_interleave => 2, type => "raw", xsize => 4, ysize => 4),
     "invalid interleave");
  is($im->errstr, "raw_interleave must be 0 or 1", "check message");
}

{ # store/data channel behaviour
  my $im = Imager->new;
  ok($im->read(file => "testout/t103_3to4.raw", xsize => 4, ysize => 4, 
	       raw_datachannels => 4, raw_interleave => 0, type => "raw"),
     "read 4 channel file as 3 channels")
    or print "# ", $im->errstr, "\n";
  is_color3($im->getpixel(x => 2, y => 1), 0x12, 0x23, 0x34,
	    "check read correctly");
}

{ # should fail to read with storechannels > 4
  my $im = Imager->new;
  ok(!$im->read(file => "testout/t103_line_int.raw", type => "raw",
		raw_interleave => 1, xsize => 4, ysize => 4,
		raw_storechannels => 5),
     "read with large storechannels");
  is($im->errstr, "raw_storechannels must be between 1 and 4", 
     "check error message");
}

{ # should zero spare channels if storechannels > datachannels
  my $im = Imager->new;
  ok($im->read(file => "testout/t103_base.raw", type => "raw",
		raw_interleave => 0, xsize => 4, ysize => 4,
		raw_storechannels => 4),
     "read with storechannels > datachannels");
  is($im->getchannels, 4, "should have 4 channels");
  is_color4($im->getpixel(x => 2, y => 1), 0x12, 0x23, 0x34, 0x00,
	    "check last channel zeroed");
}

{
  my @ims = ( basic => test_image(), mono => test_image_mono() );
  push @ims, masked => test_image()->masked();

  my $fail_close = sub {
    Imager::i_push_error(0, "synthetic close failure");
    return 0;
  };

  while (my ($type, $im) = splice(@ims, 0, 2)) {
    my $io = Imager::io_new_cb(sub { 1 }, undef, undef, $fail_close);
    ok(!$im->write(io => $io, type => "raw"),
       "write $type image with a failing close handler");
    like($im->errstr, qr/synthetic close failure/,
	 "check error message");
  }
}

{ # https://rt.cpan.org/Ticket/Display.html?id=106836
  my $im = test_image;
  my $data;
  ok($im->write(data => \$data, type => "raw", raw_interleave => 0), "save some raw image")
    or diag $im->errstr;
  my $im2 = Imager->new
    (
     data => \$data,
     filetype => "raw",
     xsize => $im->getwidth,
     ysize => $im->getheight,
     raw_datachannels => $im->getchannels,
     raw_storechannels => $im->getchannels,
     raw_interleave => 0,
    );
  ok($im2, "read raw image using new() method");
  is_image($im, $im2, "check they match");
}

Imager->close_log;

unless ($ENV{IMAGER_KEEP_FILES}) {
  unlink "testout/t103raw.log";
  unlink(qw(testout/t103_base.raw testout/t103_3to4.raw
	    testout/t103_line_int.raw testout/t103_img_int.raw))
}

sub read_test {
  my ($in, $xsize, $ysize, $data, $store, $intrl, $base) = @_;
  open FH, $in or die "Cannot open $in: $!";
  binmode FH;
  my $IO = Imager::io_new_fd( fileno(FH) );

  my $img = i_readraw_wiol($IO, $xsize, $ysize, $data, $store, $intrl);
 SKIP:
  {
    ok($img, "read_test $in read")
      or skip("couldn't read $in", 1);
    is(i_img_diff($img, $baseimg), 0, "read_test $in compare");
  }
}

sub save_data {
  my $outname = shift;
  my $data = load_data();
  open FH, "> $outname" or die "Cannot create $outname: $!";
  binmode FH;
  print FH $data;
  close FH;
}

sub load_data {
  my $hex = '';
  while (<DATA>) {
    next if /^#/;
    last if /^EOF/;
    chomp;
    $hex .= $_;
  }
  $hex =~ tr/ //d;
  my $result = pack("H*", $hex);
  #print unpack("H*", $result),"\n";
  return $result;
}

# FIXME: may need tests for 1,2,4 channel images

__DATA__
# we keep some packed raw images here
# we decode this in the code, ignoring lines starting with #, a subfile
# ends with EOF, data is HEX encoded (spaces ignored)

# basic 3 channel version of the image
001122 011223 021324 031425
102132 112233 122334 132435
203142 213243 223344 233445
304152 314253 324354 334455
EOF

# test image for reading a 4 channel image into a 3 channel image
# 4 x 4 pixels
00112233 01122334 02132435 03142536
10213243 11223344 12233445 13243546
20314253 21324354 22334455 23344556
30415263 31425364 32435465 33445566
EOF

# test image for line based interlacing
# 4 x 4 pixels
# first line
00 01 02 03
11 12 13 14
22 23 24 25

# second line
10 11 12 13
21 22 23 24
32 33 34 35

# third line
20 21 22 23
31 32 33 34
42 43 44 45

# fourth line
30 31 32 33
41 42 43 44
52 53 54 55

EOF

# test image for image based interlacing
# first channel
00 01 02 03
10 11 12 13
20 21 22 23
30 31 32 33

# second channel
11 12 13 14
21 22 23 24
31 32 33 34
41 42 43 44

# third channel
22 23 24 25
32 33 34 35
42 43 44 45
52 53 54 55

EOF