include "pixelimage.s7i";
const string: EXIF_MAGIC is "Exif";
const string: EXIF_TIFF_MAGIC_LE is "II\42;\0;";
const string: EXIF_TIFF_MAGIC_BE is "MM\0;\42;";
const integer: EXIF_THUMBNAIL_WIDTH is 16#0100;
const integer: EXIF_IMAGE_DESCRIPTION is 16#010e;
const integer: EXIF_MANUFACTURER is 16#010f;
const integer: EXIF_MODEL is 16#0110;
const integer: EXIF_ORIENTATION is 16#0112;
const integer: EXIF_X_RESOLUTION is 16#011a;
const integer: EXIF_Y_RESOLUTION is 16#011b;
const integer: EXIF_RESOLUTION_UNIT is 16#0128;
const integer: EXIF_SOFTWARE is 16#0131;
const integer: EXIF_DATE_TIME is 16#0132;
const integer: EXIF_YCBCR_POSITIONING is 16#0213;
const integer: EXIF_OFFSET is 16#8769;
const integer: EXIF_UNSIGNED_BYTE_TYPE is 1;
const integer: EXIF_ASCII_STRINGS_TYPE is 2;
const integer: EXIF_UNSIGNED_SHORT_TYPE is 3;
const integer: EXIF_UNSIGNED_LONG_TYPE is 4;
const integer: EXIF_UNSIGNED_RATIONAL_TYPE is 5;
const integer: EXIF_SIGNED_BYTE_TYPE is 6;
const integer: EXIF_UNDEFINED_TYPE is 7;
const integer: EXIF_SIGNED_SHORT_TYPE is 8;
const integer: EXIF_SIGNED_LONG_TYPE is 9;
const integer: EXIF_SIGNED_RATIONAL_TYPE is 10;
const integer: EXIF_SINGLE_FLOAT_TYPE is 11;
const integer: EXIF_DOUBLE_FLOAT_TYPE is 12;
const integer: EXIF_ORIENTATION_DEFAULT is 0;
const integer: EXIF_ORIENTATION_NORMAL is 1;
const integer: EXIF_ORIENTATION_MIRROR_HORIZONTAL is 2;
const integer: EXIF_ORIENTATION_ROTATE_180 is 3;
const integer: EXIF_ORIENTATION_MIRROR_VERTICAL is 4;
const integer: EXIF_ORIENTATION_MIRROR_ROTATE_90 is 5;
const integer: EXIF_ORIENTATION_ROTATE_90 is 6;
const integer: EXIF_ORIENTATION_MIRROR_ROTATE_270 is 7;
const integer: EXIF_ORIENTATION_ROTATE_270 is 8;
const integer: EXIF_ORIENTATION_UNDEFINED is 9;
const type: exifDataType is new struct
var integer: orientation is 0;
end struct;
const proc: readExifData (in string: stri, inout exifDataType: exifData) is func
local
var integer: offsetToFirstIfd is 0;
var integer: pos is 1;
var integer: numberOfDirectoryEntries is 0;
var integer: tagNumber is 0;
var integer: format is 0;
var integer: numberOfComponents is 0;
begin
if stri[1 fixLen 4] = EXIF_TIFF_MAGIC_LE then
offsetToFirstIfd := bytes2Int(stri[5 fixLen 4], UNSIGNED, LE);
pos := succ(offsetToFirstIfd);
numberOfDirectoryEntries := bytes2Int(stri[pos fixLen 2], UNSIGNED, LE);
pos +:= 2;
while numberOfDirectoryEntries > 0 do
tagNumber := bytes2Int(stri[pos fixLen 2], UNSIGNED, LE);
format := bytes2Int(stri[pos + 2 fixLen 2], UNSIGNED, LE);
numberOfComponents := bytes2Int(stri[pos + 4 fixLen 4], UNSIGNED, LE);
if tagNumber = EXIF_ORIENTATION and format = EXIF_UNSIGNED_SHORT_TYPE then
exifData.orientation := bytes2Int(stri[pos + 8 fixLen 2], UNSIGNED, LE);
end if;
pos +:= 12;
decr(numberOfDirectoryEntries);
end while;
elsif stri[1 fixLen 4] = EXIF_TIFF_MAGIC_BE then
offsetToFirstIfd := bytes2Int(stri[5 fixLen 4], UNSIGNED, BE);
pos := succ(offsetToFirstIfd);
numberOfDirectoryEntries := bytes2Int(stri[pos fixLen 2], UNSIGNED, BE);
pos +:= 2;
while numberOfDirectoryEntries > 0 do
tagNumber := bytes2Int(stri[pos fixLen 2], UNSIGNED, BE);
format := bytes2Int(stri[pos + 2 fixLen 2], UNSIGNED, BE);
numberOfComponents := bytes2Int(stri[pos + 4 fixLen 4], UNSIGNED, BE);
if tagNumber = EXIF_ORIENTATION and format = EXIF_UNSIGNED_SHORT_TYPE then
exifData.orientation := bytes2Int(stri[pos + 8 fixLen 2], UNSIGNED, BE);
end if;
pos +:= 12;
decr(numberOfDirectoryEntries);
end while;
end if;
end func;
const proc: changeOrientation (inout pixelImage: image, in integer: orientation) is func
begin
case orientation of
when {EXIF_ORIENTATION_MIRROR_HORIZONTAL}:
mirrorHorizontally(image);
when {EXIF_ORIENTATION_ROTATE_180}:
rotate180(image);
when {EXIF_ORIENTATION_MIRROR_VERTICAL}:
mirrorVertically(image);
when {EXIF_ORIENTATION_MIRROR_ROTATE_90}:
image := getRotated270AndMirroredHorizontally(image);
when {EXIF_ORIENTATION_ROTATE_90}:
rotate270(image);
when {EXIF_ORIENTATION_MIRROR_ROTATE_270}:
image := getRotated90AndMirroredHorizontally(image);
when {EXIF_ORIENTATION_ROTATE_270}:
rotate90(image);
end case;
end func;