Mercurial > hg > forks > libbpg
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 { |