Mercurial > hg > forks > libbpg
comparison bpgenc.c @ 4:bbd61622856a
Initial implementation of TIFF format read support via libtiff.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Wed, 07 Dec 2016 10:37:38 +0200 |
parents | ffcd1967fb5c |
children | 524eae707ba4 |
comparison
equal
deleted
inserted
replaced
3:ffcd1967fb5c | 4:bbd61622856a |
---|---|
29 #include <math.h> | 29 #include <math.h> |
30 #include <assert.h> | 30 #include <assert.h> |
31 | 31 |
32 #include <png.h> | 32 #include <png.h> |
33 #include <jpeglib.h> | 33 #include <jpeglib.h> |
34 #include <tiffio.h> | |
34 | 35 |
35 #include "bpgenc.h" | 36 #include "bpgenc.h" |
36 | 37 |
37 typedef uint16_t PIXEL; | 38 typedef uint16_t PIXEL; |
38 | 39 |
904 md_next = md->next; | 905 md_next = md->next; |
905 free(md->buf); | 906 free(md->buf); |
906 free(md); | 907 free(md); |
907 md = md_next; | 908 md = md_next; |
908 } | 909 } |
910 } | |
911 | |
912 Image *read_tiff(BPGMetaData **pmd, const char *filename, | |
913 BPGColorSpaceEnum color_space, int out_bit_depth, | |
914 int limited_range, int premultiplied_alpha) | |
915 { | |
916 TIFF *tif; | |
917 Image *img = NULL; | |
918 BPGImageFormatEnum img_format; | |
919 uint8_t *buf = NULL; | |
920 uint32_t img_width, img_height; | |
921 int img_alpha, img_bpp; | |
922 size_t img_linesize; | |
923 uint16_t img_depth, img_spp, img_sfmt, img_pconfig; | |
924 ColorConvertState cvt; | |
925 RGBConvertFunc *convert_func; | |
926 | |
927 *pmd = NULL; | |
928 | |
929 // Open and read TIFF header etc. | |
930 if ((tif = TIFFOpen(filename, "rb")) == NULL) | |
931 return NULL; | |
932 | |
933 TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &img_width); | |
934 TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &img_height); | |
935 TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &img_spp); | |
936 TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &img_depth); | |
937 TIFFGetField(tif, TIFFTAG_SAMPLEFORMAT, &img_sfmt); | |
938 TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &img_pconfig); | |
939 | |
940 // Check basics | |
941 if ((img_depth != 8 && img_depth != 16) || img_spp > 4) | |
942 goto err; | |
943 | |
944 img_linesize = TIFFScanlineSize(tif); | |
945 img_format = BPG_FORMAT_444; | |
946 img_bpp = sizeof(uint32_t) * img_depth / 8; | |
947 | |
948 if (img_spp > 3) | |
949 { | |
950 uint16_t img_esmp, *img_esmp_types; | |
951 | |
952 TIFFGetField(tif, TIFFTAG_EXTRASAMPLES, &img_esmp, &img_esmp_types); | |
953 img_alpha = img_esmp == 1 && img_esmp_types[0] == EXTRASAMPLE_UNASSALPHA; | |
954 } | |
955 else | |
956 img_alpha = 0; | |
957 | |
958 // Allocate temporary image space | |
959 buf = (uint8_t *) _TIFFmalloc(img_linesize * img_spp); | |
960 if (buf == NULL) | |
961 goto err; | |
962 | |
963 // Allocate target image | |
964 img = image_alloc(img_width, img_height, img_format, img_alpha, color_space, out_bit_depth); | |
965 if (img == NULL) | |
966 goto err; | |
967 | |
968 img->limited_range = limited_range; | |
969 img->premultiplied_alpha = premultiplied_alpha; | |
970 | |
971 convert_init(&cvt, img_depth, out_bit_depth, color_space, limited_range); | |
972 | |
973 int idx = img_depth == 16; | |
974 convert_func = rgb_to_cs[idx][color_space]; | |
975 | |
976 for (int y = 0; y < img->h; y++) | |
977 { | |
978 // Read TIFF image to raster | |
979 if (!TIFFReadScanline(tif, buf, y, 0)) | |
980 goto err; | |
981 | |
982 // Convert | |
983 convert_func(&cvt, | |
984 (PIXEL *)(img->data[0] + y * img->linesize[0]), | |
985 (PIXEL *)(img->data[1] + y * img->linesize[1]), | |
986 (PIXEL *)(img->data[2] + y * img->linesize[2]), | |
987 buf, img->w, img_spp); | |
988 } | |
989 | |
990 | |
991 err: | |
992 if (buf != NULL) | |
993 _TIFFfree(buf); | |
994 | |
995 TIFFClose(tif); | |
996 return img; | |
909 } | 997 } |
910 | 998 |
911 Image *read_png(BPGMetaData **pmd, | 999 Image *read_png(BPGMetaData **pmd, |
912 FILE *f, BPGColorSpaceEnum color_space, int out_bit_depth, | 1000 FILE *f, BPGColorSpaceEnum color_space, int out_bit_depth, |
913 int limited_range, int premultiplied_alpha) | 1001 int limited_range, int premultiplied_alpha) |
1418 jpeg_destroy_decompress(&cinfo); | 1506 jpeg_destroy_decompress(&cinfo); |
1419 *pmd = first_md; | 1507 *pmd = first_md; |
1420 return img; | 1508 return img; |
1421 } | 1509 } |
1422 | 1510 |
1511 static const char PROBE_TIFF_MAGIC_LE[] = { 'I', 'I', 42, 0 }; | |
1512 static const char PROBE_TIFF_MAGIC_BE[] = { 'M', 'M', 0, 42 }; | |
1513 #define PROBE_BUF_SIZE 8 | |
1514 | |
1423 Image *load_image(BPGMetaData **pmd, const char *infilename, | 1515 Image *load_image(BPGMetaData **pmd, const char *infilename, |
1424 BPGColorSpaceEnum color_space, int bit_depth, | 1516 BPGColorSpaceEnum color_space, int bit_depth, |
1425 int limited_range, int premultiplied_alpha) | 1517 int limited_range, int premultiplied_alpha) |
1426 { | 1518 { |
1427 FILE *f; | 1519 FILE *f; |
1439 | 1531 |
1440 fseek(f, 0, SEEK_SET); | 1532 fseek(f, 0, SEEK_SET); |
1441 | 1533 |
1442 if (png_sig_cmp(buf, 0, PROBE_BUF_SIZE) == 0) | 1534 if (png_sig_cmp(buf, 0, PROBE_BUF_SIZE) == 0) |
1443 img = read_png(&md, f, color_space, bit_depth, limited_range, premultiplied_alpha); | 1535 img = read_png(&md, f, color_space, bit_depth, limited_range, premultiplied_alpha); |
1536 else | |
1537 if (memcmp(buf, PROBE_TIFF_MAGIC_LE, sizeof(PROBE_TIFF_MAGIC_LE)) == 0 || | |
1538 memcmp(buf, PROBE_TIFF_MAGIC_BE, sizeof(PROBE_TIFF_MAGIC_BE)) == 0) | |
1539 img = read_tiff(&md, infilename, color_space, bit_depth, limited_range, premultiplied_alpha); | |
1444 else | 1540 else |
1445 img = read_jpeg(&md, f, bit_depth); | 1541 img = read_jpeg(&md, f, bit_depth); |
1446 | 1542 |
1447 err: | 1543 err: |
1448 fclose(f); | 1544 fclose(f); |