comparison bpgenc.c @ 34:5d51fff843eb default tip

A "commit dump" of random changes I've made, as I probably won't be touching this code anymore.
author Matti Hamalainen <ccr@tnsp.org>
date Sun, 08 Mar 2020 19:18:48 +0200
parents 33594243ce31
children
comparison
equal deleted inserted replaced
33:33594243ce31 34:5d51fff843eb
691 691
692 Image *image_alloc(int w, int h, BPGImageFormatEnum format, int has_alpha, 692 Image *image_alloc(int w, int h, BPGImageFormatEnum format, int has_alpha,
693 BPGColorSpaceEnum color_space, int bit_depth) 693 BPGColorSpaceEnum color_space, int bit_depth)
694 { 694 {
695 Image *img; 695 Image *img;
696 int i, linesize, w1, h1, c_count; 696 int i, c_count;
697 697
698 img = malloc(sizeof(Image)); 698 if ((img = malloc(sizeof(Image))) == NULL)
699 memset(img, 0, sizeof(*img)); 699 return NULL;
700
701 memset(img, 0, sizeof(Image));
700 702
701 img->w = w; 703 img->w = w;
702 img->h = h; 704 img->h = h;
703 img->format = format; 705 img->format = format;
704 img->has_alpha = has_alpha; 706 img->has_alpha = has_alpha;
714 716
715 if (has_alpha) 717 if (has_alpha)
716 c_count++; 718 c_count++;
717 719
718 for(i = 0; i < c_count; i++) { 720 for(i = 0; i < c_count; i++) {
721 int w1, h1, linesize;
722
719 get_plane_res(img, &w1, &h1, i); 723 get_plane_res(img, &w1, &h1, i);
720 724
721 /* multiple of 16 pixels to add borders */ 725 /* multiple of 16 pixels to add borders */
722 w1 = (w1 + (W_PAD - 1)) & ~(W_PAD - 1); 726 w1 = (w1 + (W_PAD - 1)) & ~(W_PAD - 1);
723 h1 = (h1 + (W_PAD - 1)) & ~(W_PAD - 1); 727 h1 = (h1 + (W_PAD - 1)) & ~(W_PAD - 1);
936 BPGMetaData *md; 940 BPGMetaData *md;
937 941
938 if (buf == NULL || len == 0) 942 if (buf == NULL || len == 0)
939 return -2; 943 return -2;
940 944
945 #ifdef TIFF_DEBUG
946 char *filename = NULL, *mtype = NULL;
947 FILE *fh;
948
949 switch (tag)
950 {
951 case BPG_EXTENSION_TAG_XMP: filename = "paska.xmp"; mtype = "XMP"; break;
952 case BPG_EXTENSION_TAG_EXIF: filename = "paska.exif"; mtype = "EXIF"; break;
953 case BPG_EXTENSION_TAG_ICCP: filename = "paska.iccp"; mtype = "ICCP"; break;
954 default: mtype = "???";
955 }
956 printf("bpg_add_md_contents(%p, %s (%d), %d, %p)\n", list, mtype, tag, len, buf);
957 if (filename != NULL && (fh = fopen(filename, "wb")) != NULL)
958 {
959 printf("bpg_add_md_contents() writing to file '%s' ..\n", filename);
960 fwrite(buf, len, 1, fh);
961 fclose(fh);
962 }
963 #endif
964
941 if ((md = bpg_md_alloc(tag)) == NULL) 965 if ((md = bpg_md_alloc(tag)) == NULL)
942 goto err; 966 goto err;
943 967
944 if ((md->buf = malloc(len)) == NULL) 968 if ((md->buf = malloc(len)) == NULL)
945 goto err; 969 goto err;
985 { 1009 {
986 { EXIFTAG_EXPOSURETIME , "ExposureTime" , EXIF_IFD_EXIF }, 1010 { EXIFTAG_EXPOSURETIME , "ExposureTime" , EXIF_IFD_EXIF },
987 { EXIFTAG_FNUMBER , "FNumber" , EXIF_IFD_EXIF }, 1011 { EXIFTAG_FNUMBER , "FNumber" , EXIF_IFD_EXIF },
988 { EXIFTAG_EXPOSUREPROGRAM , "ExposureProgram" , EXIF_IFD_EXIF }, 1012 { EXIFTAG_EXPOSUREPROGRAM , "ExposureProgram" , EXIF_IFD_EXIF },
989 { EXIFTAG_SPECTRALSENSITIVITY , "Spectralsensitivity" , EXIF_IFD_EXIF }, 1013 { EXIFTAG_SPECTRALSENSITIVITY , "Spectralsensitivity" , EXIF_IFD_EXIF },
1014 // { EXIFTAG_ISOSPEEDRATINGS , "ISOSpeed" , EXIF_IFD_EXIF },
1015 // { EXIFTAG_OECF , "OptoElectricConversion" , EXIF_IFD_EXIF },
1016 // { EXIFTAG_EXIFVERSION , "ExifVersion" , EXIF_IFD_EXIF },
990 { EXIFTAG_DATETIMEORIGINAL , "DateTimeOriginal" , EXIF_IFD_EXIF }, 1017 { EXIFTAG_DATETIMEORIGINAL , "DateTimeOriginal" , EXIF_IFD_EXIF },
991 { EXIFTAG_DATETIMEDIGITIZED , "DateTimeDigitized" , EXIF_IFD_EXIF }, 1018 { EXIFTAG_DATETIMEDIGITIZED , "DateTimeDigitized" , EXIF_IFD_EXIF },
1019 // { EXIFTAG_COMPONENTSCONFIGURATION , "ComponentsConfiguration" , EXIF_IFD_EXIF },
1020 // { EXIFTAG_COMPRESSEDBITSPERPIXEL , "ImageCompression" , EXIF_IFD_EXIF },
992 { EXIFTAG_SHUTTERSPEEDVALUE , "ShutterSpeed" , EXIF_IFD_EXIF }, 1021 { EXIFTAG_SHUTTERSPEEDVALUE , "ShutterSpeed" , EXIF_IFD_EXIF },
993 { EXIFTAG_APERTUREVALUE , "Aperture" , EXIF_IFD_EXIF }, 1022 { EXIFTAG_APERTUREVALUE , "Aperture" , EXIF_IFD_EXIF },
994 { EXIFTAG_BRIGHTNESSVALUE , "Brightness" , EXIF_IFD_EXIF }, 1023 { EXIFTAG_BRIGHTNESSVALUE , "Brightness" , EXIF_IFD_EXIF },
995 { EXIFTAG_EXPOSUREBIASVALUE , "ExposureBias" , EXIF_IFD_EXIF }, 1024 { EXIFTAG_EXPOSUREBIASVALUE , "ExposureBias" , EXIF_IFD_EXIF },
996 { EXIFTAG_MAXAPERTUREVALUE , "MaxAperture" , EXIF_IFD_EXIF }, 1025 { EXIFTAG_MAXAPERTUREVALUE , "MaxAperture" , EXIF_IFD_EXIF },
999 { EXIFTAG_METERINGMODE , "MeteringMode" , EXIF_IFD_EXIF }, 1028 { EXIFTAG_METERINGMODE , "MeteringMode" , EXIF_IFD_EXIF },
1000 { EXIFTAG_LIGHTSOURCE , "Lightsource" , EXIF_IFD_EXIF }, 1029 { EXIFTAG_LIGHTSOURCE , "Lightsource" , EXIF_IFD_EXIF },
1001 { EXIFTAG_FLASH , "Flash" , EXIF_IFD_EXIF }, 1030 { EXIFTAG_FLASH , "Flash" , EXIF_IFD_EXIF },
1002 { EXIFTAG_FOCALLENGTH , "FocalLength" , EXIF_IFD_EXIF }, 1031 { EXIFTAG_FOCALLENGTH , "FocalLength" , EXIF_IFD_EXIF },
1003 { EXIFTAG_SUBJECTAREA , "SubjectArea" , EXIF_IFD_EXIF }, 1032 { EXIFTAG_SUBJECTAREA , "SubjectArea" , EXIF_IFD_EXIF },
1033 // { EXIFTAG_MAKERNOTE , "MakerNote" , EXIF_IFD_EXIF },
1004 { EXIFTAG_USERCOMMENT , "UserComment" , EXIF_IFD_EXIF }, 1034 { EXIFTAG_USERCOMMENT , "UserComment" , EXIF_IFD_EXIF },
1005 { EXIFTAG_SUBSECTIME , "SubSecTime" , EXIF_IFD_EXIF }, 1035 { EXIFTAG_SUBSECTIME , "SubSecTime" , EXIF_IFD_EXIF },
1006 { EXIFTAG_SUBSECTIMEORIGINAL , "SubSecTimeOriginal" , EXIF_IFD_EXIF }, 1036 { EXIFTAG_SUBSECTIMEORIGINAL , "SubSecTimeOriginal" , EXIF_IFD_EXIF },
1007 { EXIFTAG_SUBSECTIMEDIGITIZED , "SubSecTimeDigitized" , EXIF_IFD_EXIF }, 1037 { EXIFTAG_SUBSECTIMEDIGITIZED , "SubSecTimeDigitized" , EXIF_IFD_EXIF },
1008 1038
1039 // { EXIFTAG_FLASHPIXVERSION , "FlashpixVersion" , EXIF_IFD_EXIF },
1009 { EXIFTAG_COLORSPACE , "Colorspace" , EXIF_IFD_EXIF }, 1040 { EXIFTAG_COLORSPACE , "Colorspace" , EXIF_IFD_EXIF },
1010 { EXIFTAG_PIXELXDIMENSION , "Validimage" , EXIF_IFD_EXIF }, 1041 { EXIFTAG_PIXELXDIMENSION , "Validimage" , EXIF_IFD_EXIF },
1011 { EXIFTAG_PIXELYDIMENSION , "Validimage" , EXIF_IFD_EXIF }, 1042 { EXIFTAG_PIXELYDIMENSION , "Validimage" , EXIF_IFD_EXIF },
1012 { EXIFTAG_RELATEDSOUNDFILE , "Relatedaudio" , EXIF_IFD_EXIF }, 1043 { EXIFTAG_RELATEDSOUNDFILE , "Relatedaudio" , EXIF_IFD_EXIF },
1013 { EXIFTAG_FLASHENERGY , "Flashenergy" , EXIF_IFD_EXIF }, 1044 { EXIFTAG_FLASHENERGY , "Flashenergy" , EXIF_IFD_EXIF },
1018 { EXIFTAG_SUBJECTLOCATION , "SubjectLocation" , EXIF_IFD_EXIF }, 1049 { EXIFTAG_SUBJECTLOCATION , "SubjectLocation" , EXIF_IFD_EXIF },
1019 { EXIFTAG_EXPOSUREINDEX , "ExposureIndex" , EXIF_IFD_EXIF }, 1050 { EXIFTAG_EXPOSUREINDEX , "ExposureIndex" , EXIF_IFD_EXIF },
1020 { EXIFTAG_SENSINGMETHOD , "SensingMethod" , EXIF_IFD_EXIF }, 1051 { EXIFTAG_SENSINGMETHOD , "SensingMethod" , EXIF_IFD_EXIF },
1021 { EXIFTAG_FILESOURCE , "FileSource" , EXIF_IFD_EXIF }, 1052 { EXIFTAG_FILESOURCE , "FileSource" , EXIF_IFD_EXIF },
1022 { EXIFTAG_SCENETYPE , "SceneType" , EXIF_IFD_EXIF }, 1053 { EXIFTAG_SCENETYPE , "SceneType" , EXIF_IFD_EXIF },
1054 // { EXIFTAG_CFAPATTERN , "CFApattern" , EXIF_IFD_EXIF },
1023 { EXIFTAG_CUSTOMRENDERED , "CustomRendered" , EXIF_IFD_EXIF }, 1055 { EXIFTAG_CUSTOMRENDERED , "CustomRendered" , EXIF_IFD_EXIF },
1024 { EXIFTAG_EXPOSUREMODE , "ExposureMode" , EXIF_IFD_EXIF }, 1056 { EXIFTAG_EXPOSUREMODE , "ExposureMode" , EXIF_IFD_EXIF },
1025 { EXIFTAG_WHITEBALANCE , "WhiteBalance" , EXIF_IFD_EXIF }, 1057 { EXIFTAG_WHITEBALANCE , "WhiteBalance" , EXIF_IFD_EXIF },
1026 { EXIFTAG_DIGITALZOOMRATIO , "DigitalZoom" , EXIF_IFD_EXIF }, 1058 { EXIFTAG_DIGITALZOOMRATIO , "DigitalZoom" , EXIF_IFD_EXIF },
1027 { EXIFTAG_FOCALLENGTHIN35MMFILM , "FocalLength35mm" , EXIF_IFD_EXIF }, 1059 { EXIFTAG_FOCALLENGTHIN35MMFILM , "FocalLength35mm" , EXIF_IFD_EXIF },
1090 entry->format = type; 1122 entry->format = type;
1091 1123
1092 exif_content_add_entry(exif->ifd[conv->ifd], entry); 1124 exif_content_add_entry(exif->ifd[conv->ifd], entry);
1093 (*added)++; 1125 (*added)++;
1094 } 1126 }
1127 }
1128 }
1129 #endif
1130
1131
1132 #ifdef TIFF_DEBUG
1133 static void tiff_tags_dump(TIFF *tif, const TIFFTagConvertInfo *table)
1134 {
1135 const TIFFTagConvertInfo *conv;
1136
1137 for (conv = table; conv->tag != 0 && conv->name != NULL; conv++)
1138 {
1139 const TIFFField *tfd = TIFFFieldWithTag(tif, conv->tag);
1140 TIFFDataType type = TIFFFieldDataType(tfd);
1141 uint16_t tmp_short;
1142 float tmp_rat;
1143 char *tmp_str, *name = "?";
1144 char tmp_buf[128] = "-";
1145 int have;
1146
1147 switch (type)
1148 {
1149 case TIFF_SHORT:
1150 name = "short";
1151 if ((have = TIFFGetField(tif, conv->tag, &tmp_short)))
1152 snprintf(tmp_buf, sizeof(tmp_buf), "%d", tmp_short);
1153 break;
1154 case TIFF_RATIONAL:
1155 name = "rational";
1156 if ((have = TIFFGetField(tif, conv->tag, &tmp_rat)))
1157 snprintf(tmp_buf, sizeof(tmp_buf), "%1.2f", tmp_rat);
1158 break;
1159 case TIFF_ASCII:
1160 name = "ascii";
1161 if ((have = (TIFFGetField(tif, conv->tag, &tmp_str) && tmp_str != NULL)))
1162 snprintf(tmp_buf, sizeof(tmp_buf), "'%s'", tmp_str);
1163 break;
1164
1165 default:
1166 have = 0;
1167 }
1168 if (have)
1169 printf("%-20s [%-10s]: %s\n", conv->name, name, tmp_buf);
1095 } 1170 }
1096 } 1171 }
1097 #endif 1172 #endif
1098 1173
1099 1174
1153 // Check basics 1228 // Check basics
1154 err_spp = 0; 1229 err_spp = 0;
1155 switch (img_pmetric) 1230 switch (img_pmetric)
1156 { 1231 {
1157 case PHOTOMETRIC_MINISBLACK: 1232 case PHOTOMETRIC_MINISBLACK:
1233 case PHOTOMETRIC_MINISWHITE:
1158 img_format = BPG_FORMAT_GRAY; 1234 img_format = BPG_FORMAT_GRAY;
1159 color_space = BPG_CS_YCbCr; 1235 color_space = BPG_CS_YCbCr;
1160 if (img_spp != 1) 1236 if (img_spp != 1)
1161 err_spp = 1; 1237 err_spp = 1;
1162 break; 1238 break;
1196 goto err; 1272 goto err;
1197 } 1273 }
1198 1274
1199 img_linesize = TIFFScanlineSize(tif); 1275 img_linesize = TIFFScanlineSize(tif);
1200 1276
1277 #ifdef TIFF_DEBUG
1278 int img_bpp = sizeof(uint32_t) * img_depth / 8;
1279 printf(
1280 "\nTIFF '%s'\n"
1281 " %d x %d, spp=%d, bpp=%d, depth=%d, pmet=%d\n"
1282 " pconfig=%d, line_size=%d, cbps=%d\n",
1283 filename,
1284 img_width, img_height, img_spp, img_bpp, img_depth, img_pmetric,
1285 img_pconfig, img_linesize, img_width * img_bpp);
1286 #endif
1287
1201 if (img_spp > 3) 1288 if (img_spp > 3)
1202 { 1289 {
1203 uint16_t img_esmp, *img_esmp_types; 1290 uint16_t img_esmp, *img_esmp_types;
1204 1291
1205 TIFFGetField(tif, TIFFTAG_EXTRASAMPLES, &img_esmp, &img_esmp_types); 1292 TIFFGetField(tif, TIFFTAG_EXTRASAMPLES, &img_esmp, &img_esmp_types);
1206 img_alpha = img_esmp == 1 && img_esmp_types[0] == EXTRASAMPLE_ASSOCALPHA; 1293 img_alpha = img_esmp == 1 && img_esmp_types[0] == EXTRASAMPLE_ASSOCALPHA;
1294 #ifdef TIFF_DEBUG
1295 printf(" esmp=%d: ", img_esmp);
1296 for (int n = 0; n < img_esmp; n++)
1297 printf("#%d=%d%s", n + 1, img_esmp_types[n], (n < img_esmp - 1) ? ", " : "");
1298 printf("\n");
1299 #endif
1207 } 1300 }
1208 else 1301 else
1209 img_alpha = 0; 1302 img_alpha = 0;
1303
1304 #ifdef TIFF_DEBUG
1305 printf(" alpha: %s\n\n", img_alpha ? "yes" : "no");
1306 #endif
1210 1307
1211 // Allocate temporary image space 1308 // Allocate temporary image space
1212 buf = (uint8_t *) _TIFFmalloc(img_linesize * img_spp); 1309 buf = (uint8_t *) _TIFFmalloc(img_linesize * img_spp);
1213 if (buf == NULL) 1310 if (buf == NULL)
1214 goto err; 1311 goto err;
1240 convert_func = rgb_to_cs[idx][color_space]; 1337 convert_func = rgb_to_cs[idx][color_space];
1241 1338
1242 for (y = 0; y < img->h; y++) 1339 for (y = 0; y < img->h; y++)
1243 { 1340 {
1244 // Read TIFF image to raster 1341 // Read TIFF image to raster
1342 /*
1343 for (int n = 0; n < img_spp; n++)
1344 if (!TIFFReadScanline(tif, buf + (img_linesize * n), y, n))
1345 goto err;
1346 */
1245 if (!TIFFReadScanline(tif, buf, y, 0)) 1347 if (!TIFFReadScanline(tif, buf, y, 0))
1246 goto err; 1348 goto err;
1247 1349
1248 // Convert the scanline data 1350 // Convert the scanline data
1249 switch (img_pmetric) 1351 switch (img_pmetric)
1284 ((uint8_t *) buf) + 3, img->w, 4); 1386 ((uint8_t *) buf) + 3, img->w, 4);
1285 } 1387 }
1286 } 1388 }
1287 break; 1389 break;
1288 1390
1391 case PHOTOMETRIC_MINISWHITE:
1289 case PHOTOMETRIC_MINISBLACK: 1392 case PHOTOMETRIC_MINISBLACK:
1290 if (img_depth == 16) 1393 if (img_depth == 16)
1291 { 1394 {
1292 luma16_to_gray(&cvt, 1395 luma16_to_gray(&cvt,
1293 (PIXEL *)(img->data[0] + y * img->linesize[0]), 1396 (PIXEL *)(img->data[0] + y * img->linesize[0]),
1337 exif_data_set_option(exif, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION); 1440 exif_data_set_option(exif, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION);
1338 exif_data_set_data_type(exif, EXIF_DATA_TYPE_COMPRESSED); 1441 exif_data_set_data_type(exif, EXIF_DATA_TYPE_COMPRESSED);
1339 exif_data_set_byte_order(exif, EXIF_BYTE_ORDER_INTEL); 1442 exif_data_set_byte_order(exif, EXIF_BYTE_ORDER_INTEL);
1340 1443
1341 tiff_tags_convert(tif, tiff_tag_convert_table, exif_mem, exif, &added); 1444 tiff_tags_convert(tif, tiff_tag_convert_table, exif_mem, exif, &added);
1445 #ifdef TIFF_DEBUG
1446 tiff_tags_dump(tif, tiff_tag_convert_table);
1447 #endif
1342 1448
1343 if (TIFFGetField(tif, TIFFTAG_EXIFIFD, &tmp_offs) && 1449 if (TIFFGetField(tif, TIFFTAG_EXIFIFD, &tmp_offs) &&
1344 TIFFReadEXIFDirectory(tif, tmp_offs)) 1450 TIFFReadEXIFDirectory(tif, tmp_offs))
1345 { 1451 {
1346 tiff_tags_convert(tif, exif_tag_convert_table, exif_mem, exif, &added); 1452 tiff_tags_convert(tif, exif_tag_convert_table, exif_mem, exif, &added);
1453 #ifdef TIFF_DEBUG
1454 tiff_tags_dump(tif, exif_tag_convert_table);
1455 #endif
1347 } 1456 }
1348 1457
1349 if (added) 1458 if (added)
1350 { 1459 {
1351 uint8_t *ex_buf = NULL; 1460 uint8_t *ex_buf = NULL;
1375 free(buf2); 1484 free(buf2);
1376 1485
1377 TIFFClose(tif); 1486 TIFFClose(tif);
1378 return img; 1487 return img;
1379 } 1488 }
1380
1381 1489
1382 Image *read_png(BPGMetaData **pmd, 1490 Image *read_png(BPGMetaData **pmd,
1383 FILE *f, BPGColorSpaceEnum color_space, int out_bit_depth, 1491 FILE *f, BPGColorSpaceEnum color_space, int out_bit_depth,
1384 int limited_range, int premultiplied_alpha) 1492 int limited_range, int premultiplied_alpha)
1385 { 1493 {