Mercurial > hg > dmlib
comparison tools/libgfx.c @ 2093:d17512dbb4ef
Some work on reading >8bpp images.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Thu, 28 Feb 2019 12:32:07 +0200 |
parents | 614b161c0aa5 |
children | 4276b8c0fef0 |
comparison
equal
deleted
inserted
replaced
2092:614b161c0aa5 | 2093:d17512dbb4ef |
---|---|
128 return NULL; | 128 return NULL; |
129 | 129 |
130 img->width = width; | 130 img->width = width; |
131 img->height = height; | 131 img->height = height; |
132 img->format = format; | 132 img->format = format; |
133 img->bpp = (bpp <= 0) ? dmImageGetBytesPerPixel(format) * 8 : bpp; | 133 img->bpp = (bpp <= 0) ? dmImageGetBitsPerPixel(format) : bpp; |
134 img->pitch = width * img->bpp; | 134 img->pitch = (width * img->bpp) / 8; |
135 img->size = img->pitch * img->height; | 135 img->size = img->pitch * img->height; |
136 img->ctransp = -1; | 136 img->ctransp = -1; |
137 img->aspect = -1; | 137 img->aspect = -1; |
138 | 138 |
139 if ((img->data = dmMalloc(img->size)) == NULL) | 139 if ((img->data = dmMalloc(img->size)) == NULL) |
712 png_set_write_fn(png_ptr, fp, dmPNGWriteData, dmPNGWriteFlush); | 712 png_set_write_fn(png_ptr, fp, dmPNGWriteData, dmPNGWriteFlush); |
713 | 713 |
714 // Write PNG header info | 714 // Write PNG header info |
715 switch (spec->format) | 715 switch (spec->format) |
716 { | 716 { |
717 case DM_COLFMT_PALETTE: fmt = PNG_COLOR_TYPE_PALETTE; break; | 717 case DM_COLFMT_PALETTE : fmt = PNG_COLOR_TYPE_PALETTE; break; |
718 case DM_COLFMT_RGB : fmt = PNG_COLOR_TYPE_RGB; break; | 718 case DM_COLFMT_GRAYSCALE : fmt = PNG_COLOR_TYPE_GRAY; break; |
719 case DM_COLFMT_RGBA : fmt = PNG_COLOR_TYPE_RGB_ALPHA; break; | 719 case DM_COLFMT_RGB : fmt = PNG_COLOR_TYPE_RGB; break; |
720 case DM_COLFMT_RGBA : fmt = PNG_COLOR_TYPE_RGB_ALPHA; break; | |
720 default: | 721 default: |
721 res = dmError(DMERR_NOT_SUPPORTED, | 722 res = dmError(DMERR_NOT_SUPPORTED, |
722 "PNG: Unsupported image format %d.\n", | 723 "PNG: Unsupported image format %d.\n", |
723 spec->format); | 724 spec->format); |
724 goto error; | 725 goto error; |
799 png_infop info_ptr = NULL; | 800 png_infop info_ptr = NULL; |
800 png_colorp palette = NULL; | 801 png_colorp palette = NULL; |
801 png_bytep *row_pointers = NULL; | 802 png_bytep *row_pointers = NULL; |
802 png_bytep trans = NULL; | 803 png_bytep trans = NULL; |
803 png_uint_32 width, height, res_x = 0, res_y = 0; | 804 png_uint_32 width, height, res_x = 0, res_y = 0; |
804 int i, bit_depth, color_type, ncolors, ntrans, unit_type; | 805 int i, itype, bit_depth, color_type, ncolors, ntrans, unit_type; |
805 int res = DMERR_OK; | 806 int res = DMERR_OK; |
806 DMImage *img; | 807 DMImage *img; |
807 | 808 |
808 // Create PNG structures | 809 // Create PNG structures |
809 png_ptr = png_create_read_struct( | 810 png_ptr = png_create_read_struct( |
850 } | 851 } |
851 | 852 |
852 switch (color_type) | 853 switch (color_type) |
853 { | 854 { |
854 case PNG_COLOR_TYPE_GRAY: | 855 case PNG_COLOR_TYPE_GRAY: |
855 if (bit_depth < 8) | |
856 png_set_expand_gray_1_2_4_to_8(png_ptr); | |
857 | |
858 if (bit_depth > 8) | 856 if (bit_depth > 8) |
859 { | 857 { |
860 res = dmError(DMERR_NOT_SUPPORTED, | 858 res = dmError(DMERR_NOT_SUPPORTED, |
861 "PNG: Unsupported bit depth for grayscale image: %d\n", | 859 "PNG: Unsupported bit depth for grayscale image: %d\n", |
862 bit_depth); | 860 bit_depth); |
863 goto error; | 861 goto error; |
864 } | 862 } |
863 | |
864 if (bit_depth < 8) | |
865 png_set_expand_gray_1_2_4_to_8(png_ptr); | |
866 | |
867 itype = DM_COLFMT_GRAYSCALE; | |
865 break; | 868 break; |
866 | 869 |
867 case PNG_COLOR_TYPE_PALETTE: | 870 case PNG_COLOR_TYPE_PALETTE: |
868 png_set_packing(png_ptr); | 871 png_set_packing(png_ptr); |
872 itype = DM_COLFMT_PALETTE; | |
873 break; | |
874 | |
875 case PNG_COLOR_TYPE_RGB: | |
876 itype = DM_COLFMT_RGB; | |
877 break; | |
878 | |
879 case PNG_COLOR_TYPE_RGBA: | |
880 itype = DM_COLFMT_RGBA; | |
869 break; | 881 break; |
870 | 882 |
871 default: | 883 default: |
872 res = dmError(DMERR_NOT_SUPPORTED, | 884 res = dmError(DMERR_NOT_SUPPORTED, |
873 "PNG: RGB/RGBA images not supported for loading.\n"); | 885 "PNG: RGB/RGBA images not supported for loading.\n"); |
877 // Allocate image | 889 // Allocate image |
878 dmMsg(2, "PNG: %d x %d, depth=%d, type=%d\n", | 890 dmMsg(2, "PNG: %d x %d, depth=%d, type=%d\n", |
879 width, height, bit_depth, color_type); | 891 width, height, bit_depth, color_type); |
880 | 892 |
881 if ((*pimg = img = dmImageAlloc(width, height, | 893 if ((*pimg = img = dmImageAlloc(width, height, |
882 DM_COLFMT_PALETTE, | 894 itype, |
883 // XXX TODO? When/if we ever handle < 8bit indexed correctly, we can use the actual bpp | 895 // XXX TODO? When/if we ever handle < 8bit indexed correctly, we can use the actual bpp |
884 -1 /* bit_depth */)) == NULL) | 896 -1 /* bit_depth */)) == NULL) |
885 { | 897 { |
886 res = dmError(DMERR_MALLOC, | 898 res = dmError(DMERR_MALLOC, |
887 "PNG: Could not allocate image data.\n"); | 899 "PNG: Could not allocate image data.\n"); |
906 | 918 |
907 png_read_end(png_ptr, NULL); | 919 png_read_end(png_ptr, NULL); |
908 png_free(png_ptr, row_pointers); | 920 png_free(png_ptr, row_pointers); |
909 | 921 |
910 // Create palette | 922 // Create palette |
911 switch (color_type) | 923 if (color_type == PNG_COLOR_TYPE_PALETTE) |
912 { | 924 { |
913 case PNG_COLOR_TYPE_GRAY: | 925 png_get_PLTE(png_ptr, info_ptr, &palette, &ncolors); |
914 ncolors = 256; | 926 if (ncolors > 0 && palette != NULL) |
915 dmMsg(2, "PNG: Generating %d color grayscale palette.\n", ncolors); | 927 { |
928 dmMsg(2, "PNG: Palette of %d colors found.\n", ncolors); | |
916 | 929 |
917 if (!dmImagePaletteAlloc(img, ncolors, -1)) | 930 if (!dmImagePaletteAlloc(img, ncolors, -1)) |
918 { | 931 { |
919 res = DMERR_MALLOC; | 932 res = DMERR_MALLOC; |
920 goto error; | 933 goto error; |
921 } | 934 } |
922 | 935 |
923 for (i = 0; i < img->ncolors; i++) | 936 for (i = 0; i < img->ncolors; i++) |
924 { | 937 { |
925 img->pal[i].r = img->pal[i].g = img->pal[i].b = i; | 938 img->pal[i].r = palette[i].red; |
926 } | 939 img->pal[i].g = palette[i].green; |
927 break; | 940 img->pal[i].b = palette[i].blue; |
928 | 941 } |
929 case PNG_COLOR_TYPE_PALETTE: | 942 } |
930 png_get_PLTE(png_ptr, info_ptr, &palette, &ncolors); | 943 |
931 dmMsg(2, "PNG: Palette of %d colors found.\n", ncolors); | |
932 if (ncolors > 0 && palette != NULL) | |
933 { | |
934 if (!dmImagePaletteAlloc(img, ncolors, -1)) | |
935 { | |
936 res = DMERR_MALLOC; | |
937 goto error; | |
938 } | |
939 | |
940 for (i = 0; i < img->ncolors; i++) | |
941 { | |
942 img->pal[i].r = palette[i].red; | |
943 img->pal[i].g = palette[i].green; | |
944 img->pal[i].b = palette[i].blue; | |
945 } | |
946 } | |
947 break; | |
948 } | |
949 | |
950 if (color_type == PNG_COLOR_TYPE_PALETTE || | |
951 color_type == PNG_COLOR_TYPE_GRAY) | |
952 { | |
953 png_get_tRNS(png_ptr, info_ptr, &trans, &ntrans, NULL); | 944 png_get_tRNS(png_ptr, info_ptr, &trans, &ntrans, NULL); |
954 if (trans != NULL && ntrans > 0) | 945 if (trans != NULL && ntrans > 0) |
955 { | 946 { |
956 dmMsg(2, "PNG: %d transparent colors.\n", ntrans); | 947 dmMsg(2, "PNG: %d transparent colors.\n", ntrans); |
957 for (i = 0; i < img->ncolors && i < ntrans; i++) | 948 for (i = 0; i < img->ncolors && i < ntrans; i++) |
1129 // Always force planar for PCX | 1120 // Always force planar for PCX |
1130 memcpy(&spec, pspec, sizeof(DMImageConvSpec)); | 1121 memcpy(&spec, pspec, sizeof(DMImageConvSpec)); |
1131 spec.planar = TRUE; | 1122 spec.planar = TRUE; |
1132 | 1123 |
1133 // XXX: 24bit PCX does not work yet .. | 1124 // XXX: 24bit PCX does not work yet .. |
1134 if (spec.format != DM_COLFMT_PALETTE) | 1125 if (spec.format != DM_COLFMT_PALETTE && |
1126 spec.format != DM_COLFMT_GRAYSCALE) | |
1135 { | 1127 { |
1136 return dmError(DMERR_NOT_SUPPORTED, | 1128 return dmError(DMERR_NOT_SUPPORTED, |
1137 "24bit PCX not supported yet.\n"); | 1129 "24bit PCX not supported yet.\n"); |
1138 } | 1130 } |
1139 | 1131 |
1148 pcx.header = &hdr; | 1140 pcx.header = &hdr; |
1149 pcx.fp = fp; | 1141 pcx.fp = fp; |
1150 | 1142 |
1151 // Create PCX header | 1143 // Create PCX header |
1152 dmMemset(&hdr, 0, sizeof(hdr)); | 1144 dmMemset(&hdr, 0, sizeof(hdr)); |
1153 if (spec.format == DM_COLFMT_PALETTE) | 1145 if (spec.format == DM_COLFMT_PALETTE || |
1146 spec.format == DM_COLFMT_GRAYSCALE) | |
1154 { | 1147 { |
1155 const int ncolors = img->ncolors > DMPCX_PAL_COLORS ? DMPCX_PAL_COLORS : img->ncolors; | 1148 const int ncolors = img->ncolors > DMPCX_PAL_COLORS ? DMPCX_PAL_COLORS : img->ncolors; |
1156 for (int i = 0; i < ncolors; i++) | 1149 for (int i = 0; i < ncolors; i++) |
1157 { | 1150 { |
1158 hdr.colorMap[i].r = img->pal[i].r; | 1151 hdr.colorMap[i].r = img->pal[i].r; |
1248 | 1241 |
1249 // Write image data | 1242 // Write image data |
1250 res = dmWriteImageData(img, (void *) &pcx, dmWritePCXRow, &spec); | 1243 res = dmWriteImageData(img, (void *) &pcx, dmWritePCXRow, &spec); |
1251 | 1244 |
1252 // Write VGA palette | 1245 // Write VGA palette |
1253 if (spec.format == DM_COLFMT_PALETTE) | 1246 if (spec.format == DM_COLFMT_PALETTE || |
1247 spec.format == DM_COLFMT_GRAYSCALE) | |
1254 { | 1248 { |
1255 int i; | 1249 int i; |
1256 dmMsg(2, "PCX: Writing palette of %d active entries.\n", img->ncolors); | 1250 dmMsg(2, "PCX: Writing palette of %d active entries.\n", img->ncolors); |
1257 | 1251 |
1258 dmf_write_byte(pcx.fp, 0x0C); | 1252 dmf_write_byte(pcx.fp, 0x0C); |
1424 goto error; | 1418 goto error; |
1425 } | 1419 } |
1426 | 1420 |
1427 // Allocate image | 1421 // Allocate image |
1428 if ((*pimg = img = dmImageAlloc(hdr.xmax - hdr.xmin + 1, hdr.ymax - hdr.ymin + 1, | 1422 if ((*pimg = img = dmImageAlloc(hdr.xmax - hdr.xmin + 1, hdr.ymax - hdr.ymin + 1, |
1429 isPaletted ? DM_COLFMT_PALETTE : DM_COLFMT_RGBA, | 1423 isPaletted ? DM_COLFMT_PALETTE : DM_COLFMT_RGB, |
1430 // XXX TODO? When/if we ever handle < 8bit indexed correctly, we can use the actual bpp | 1424 // XXX TODO? When/if we ever handle < 8bit indexed correctly, we can use the actual bpp |
1431 // isPaletted ? (hdr.bitsPerPlane * hdr.nplanes) : -1 | 1425 // isPaletted ? (hdr.bitsPerPlane * hdr.nplanes) : -1 |
1432 -1 | 1426 -1 |
1433 )) == NULL) | 1427 )) == NULL) |
1434 { | 1428 { |