OLD | NEW |
1 | 1 |
2 /* pngwrite.c - general routines to write a PNG file | 2 /* pngwrite.c - general routines to write a PNG file |
3 * | 3 * |
4 * Last changed in libpng 1.2.52 [November 20, 2014] | 4 * Last changed in libpng 1.2.54 [November 12, 2015] |
5 * Copyright (c) 1998-2014 Glenn Randers-Pehrson | 5 * Copyright (c) 1998-2015 Glenn Randers-Pehrson |
6 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) | 6 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) |
7 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) | 7 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) |
8 * | 8 * |
9 * This code is released under the libpng license. | 9 * This code is released under the libpng license. |
10 * For conditions of distribution and use, see the disclaimer | 10 * For conditions of distribution and use, see the disclaimer |
11 * and license in png.h | 11 * and license in png.h |
12 */ | 12 */ |
13 | 13 |
14 /* Get internal access to png.h */ | 14 /* Get internal access to png.h */ |
15 #define PNG_INTERNAL | 15 #define PNG_INTERNAL |
(...skipping 561 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
577 } | 577 } |
578 | 578 |
579 /* Initialize zbuf - compression buffer */ | 579 /* Initialize zbuf - compression buffer */ |
580 png_ptr->zbuf_size = PNG_ZBUF_SIZE; | 580 png_ptr->zbuf_size = PNG_ZBUF_SIZE; |
581 png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, | 581 png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, |
582 (png_uint_32)png_ptr->zbuf_size); | 582 (png_uint_32)png_ptr->zbuf_size); |
583 | 583 |
584 png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL, | 584 png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL, |
585 png_flush_ptr_NULL); | 585 png_flush_ptr_NULL); |
586 | 586 |
587 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED | |
588 png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT, | |
589 1, png_doublep_NULL, png_doublep_NULL); | |
590 #endif | |
591 | |
592 #ifdef PNG_SETJMP_SUPPORTED | 587 #ifdef PNG_SETJMP_SUPPORTED |
593 /* Applications that neglect to set up their own setjmp() and then | 588 /* Applications that neglect to set up their own setjmp() and then |
594 * encounter a png_error() will longjmp here. Since the jmpbuf is | 589 * encounter a png_error() will longjmp here. Since the jmpbuf is |
595 * then meaningless we abort instead of returning. | 590 * then meaningless we abort instead of returning. |
596 */ | 591 */ |
597 #ifdef USE_FAR_KEYWORD | 592 #ifdef USE_FAR_KEYWORD |
598 if (setjmp(jmpbuf)) | 593 if (setjmp(jmpbuf)) |
599 PNG_ABORT(); | 594 PNG_ABORT(); |
600 png_memcpy(png_ptr->jmpbuf, jmpbuf, png_sizeof(jmp_buf)); | 595 png_memcpy(png_ptr->jmpbuf, jmpbuf, png_sizeof(jmp_buf)); |
601 #else | 596 #else |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
724 png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf)); | 719 png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf)); |
725 #endif | 720 #endif |
726 | 721 |
727 png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL, | 722 png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL, |
728 png_flush_ptr_NULL); | 723 png_flush_ptr_NULL); |
729 | 724 |
730 /* Initialize zbuf - compression buffer */ | 725 /* Initialize zbuf - compression buffer */ |
731 png_ptr->zbuf_size = PNG_ZBUF_SIZE; | 726 png_ptr->zbuf_size = PNG_ZBUF_SIZE; |
732 png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, | 727 png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, |
733 (png_uint_32)png_ptr->zbuf_size); | 728 (png_uint_32)png_ptr->zbuf_size); |
734 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED | |
735 png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT, | |
736 1, png_doublep_NULL, png_doublep_NULL); | |
737 #endif | |
738 } | 729 } |
739 | 730 |
740 /* Write a few rows of image data. If the image is interlaced, | 731 /* Write a few rows of image data. If the image is interlaced, |
741 * either you will have to write the 7 sub images, or, if you | 732 * either you will have to write the 7 sub images, or, if you |
742 * have called png_set_interlace_handling(), you will have to | 733 * have called png_set_interlace_handling(), you will have to |
743 * "write" the image seven times. | 734 * "write" the image seven times. |
744 */ | 735 */ |
745 void PNGAPI | 736 void PNGAPI |
746 png_write_rows(png_structp png_ptr, png_bytepp row, | 737 png_write_rows(png_structp png_ptr, png_bytepp row, |
747 png_uint_32 num_rows) | 738 png_uint_32 num_rows) |
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1143 png_free(png_ptr, png_ptr->sub_row); | 1134 png_free(png_ptr, png_ptr->sub_row); |
1144 png_free(png_ptr, png_ptr->up_row); | 1135 png_free(png_ptr, png_ptr->up_row); |
1145 png_free(png_ptr, png_ptr->avg_row); | 1136 png_free(png_ptr, png_ptr->avg_row); |
1146 png_free(png_ptr, png_ptr->paeth_row); | 1137 png_free(png_ptr, png_ptr->paeth_row); |
1147 #endif | 1138 #endif |
1148 | 1139 |
1149 #ifdef PNG_TIME_RFC1123_SUPPORTED | 1140 #ifdef PNG_TIME_RFC1123_SUPPORTED |
1150 png_free(png_ptr, png_ptr->time_buffer); | 1141 png_free(png_ptr, png_ptr->time_buffer); |
1151 #endif | 1142 #endif |
1152 | 1143 |
1153 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED | |
1154 png_free(png_ptr, png_ptr->prev_filters); | |
1155 png_free(png_ptr, png_ptr->filter_weights); | |
1156 png_free(png_ptr, png_ptr->inv_filter_weights); | |
1157 png_free(png_ptr, png_ptr->filter_costs); | |
1158 png_free(png_ptr, png_ptr->inv_filter_costs); | |
1159 #endif | |
1160 | |
1161 #ifdef PNG_SETJMP_SUPPORTED | 1144 #ifdef PNG_SETJMP_SUPPORTED |
1162 /* Reset structure */ | 1145 /* Reset structure */ |
1163 png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf)); | 1146 png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf)); |
1164 #endif | 1147 #endif |
1165 | 1148 |
1166 error_fn = png_ptr->error_fn; | 1149 error_fn = png_ptr->error_fn; |
1167 warning_fn = png_ptr->warning_fn; | 1150 warning_fn = png_ptr->warning_fn; |
1168 error_ptr = png_ptr->error_ptr; | 1151 error_ptr = png_ptr->error_ptr; |
1169 #ifdef PNG_USER_MEM_SUPPORTED | 1152 #ifdef PNG_USER_MEM_SUPPORTED |
1170 free_fn = png_ptr->free_fn; | 1153 free_fn = png_ptr->free_fn; |
(...skipping 23 matching lines...) Expand all Loading... |
1194 return; | 1177 return; |
1195 #ifdef PNG_MNG_FEATURES_SUPPORTED | 1178 #ifdef PNG_MNG_FEATURES_SUPPORTED |
1196 if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && | 1179 if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && |
1197 (method == PNG_INTRAPIXEL_DIFFERENCING)) | 1180 (method == PNG_INTRAPIXEL_DIFFERENCING)) |
1198 method = PNG_FILTER_TYPE_BASE; | 1181 method = PNG_FILTER_TYPE_BASE; |
1199 #endif | 1182 #endif |
1200 if (method == PNG_FILTER_TYPE_BASE) | 1183 if (method == PNG_FILTER_TYPE_BASE) |
1201 { | 1184 { |
1202 switch (filters & (PNG_ALL_FILTERS | 0x07)) | 1185 switch (filters & (PNG_ALL_FILTERS | 0x07)) |
1203 { | 1186 { |
| 1187 case PNG_FILTER_VALUE_NONE: |
| 1188 png_ptr->do_filter = PNG_FILTER_NONE; break; |
1204 #ifdef PNG_WRITE_FILTER_SUPPORTED | 1189 #ifdef PNG_WRITE_FILTER_SUPPORTED |
1205 case 5: | 1190 case 5: |
1206 case 6: | 1191 case 6: |
1207 case 7: png_warning(png_ptr, "Unknown row filter for method 0"); | 1192 case 7: png_warning(png_ptr, "Unknown row filter for method 0"); |
1208 #endif /* PNG_WRITE_FILTER_SUPPORTED */ | 1193 break; |
1209 case PNG_FILTER_VALUE_NONE: | |
1210 png_ptr->do_filter = PNG_FILTER_NONE; break; | |
1211 #ifdef PNG_WRITE_FILTER_SUPPORTED | |
1212 case PNG_FILTER_VALUE_SUB: | 1194 case PNG_FILTER_VALUE_SUB: |
1213 png_ptr->do_filter = PNG_FILTER_SUB; break; | 1195 png_ptr->do_filter = PNG_FILTER_SUB; break; |
1214 case PNG_FILTER_VALUE_UP: | 1196 case PNG_FILTER_VALUE_UP: |
1215 png_ptr->do_filter = PNG_FILTER_UP; break; | 1197 png_ptr->do_filter = PNG_FILTER_UP; break; |
1216 case PNG_FILTER_VALUE_AVG: | 1198 case PNG_FILTER_VALUE_AVG: |
1217 png_ptr->do_filter = PNG_FILTER_AVG; break; | 1199 png_ptr->do_filter = PNG_FILTER_AVG; break; |
1218 case PNG_FILTER_VALUE_PAETH: | 1200 case PNG_FILTER_VALUE_PAETH: |
1219 png_ptr->do_filter = PNG_FILTER_PAETH; break; | 1201 png_ptr->do_filter = PNG_FILTER_PAETH; break; |
1220 default: png_ptr->do_filter = (png_byte)filters; break; | 1202 default: png_ptr->do_filter = (png_byte)filters; break; |
1221 #else | 1203 #else |
1222 default: png_warning(png_ptr, "Unknown row filter for method 0"); | 1204 default: png_warning(png_ptr, "Unknown row filter for method 0"); |
| 1205 break; |
1223 #endif /* PNG_WRITE_FILTER_SUPPORTED */ | 1206 #endif /* PNG_WRITE_FILTER_SUPPORTED */ |
1224 } | 1207 } |
1225 | 1208 |
1226 /* If we have allocated the row_buf, this means we have already started | 1209 /* If we have allocated the row_buf, this means we have already started |
1227 * with the image and we should have allocated all of the filter buffers | 1210 * with the image and we should have allocated all of the filter buffers |
1228 * that have been selected. If prev_row isn't already allocated, then | 1211 * that have been selected. If prev_row isn't already allocated, then |
1229 * it is too late to start using the filters that need it, since we | 1212 * it is too late to start using the filters that need it, since we |
1230 * will be missing the data in the previous row. If an application | 1213 * will be missing the data in the previous row. If an application |
1231 * wants to start and stop using particular filters during compression, | 1214 * wants to start and stop using particular filters during compression, |
1232 * it should start out with all of the filters, and then add and | 1215 * it should start out with all of the filters, and then add and |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1303 * question as to whether it can be improved upon by trying to keep the | 1286 * question as to whether it can be improved upon by trying to keep the |
1304 * filtered data going to zlib more consistent, hopefully resulting in | 1287 * filtered data going to zlib more consistent, hopefully resulting in |
1305 * better compression. | 1288 * better compression. |
1306 */ | 1289 */ |
1307 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* GRR 970116 */ | 1290 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* GRR 970116 */ |
1308 void PNGAPI | 1291 void PNGAPI |
1309 png_set_filter_heuristics(png_structp png_ptr, int heuristic_method, | 1292 png_set_filter_heuristics(png_structp png_ptr, int heuristic_method, |
1310 int num_weights, png_doublep filter_weights, | 1293 int num_weights, png_doublep filter_weights, |
1311 png_doublep filter_costs) | 1294 png_doublep filter_costs) |
1312 { | 1295 { |
1313 int i; | 1296 PNG_UNUSED(png_ptr) |
1314 | 1297 PNG_UNUSED(heuristic_method) |
1315 png_debug(1, "in png_set_filter_heuristics"); | 1298 PNG_UNUSED(num_weights) |
1316 | 1299 PNG_UNUSED(filter_weights) |
1317 if (png_ptr == NULL) | 1300 PNG_UNUSED(filter_costs) |
1318 return; | |
1319 if (heuristic_method >= PNG_FILTER_HEURISTIC_LAST) | |
1320 { | |
1321 png_warning(png_ptr, "Unknown filter heuristic method"); | |
1322 return; | |
1323 } | |
1324 | |
1325 if (heuristic_method == PNG_FILTER_HEURISTIC_DEFAULT) | |
1326 { | |
1327 heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED; | |
1328 } | |
1329 | |
1330 if (num_weights < 0 || filter_weights == NULL || | |
1331 heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED) | |
1332 { | |
1333 num_weights = 0; | |
1334 } | |
1335 | |
1336 png_ptr->num_prev_filters = (png_byte)num_weights; | |
1337 png_ptr->heuristic_method = (png_byte)heuristic_method; | |
1338 | |
1339 if (num_weights > 0) | |
1340 { | |
1341 if (png_ptr->prev_filters == NULL) | |
1342 { | |
1343 png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr, | |
1344 (png_uint_32)(png_sizeof(png_byte) * num_weights)); | |
1345 | |
1346 /* To make sure that the weighting starts out fairly */ | |
1347 for (i = 0; i < num_weights; i++) | |
1348 { | |
1349 png_ptr->prev_filters[i] = 255; | |
1350 } | |
1351 } | |
1352 | |
1353 if (png_ptr->filter_weights == NULL) | |
1354 { | |
1355 png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr, | |
1356 (png_uint_32)(png_sizeof(png_uint_16) * num_weights)); | |
1357 | |
1358 png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr, | |
1359 (png_uint_32)(png_sizeof(png_uint_16) * num_weights)); | |
1360 for (i = 0; i < num_weights; i++) | |
1361 { | |
1362 png_ptr->inv_filter_weights[i] = | |
1363 png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; | |
1364 } | |
1365 } | |
1366 | |
1367 for (i = 0; i < num_weights; i++) | |
1368 { | |
1369 if (filter_weights[i] < 0.0) | |
1370 { | |
1371 png_ptr->inv_filter_weights[i] = | |
1372 png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; | |
1373 } | |
1374 else | |
1375 { | |
1376 png_ptr->inv_filter_weights[i] = | |
1377 (png_uint_16)((double)PNG_WEIGHT_FACTOR*filter_weights[i]+0.5); | |
1378 png_ptr->filter_weights[i] = | |
1379 (png_uint_16)((double)PNG_WEIGHT_FACTOR/filter_weights[i]+0.5); | |
1380 } | |
1381 } | |
1382 } | |
1383 | |
1384 /* If, in the future, there are other filter methods, this would | |
1385 * need to be based on png_ptr->filter. | |
1386 */ | |
1387 if (png_ptr->filter_costs == NULL) | |
1388 { | |
1389 png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr, | |
1390 (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); | |
1391 | |
1392 png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr, | |
1393 (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); | |
1394 | |
1395 for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) | |
1396 { | |
1397 png_ptr->inv_filter_costs[i] = | |
1398 png_ptr->filter_costs[i] = PNG_COST_FACTOR; | |
1399 } | |
1400 } | |
1401 | |
1402 /* Here is where we set the relative costs of the different filters. We | |
1403 * should take the desired compression level into account when setting | |
1404 * the costs, so that Paeth, for instance, has a high relative cost at low | |
1405 * compression levels, while it has a lower relative cost at higher | |
1406 * compression settings. The filter types are in order of increasing | |
1407 * relative cost, so it would be possible to do this with an algorithm. | |
1408 */ | |
1409 for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) | |
1410 { | |
1411 if (filter_costs == NULL || filter_costs[i] < 0.0) | |
1412 { | |
1413 png_ptr->inv_filter_costs[i] = | |
1414 png_ptr->filter_costs[i] = PNG_COST_FACTOR; | |
1415 } | |
1416 else if (filter_costs[i] >= 1.0) | |
1417 { | |
1418 png_ptr->inv_filter_costs[i] = | |
1419 (png_uint_16)((double)PNG_COST_FACTOR / filter_costs[i] + 0.5); | |
1420 png_ptr->filter_costs[i] = | |
1421 (png_uint_16)((double)PNG_COST_FACTOR * filter_costs[i] + 0.5); | |
1422 } | |
1423 } | |
1424 } | 1301 } |
1425 #endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ | 1302 #endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ |
1426 | 1303 |
1427 void PNGAPI | 1304 void PNGAPI |
1428 png_set_compression_level(png_structp png_ptr, int level) | 1305 png_set_compression_level(png_structp png_ptr, int level) |
1429 { | 1306 { |
1430 png_debug(1, "in png_set_compression_level"); | 1307 png_debug(1, "in png_set_compression_level"); |
1431 | 1308 |
1432 if (png_ptr == NULL) | 1309 if (png_ptr == NULL) |
1433 return; | 1310 return; |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1593 png_write_image(png_ptr, info_ptr->row_pointers); | 1470 png_write_image(png_ptr, info_ptr->row_pointers); |
1594 | 1471 |
1595 /* It is REQUIRED to call this to finish writing the rest of the file */ | 1472 /* It is REQUIRED to call this to finish writing the rest of the file */ |
1596 png_write_end(png_ptr, info_ptr); | 1473 png_write_end(png_ptr, info_ptr); |
1597 | 1474 |
1598 PNG_UNUSED(transforms) /* Quiet compiler warnings */ | 1475 PNG_UNUSED(transforms) /* Quiet compiler warnings */ |
1599 PNG_UNUSED(params) | 1476 PNG_UNUSED(params) |
1600 } | 1477 } |
1601 #endif | 1478 #endif |
1602 #endif /* PNG_WRITE_SUPPORTED */ | 1479 #endif /* PNG_WRITE_SUPPORTED */ |
OLD | NEW |