COVERAGE SUMMARY
FILE SUMMARY
NameExecutedRoutines%ExecutedLines%Unexecuted
/home/matt/eu/rds/include/std/image.e0180.00%02270.00%227
ROUTINE SUMMARY
RoutineExecutedLinesUnexecuted
read_bitmap()0490.00%49
unpack()0430.00%43
putBmpFileHeader()0290.00%29
putOneRowImage()0170.00%17
save_bitmap()0160.00%16
putImage1()0140.00%14
get_c_block()080.00%8
get_rgb_block()080.00%8
putColorTable()080.00%8
get_rgb()070.00%7
get_word()060.00%6
get_dword()040.00%4
region()040.00%4
graphics_point()020.00%2
positive_atom()020.00%2
row_bytes()020.00%2
text_point()020.00%2
two_seq()020.00%2
LINE COVERAGE DETAIL
#Executed
1
-- (c) Copyright - See License.txt
2
--
3
namespace image
4
5
public include std/graphcst.e
6
include std/convert.e
7
include std/machine.e
8
9
--****
10
-- == Graphics - Image Routines
11
--
12
-- <>
13
--
14
150
constant BMPFILEHDRSIZE = 14
160
constant OLDHDRSIZE = 12, NEWHDRSIZE = 40
170
constant EOF = -1
18
19
integer fn, error_code
20
210
220
return length(p) = 2 and p[1] >= 0 and p[2] >= 0
23
end type
24
250
26
-- read 2 bytes
27
integer lower, upper
28
290
lower = getc(fn)
300
upper = getc(fn)
310
if upper = EOF then
320
error_code = BMP_UNEXPECTED_EOF
33
end if
340
return upper * 256 + lower
35
end function
36
370
38
-- read 4 bytes
39
integer lower, upper
40
410
lower = get_word()
420
upper = get_word()
430
return upper * 65536 + lower
44
end function
45
460
47
-- read num_bytes bytes
48
sequence s
49
500
s = repeat(0, num_bytes)
510
for i = 1 to num_bytes do
520
s[i] = getc(fn)
530
end for
540
if s[$] = EOF then
550
error_code = BMP_UNEXPECTED_EOF
56
end if
570
return s
58
end function
59
600
61
-- get red, green, blue palette values
62
integer red, green, blue
63
640
blue = getc(fn)
650
green = getc(fn)
660
red = getc(fn)
670
if set_size = 4 then
680
if getc(fn) then
69
end if
70
end if
710
return {red, green, blue}
72
end function
73
740
75
-- reads palette
76
sequence s
77
780
s = {}
790
for i = 1 to num_dwords do
800
s = append(s, get_rgb(set_size))
810
end for
820
if s[$][3] = EOF then
830
error_code = BMP_UNEXPECTED_EOF
84
end if
850
return s
86
end function
87
880
89
-- number of bytes per row of pixel data
900
return floor(((BitCount * Width) + 31) / 32) * 4
91
end function
92
930
94
-- unpack the 1-d byte sequence into a 2-d sequence of pixels
95
sequence pic_2d, row, bits
96
integer bytes, next_byte, byte
97
980
pic_2d = {}
990
bytes = row_bytes(BitCount, Width)
1000
next_byte = 1
1010
for i = 1 to Height do
1020
row = {}
1030
if BitCount = 1 then
1040
for j = 1 to bytes do
1050
byte = image[next_byte]
1060
next_byte += 1
1070
bits = repeat(0, 8)
1080
for k = 8 to 1 by -1 do
1090
bits[k] = and_bits(byte, 1)
1100
byte = floor(byte/2)
1110
end for
1120
row &= bits
1130
end for
1140
elsif BitCount = 2 then
1150
for j = 1 to bytes do
1160
byte = image[next_byte]
1170
next_byte += 1
1180
bits = repeat(0, 4)
1190
for k = 4 to 1 by -1 do
1200
bits[k] = and_bits(byte, 3)
1210
byte = floor(byte/4)
1220
end for
1230
row &= bits
1240
end for
1250
elsif BitCount = 4 then
1260
for j = 1 to bytes do
1270
byte = image[next_byte]
1280
row = append(row, floor(byte/16))
1290
row = append(row, and_bits(byte, 15))
1300
next_byte += 1
1310
end for
1320
elsif BitCount = 8 then
1330
row = image[next_byte..next_byte+bytes-1]
1340
next_byte += bytes
135
else
1360
error_code = BMP_UNSUPPORTED_FORMAT
1370
exit
138
end if
1390
pic_2d = prepend(pic_2d, row[1..Width])
1400
end for
1410
return pic_2d
142
end function
143
144
--****
145
-- === Bitmap handling
146
--
147
148
--**
149
-- Read a bitmap (.BMP) file into a 2-d sequence of sequences (image)
150
--
151
-- Parameters:
152
-- # ##file_name## : a sequence, the path to a .bmp file to read from. The extension is not assumed if missing.
153
--
154
-- Returns:
155
-- An **object**, on success, a sequence of the form ##{palette,image}##. On failure, an error code is returned.
156
--
157
-- Comments:
158
-- In the returned value, the first element is a list of mixtures, each of which defines
159
-- a color, and the second, a list of point rows. Each pixel in a row is represented by its color index.
160
--
161
-- The file should be in the bitmap format. The most common variations of the format are supported.
162
--
163
-- Bitmaps of 2, 4, 16 or 256 colors are supported. If the file is not in a good format, an error
164
-- code (atom) is returned instead
165
--
166
--
167
-- public constant
168
-- BMP_OPEN_FAILED = 1,
169
-- BMP_UNEXPECTED_EOF = 2,
170
-- BMP_UNSUPPORTED_FORMAT = 3
171
--
172
--
173
-- You can create your own bitmap picture files using Windows Paintbrush and many other
174
-- graphics programs. You can then incorporate these pictures into your Euphoria programs.
175
--
176
-- Example 1:
177
--
178
--
179
-- x = read_bitmap("c:\\windows\\arcade.bmp")
180
--
181
--
182
-- Note:
183
-- double backslash needed to get single backslash in a string
184
--
185
-- See Also:
186
-- [[:save_bitmap]]
187
1880
189
atom Size
190
integer Type, X_hot, Y_hot, Planes, BitCount
191
atom Width, Height, Compression, OffBits, SizeHeader,
192
SizeImage, XPelsPerMeter, YPelsPerMeter, ClrUsed,
193
ClrImportant, NumColors
194
sequence Palette, Bits, two_d_bits
195
1960
error_code = 0
1970
fn = open(file_name, "rb")
1980
if fn = -1 then
1990
return BMP_OPEN_FAILED
200
end if
2010
Type = get_word()
2020
Size = get_dword()
2030
X_hot = get_word()
2040
Y_hot = get_word()
2050
OffBits = get_dword()
2060
SizeHeader = get_dword()
207
2080
if SizeHeader = NEWHDRSIZE then
2090
Width = get_dword()
2100
Height = get_dword()
2110
Planes = get_word()
2120
BitCount = get_word()
2130
Compression = get_dword()
2140
if Compression != 0 then
2150
close(fn)
2160
return BMP_UNSUPPORTED_FORMAT
217
end if
2180
SizeImage = get_dword()
2190
XPelsPerMeter = get_dword()
2200
YPelsPerMeter = get_dword()
2210
ClrUsed = get_dword()
2220
ClrImportant = get_dword()
2230
NumColors = (OffBits - SizeHeader - BMPFILEHDRSIZE) / 4
2240
if NumColors < 2 or NumColors > 256 then
2250
close(fn)
2260
return BMP_UNSUPPORTED_FORMAT
227
end if
2280
Palette = get_rgb_block(NumColors, 4)
229
2300
elsif SizeHeader = OLDHDRSIZE then
2310
Width = get_word()
2320
Height = get_word()
2330
Planes = get_word()
2340
BitCount = get_word()
2350
NumColors = (OffBits - SizeHeader - BMPFILEHDRSIZE) / 3
2360
SizeImage = row_bytes(BitCount, Width) * Height
2370
Palette = get_rgb_block(NumColors, 3)
238
else
2390
close(fn)
2400
return BMP_UNSUPPORTED_FORMAT
241
end if
2420
if Planes != 1 or Height <= 0 or Width <= 0 then
2430
close(fn)
2440
return BMP_UNSUPPORTED_FORMAT
245
end if
2460
Bits = get_c_block(row_bytes(BitCount, Width) * Height)
2470
close(fn)
2480
two_d_bits = unpack(Bits, BitCount, Width, Height)
2490
if error_code then
2500
return error_code
251
end if
2520
return {Palette, two_d_bits}
253
end function
254
255
-- type graphics_point(sequence p)
256
-- return length(p) = 2 and p[1] >= 0 and p[2] >= 0
257
-- end type
258
--
2590
2600
return length(p) = 2 and p[1] >= 1 and p[2] >= 1
261
and p[1] <= 200 and p[2] <= 500 -- rough sanity check
262
end type
263
2640
2650
return x >= 1
266
end type
267
268
integer numXPixels, numYPixels, bitCount, numRowBytes
2690
integer startXPixel =0, startYPixel = 0, endYPixel = 0
270
2710
272
-- a region on the screen
2730
if atom(r) then
2740
return r = 0
275
else
2760
return length(r) = 2 and graphics_point(r[1]) and
277
graphics_point(r[2])
278
end if
279
end type
280
2810
282
-- a two element sequence, both elements are sequences
2830
return length(s) = 2 and sequence(s[1]) and sequence(s[2])
284
end type
285
2860
287
integer offBytes
288
289
-- calculate bitCount, ie, color bits per pixel, (1, 2, 4, 8, or error)
2900
if numColors = 256 then
2910
bitCount = 8 -- 8 bits per pixel
2920
elsif numColors = 16 then
2930
bitCount = 4 -- 4 bits per pixel
2940
elsif numColors = 4 then
2950
bitCount = 2 -- 2 bits per pixel
2960
elsif numColors = 2 then
2970
bitCount = 1 -- 1 bit per pixel
298
else
2990
error_code = BMP_INVALID_MODE
3000
return
301
end if
302
3030
puts(fn, "BM") -- file-type field in the file header
3040
offBytes = 4 * numColors + BMPFILEHDRSIZE + NEWHDRSIZE
3050
numRowBytes = row_bytes(bitCount, numXPixels)
306
-- put total size of the file
3070
puts(fn, int_to_bytes(offBytes + numRowBytes * numYPixels))
308
3090
puts(fn, {0, 0, 0, 0}) -- reserved fields, must be 0
3100
puts(fn, int_to_bytes(offBytes)) -- offBytes is the offset to the start
311
-- of the bitmap information
3120
puts(fn, int_to_bytes(NEWHDRSIZE)) -- size of the secondary header
3130
puts(fn, int_to_bytes(numXPixels)) -- width of the bitmap in pixels
3140
puts(fn, int_to_bytes(numYPixels)) -- height of the bitmap in pixels
315
3160
puts(fn, {1, 0}) -- planes, must be a word of value 1
317
3180
puts(fn, {bitCount, 0}) -- bitCount
319
3200
puts(fn, {0, 0, 0, 0}) -- compression scheme
3210
puts(fn, {0, 0, 0, 0}) -- size image, not required
3220
puts(fn, {0, 0, 0, 0}) -- XPelsPerMeter, not required
3230
puts(fn, {0, 0, 0, 0}) -- YPelsPerMeter, not required
3240
puts(fn, int_to_bytes(numColors)) -- num colors used in the image
3250
puts(fn, int_to_bytes(numColors)) -- num important colors in the image
3260
end procedure
327
3280
329
-- write out one row of image data
330
integer j, byte, numBytesFilled
331
3320
x &= repeat(0, 7) -- 7 zeros is safe enough
333
3340
numBytesFilled = 0
3350
j = 1
3360
while j <= numXPixels do
3370
byte = x[j]
3380
for k = 1 to numPixelsPerByte - 1 do
3390
byte = byte * shift + x[j + k]
3400
end for
341
3420
puts(fn, byte)
3430
numBytesFilled += 1
3440
j += numPixelsPerByte
3450
end while
346
3470
for m = 1 to numRowBytes - numBytesFilled do
3480
puts(fn, 0)
3490
end for
3500
end procedure
351
3520
353
-- Write color table information to the .BMP file.
354
-- palette data is given as a sequence {{r,g,b},..,{r,g,b}}, where each
355
-- r, g, or b value is 0 to 255.
356
3570
for i = 1 to numColors do
3580
puts(fn, pal[i][3]) -- blue first in .BMP file
3590
puts(fn, pal[i][2]) -- green second
3600
puts(fn, pal[i][1]) -- red third
3610
puts(fn, 0) -- reserved, must be 0
3620
end for
3630
end procedure
364
3650
366
-- Write image data packed according to the bitCount information, in the order
367
-- last row ... first row. Data for each row is padded to a 4-byte boundary.
368
-- Image data is given as a 2-d sequence in the order first row... last row.
369
object x
370
integer numPixelsPerByte, shift
371
3720
numPixelsPerByte = 8 / bitCount
3730
shift = power(2, bitCount)
3740
for i = numYPixels to 1 by -1 do
3750
x = image[i]
3760
if atom(x) then
3770
error_code = BMP_INVALID_MODE
3780
return
3790
elsif length(x) != numXPixels then
3800
error_code = BMP_INVALID_MODE
3810
return
382
end if
3830
putOneRowImage(x, numPixelsPerByte, shift)
3840
end for
3850
end procedure
386
387
--**
388
-- Create a .BMP bitmap file, given a palette and a 2-d sequence of sequences of colors.
389
--
390
-- Parameters:
391
-- # ##palette_n_image## : a {palette, image} pair, like [[:read_bitmap()]] returns
392
-- # ##file_name## : a sequence, the name of the file to save to.
393
--
394
-- Returns:
395
-- An **integer**, 0 on success.
396
--
397
-- Comments:
398
-- This routine does the opposite of [[:read_bitmap]]().
399
-- The first element of ##palette_n_image## is a sequence of [[:mixture]]s defining each
400
-- color in the bitmap. The second element is a sequence of sequences of colors. The inner
401
-- sequences must have the same length.
402
--
403
-- The result will be one of the following codes:
404
--
405
-- public constant
406
-- BMP_SUCCESS = 0,
407
-- BMP_OPEN_FAILED = 1,
408
-- BMP_INVALID_MODE = 4 -- invalid graphics mode
409
-- -- or invalid argument
410
--
411
--
412
--
413
-- ##save_bitmap##() produces bitmaps of 2, 4, 16, or 256 colors and these can all be read with
414
-- ##read_bitmap##(). Windows Paintbrush and some other tools do not support 4-color bitmaps.
415
--
416
-- Example 1:
417
--
418
-- code = save_bitmap({paletteData, imageData},
419
-- "c:\\example\\a1.bmp")
420
--
421
--
422
-- See Also:
423
-- [[:read_bitmap]]
424
4250
426
sequence color, image
427
integer numColors
428
4290
error_code = BMP_SUCCESS
4300
fn = open(file_name, "wb")
4310
if fn = -1 then
4320
return BMP_OPEN_FAILED
433
end if
434
4350
color = palette_n_image[1]
4360
image = palette_n_image[2]
4370
numYPixels = length(image)
4380
numXPixels = length(image[1]) -- assume the same length with each row
4390
numColors = length(color)
440
4410
putBmpFileHeader(numColors)
442
4430
if error_code = BMP_SUCCESS then
4440
putColorTable(numColors, color)
4450
putImage1(image)
446
end if
4470
close(fn)
4480
return error_code
449
end function
450