From 5b264b0b58056d5d4bce8a6e4824c54adecba10f Mon Sep 17 00:00:00 2001 From: Dmitry Baryshev Date: Tue, 14 Nov 2023 13:27:01 +0300 Subject: [PATCH 01/23] PNM: PNM codec skeleton --- src/sail-codecs/CMakeLists.txt | 2 +- src/sail-codecs/pnm/CMakeLists.txt | 3 + src/sail-codecs/pnm/helpers.c | 66 +++++++ src/sail-codecs/pnm/helpers.h | 48 ++++++ src/sail-codecs/pnm/pnm.c | 236 ++++++++++++++++++++++++++ src/sail-codecs/pnm/pnm.codec.info.in | 26 +++ src/sail-codecs/pnm/pnm.png | Bin 0 -> 314 bytes 7 files changed, 380 insertions(+), 1 deletion(-) create mode 100644 src/sail-codecs/pnm/CMakeLists.txt create mode 100644 src/sail-codecs/pnm/helpers.c create mode 100644 src/sail-codecs/pnm/helpers.h create mode 100644 src/sail-codecs/pnm/pnm.c create mode 100644 src/sail-codecs/pnm/pnm.codec.info.in create mode 100644 src/sail-codecs/pnm/pnm.png diff --git a/src/sail-codecs/CMakeLists.txt b/src/sail-codecs/CMakeLists.txt index 2996212c..457f3a69 100644 --- a/src/sail-codecs/CMakeLists.txt +++ b/src/sail-codecs/CMakeLists.txt @@ -7,7 +7,7 @@ add_subdirectory(common/bmp) set(HIGHEST_PRIORITY_CODECS gif jpeg png tiff) set(HIGH_PRIORITY_CODECS bmp svg) set(MEDIUM_PRIORITY_CODECS avif jpeg2000 jpegxl webp) -set(LOW_PRIORITY_CODECS ico pcx psd qoi tga) +set(LOW_PRIORITY_CODECS ico pcx pnm psd qoi tga) set(LOWEST_PRIORITY_CODECS wal xbm) set(CODECS ${HIGHEST_PRIORITY_CODECS} diff --git a/src/sail-codecs/pnm/CMakeLists.txt b/src/sail-codecs/pnm/CMakeLists.txt new file mode 100644 index 00000000..632a0f97 --- /dev/null +++ b/src/sail-codecs/pnm/CMakeLists.txt @@ -0,0 +1,3 @@ +# Common codec configuration +# +sail_codec(NAME pnm SOURCES helpers.h helpers.c pnm.c ICON pnm.png) diff --git a/src/sail-codecs/pnm/helpers.c b/src/sail-codecs/pnm/helpers.c new file mode 100644 index 00000000..208c2d03 --- /dev/null +++ b/src/sail-codecs/pnm/helpers.c @@ -0,0 +1,66 @@ +/* This file is part of SAIL (https://github.com/HappySeaFox/sail) + + Copyright (c) 2023 Dmitry Baryshev + + The MIT License + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +#include + +#include "helpers.h" + +sail_status_t pnm_private_skip_to_data(struct sail_io *io, char *first_char) { + + char c; + + do { + SAIL_TRY(io->strict_read(io->stream, &c, 1)); + + if (c == '#') { + do { + SAIL_TRY(io->strict_read(io->stream, &c, 1)); + } while(c != '\n'); + } + } while(c < '0' || c > '9'); + + *first_char = c; + + return SAIL_OK; +} + +enum SailPixelFormat pnm_private_rgb_sail_pixel_format(enum SailPnmVersion pnm_version) { + + switch (pnm_version) { + case SAIL_PNM_VERSION_P1: + case SAIL_PNM_VERSION_P4: return SAIL_PIXEL_FORMAT_BPP1_INDEXED; + + case SAIL_PNM_VERSION_P2: + case SAIL_PNM_VERSION_P5: return SAIL_PIXEL_FORMAT_BPP8_GRAYSCALE; + + case SAIL_PNM_VERSION_P3: + case SAIL_PNM_VERSION_P6: return SAIL_PIXEL_FORMAT_BPP24_RGB; + + default: { + return SAIL_PIXEL_FORMAT_UNKNOWN; + } + } +} + diff --git a/src/sail-codecs/pnm/helpers.h b/src/sail-codecs/pnm/helpers.h new file mode 100644 index 00000000..086e8c67 --- /dev/null +++ b/src/sail-codecs/pnm/helpers.h @@ -0,0 +1,48 @@ +/* This file is part of SAIL (https://github.com/HappySeaFox/sail) + + Copyright (c) 2023 Dmitry Baryshev + + The MIT License + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +#ifndef SAIL_PNM_HELPERS_H +#define SAIL_PNM_HELPERS_H + +#include +#include +#include + +struct sail_io; + +enum SailPnmVersion { + SAIL_PNM_VERSION_P1, + SAIL_PNM_VERSION_P2, + SAIL_PNM_VERSION_P3, + SAIL_PNM_VERSION_P4, + SAIL_PNM_VERSION_P5, + SAIL_PNM_VERSION_P6, +}; + +SAIL_HIDDEN sail_status_t pnm_private_skip_to_data(struct sail_io *io, char *first_char); + +SAIL_HIDDEN enum SailPixelFormat pnm_private_rgb_sail_pixel_format(enum SailPnmVersion pnm_version); + +#endif diff --git a/src/sail-codecs/pnm/pnm.c b/src/sail-codecs/pnm/pnm.c new file mode 100644 index 00000000..15382b23 --- /dev/null +++ b/src/sail-codecs/pnm/pnm.c @@ -0,0 +1,236 @@ +/* This file is part of SAIL (https://github.com/HappySeaFox/sail) + + Copyright (c) 2023 Dmitry Baryshev + + The MIT License + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +#include +#include +#include +#include + +#include + +#include "helpers.h" + +/* + * Codec-specific state. + */ +struct pnm_state { + struct sail_io *io; + const struct sail_load_options *load_options; + const struct sail_save_options *save_options; + + bool frame_loaded; + enum SailPnmVersion version; +}; + +static sail_status_t alloc_pnm_state(struct sail_io *io, + const struct sail_load_options *load_options, + const struct sail_save_options *save_options, + struct pnm_state **pnm_state) { + + void *ptr; + SAIL_TRY(sail_malloc(sizeof(struct pnm_state), &ptr)); + *pnm_state = ptr; + + **pnm_state = (struct pnm_state) { + .io = io, + .load_options = load_options, + .save_options = save_options, + + .frame_loaded = false, + }; + + return SAIL_OK; +} + +static void destroy_pnm_state(struct pnm_state *pnm_state) { + + if (pnm_state == NULL) { + return; + } + + sail_free(pnm_state); +} + +/* + * Decoding functions. + */ + +SAIL_EXPORT sail_status_t sail_codec_load_init_v8_pnm(struct sail_io *io, const struct sail_load_options *load_options, void **state) { + + *state = NULL; + + /* Allocate a new state. */ + struct pnm_state *pnm_state; + SAIL_TRY(alloc_pnm_state(io, load_options, NULL, &pnm_state)); + *state = pnm_state; + + /* Init decoder. */ + char str[8]; + SAIL_TRY(sail_read_string_from_io(pnm_state->io, str, sizeof(str))); + + const char pnm = str[1]; + + SAIL_LOG_TRACE("PNM: Version '%c'", pnm); + + switch (pnm) { + case '1': pnm_state->version = SAIL_PNM_VERSION_P1; break; + case '2': pnm_state->version = SAIL_PNM_VERSION_P2; break; + case '3': pnm_state->version = SAIL_PNM_VERSION_P3; break; + case '4': pnm_state->version = SAIL_PNM_VERSION_P4; break; + case '5': pnm_state->version = SAIL_PNM_VERSION_P5; break; + case '6': pnm_state->version = SAIL_PNM_VERSION_P6; break; + + default: { + SAIL_LOG_ERROR("PNM: Unsupported version '%c'", pnm); + SAIL_LOG_AND_RETURN(SAIL_ERROR_UNSUPPORTED_FORMAT); + } + } + + return SAIL_OK; +} + +SAIL_EXPORT sail_status_t sail_codec_load_seek_next_frame_v8_pnm(void *state, struct sail_image **image) { + + struct pnm_state *pnm_state = state; + + if (pnm_state->frame_loaded) { + SAIL_LOG_AND_RETURN(SAIL_ERROR_NO_MORE_FRAMES); + } + + pnm_state->frame_loaded = true; + + char first_char; + SAIL_TRY(pnm_private_skip_to_data(pnm_state->io, &first_char)); + + char width_height_str[32] = { first_char }; + SAIL_TRY(sail_read_string_from_io(pnm_state->io, width_height_str + 1, sizeof(width_height_str) - 1)); + + unsigned w, h; +#ifdef _MSC_VER + if (sscanf_s(width_height_str, "%u%u", &w, &h) != 2) { +#else + if (sscanf(width_height_str, "%u%u", &w, &h) != 2) { +#endif + SAIL_LOG_ERROR("PNM: Failed to read image dimensions"); + SAIL_LOG_AND_RETURN(SAIL_ERROR_BROKEN_IMAGE); + } + + enum SailPixelFormat pixel_format = pnm_private_rgb_sail_pixel_format(pnm_state->version); + + if (pixel_format == SAIL_PIXEL_FORMAT_UNKNOWN) { + SAIL_LOG_ERROR("PNM: Unsupported pixel format"); + SAIL_LOG_AND_RETURN(SAIL_ERROR_UNSUPPORTED_PIXEL_FORMAT); + } + + struct sail_image *image_local; + SAIL_TRY(sail_alloc_image(&image_local)); + + if (pnm_state->load_options->options & SAIL_OPTION_SOURCE_IMAGE) { + SAIL_TRY_OR_CLEANUP(sail_alloc_source_image(&image_local->source_image), + /* cleanup */ sail_destroy_image(image_local)); + + image_local->source_image->pixel_format = pixel_format; + image_local->source_image->compression = SAIL_COMPRESSION_NONE; + } + + image_local->width = w; + image_local->height = h; + image_local->pixel_format = pixel_format; + image_local->delay = -1; + image_local->bytes_per_line = sail_bytes_per_line(image_local->width, image_local->pixel_format); + + if (pixel_format == SAIL_PIXEL_FORMAT_BPP1_INDEXED) { + SAIL_TRY_OR_CLEANUP(sail_alloc_palette_for_data(SAIL_PIXEL_FORMAT_BPP24_RGB, 2, &image_local->palette), + /* cleanup */ sail_destroy_image(image_local)); + + unsigned char *palette_data = image_local->palette->data; + + *palette_data++ = 255; + *palette_data++ = 255; + *palette_data++ = 255; + + *palette_data++ = 0; + *palette_data++ = 0; + *palette_data++ = 0; + } + + *image = image_local; + + return SAIL_OK; +} + +SAIL_EXPORT sail_status_t sail_codec_load_frame_v8_pnm(void *state, struct sail_image *image) { + + const struct pnm_state *pnm_state = state; + + return SAIL_OK; +} + +SAIL_EXPORT sail_status_t sail_codec_load_finish_v8_pnm(void **state) { + + struct pnm_state *pnm_state = *state; + + *state = NULL; + + destroy_pnm_state(pnm_state); + + return SAIL_OK; +} + +/* + * Encoding functions. + */ + +SAIL_EXPORT sail_status_t sail_codec_save_init_v8_pnm(struct sail_io *io, const struct sail_save_options *save_options, void **state) { + + (void)io; + (void)save_options; + (void)state; + + SAIL_LOG_AND_RETURN(SAIL_ERROR_NOT_IMPLEMENTED); +} + +SAIL_EXPORT sail_status_t sail_codec_save_seek_next_frame_v8_pnm(void *state, const struct sail_image *image) { + + (void)state; + (void)image; + + SAIL_LOG_AND_RETURN(SAIL_ERROR_NOT_IMPLEMENTED); +} + +SAIL_EXPORT sail_status_t sail_codec_save_frame_v8_pnm(void *state, const struct sail_image *image) { + + (void)state; + (void)image; + + SAIL_LOG_AND_RETURN(SAIL_ERROR_NOT_IMPLEMENTED); +} + +SAIL_EXPORT sail_status_t sail_codec_save_finish_v8_pnm(void **state) { + + (void)state; + + SAIL_LOG_AND_RETURN(SAIL_ERROR_NOT_IMPLEMENTED); +} diff --git a/src/sail-codecs/pnm/pnm.codec.info.in b/src/sail-codecs/pnm/pnm.codec.info.in new file mode 100644 index 00000000..6e4e991a --- /dev/null +++ b/src/sail-codecs/pnm/pnm.codec.info.in @@ -0,0 +1,26 @@ +# PNM codec information +# +[codec] +layout=8 +version=0.6.5 +priority=LOW +name=PNM +description=Portable aNy Map +magic-numbers=50 31;50 32;50 33;50 34;50 35;50 36 +extensions=pbm;pgm;ppm;pnm +mime-types=image/x-portable-bitmap;image/x-portable-graymap;image/x-portable-pixmap;image/x-portable-anymap + +[load-features] +features=STATIC;SOURCE-IMAGE +tuning= + +[save-features] +features= +pixel-formats= +compressions= +default-compression= +compression-level-min=0 +compression-level-max=0 +compression-level-default=0 +compression-level-step=0 +tuning= diff --git a/src/sail-codecs/pnm/pnm.png b/src/sail-codecs/pnm/pnm.png new file mode 100644 index 0000000000000000000000000000000000000000..0f448d2ae0d1e0c752f9134c9d4cd8315bec7cff GIT binary patch literal 314 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Ea{HEjtmSN`?>!lvI6;>1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP_Hy@V>PnGCRkRc~MT^vI!PA{Eo$k%Kjz;gVAtnGe> zDSs5MiaNNTH-53>yTFowr|dQzO{X-4gxW0xm9*!U-21%l+NNBWBO950F9(RU-uxuC zAouqCq)=7g;9vX7LqlisGdI|rZ+?_Hi@{@3i_U3@wu3)Cb*uxgmrl5!`anJ~^nRL~ z%biU+GOesTj(t@8m^rVL!D4>=R;4TKJ6?EBdAfJs%pY@(-|jz~dUE#5YbkTn>Ahs?720@fA9EF0z=%wY%Ma&hbVC=qUzIS3j3^ HP6kfPK literal 0 HcmV?d00001 From 265d5b9e7741ba322a495f2e1f7a9542822ed243 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshev Date: Tue, 14 Nov 2023 19:08:46 +0300 Subject: [PATCH 02/23] PNM: Read P4, P5, P6 --- src/sail-codecs/pnm/helpers.c | 20 ++++++++-- src/sail-codecs/pnm/helpers.h | 2 +- src/sail-codecs/pnm/pnm.c | 72 ++++++++++++++++++++++++++++++++--- 3 files changed, 85 insertions(+), 9 deletions(-) diff --git a/src/sail-codecs/pnm/helpers.c b/src/sail-codecs/pnm/helpers.c index 208c2d03..b508f40e 100644 --- a/src/sail-codecs/pnm/helpers.c +++ b/src/sail-codecs/pnm/helpers.c @@ -46,17 +46,31 @@ sail_status_t pnm_private_skip_to_data(struct sail_io *io, char *first_char) { return SAIL_OK; } -enum SailPixelFormat pnm_private_rgb_sail_pixel_format(enum SailPnmVersion pnm_version) { +enum SailPixelFormat pnm_private_rgb_sail_pixel_format(enum SailPnmVersion pnm_version, unsigned bpp) { switch (pnm_version) { case SAIL_PNM_VERSION_P1: case SAIL_PNM_VERSION_P4: return SAIL_PIXEL_FORMAT_BPP1_INDEXED; case SAIL_PNM_VERSION_P2: - case SAIL_PNM_VERSION_P5: return SAIL_PIXEL_FORMAT_BPP8_GRAYSCALE; + case SAIL_PNM_VERSION_P5: { + switch (bpp) { + case 8: return SAIL_PIXEL_FORMAT_BPP8_GRAYSCALE; + case 16: return SAIL_PIXEL_FORMAT_BPP16_GRAYSCALE; + + default: return SAIL_PIXEL_FORMAT_UNKNOWN; + } + } case SAIL_PNM_VERSION_P3: - case SAIL_PNM_VERSION_P6: return SAIL_PIXEL_FORMAT_BPP24_RGB; + case SAIL_PNM_VERSION_P6: { + switch (bpp) { + case 8: return SAIL_PIXEL_FORMAT_BPP24_RGB; + case 16: return SAIL_PIXEL_FORMAT_BPP48_RGB; + + default: return SAIL_PIXEL_FORMAT_UNKNOWN; + } + } default: { return SAIL_PIXEL_FORMAT_UNKNOWN; diff --git a/src/sail-codecs/pnm/helpers.h b/src/sail-codecs/pnm/helpers.h index 086e8c67..a17afe3f 100644 --- a/src/sail-codecs/pnm/helpers.h +++ b/src/sail-codecs/pnm/helpers.h @@ -43,6 +43,6 @@ enum SailPnmVersion { SAIL_HIDDEN sail_status_t pnm_private_skip_to_data(struct sail_io *io, char *first_char); -SAIL_HIDDEN enum SailPixelFormat pnm_private_rgb_sail_pixel_format(enum SailPnmVersion pnm_version); +SAIL_HIDDEN enum SailPixelFormat pnm_private_rgb_sail_pixel_format(enum SailPnmVersion pnm_version, unsigned bpp); #endif diff --git a/src/sail-codecs/pnm/pnm.c b/src/sail-codecs/pnm/pnm.c index 15382b23..bdb2519e 100644 --- a/src/sail-codecs/pnm/pnm.c +++ b/src/sail-codecs/pnm/pnm.c @@ -42,6 +42,7 @@ struct pnm_state { bool frame_loaded; enum SailPnmVersion version; + double multiplier_to_full_range; }; static sail_status_t alloc_pnm_state(struct sail_io *io, @@ -59,6 +60,7 @@ static sail_status_t alloc_pnm_state(struct sail_io *io, .save_options = save_options, .frame_loaded = false, + .multiplier_to_full_range = 0, }; return SAIL_OK; @@ -124,20 +126,60 @@ SAIL_EXPORT sail_status_t sail_codec_load_seek_next_frame_v8_pnm(void *state, st char first_char; SAIL_TRY(pnm_private_skip_to_data(pnm_state->io, &first_char)); - char width_height_str[32] = { first_char }; - SAIL_TRY(sail_read_string_from_io(pnm_state->io, width_height_str + 1, sizeof(width_height_str) - 1)); + char str[32] = { first_char }; + SAIL_TRY(sail_read_string_from_io(pnm_state->io, str + 1, sizeof(str) - 1)); + /* Dimensions. */ unsigned w, h; #ifdef _MSC_VER - if (sscanf_s(width_height_str, "%u%u", &w, &h) != 2) { + if (sscanf_s(str, "%u%u", &w, &h) != 2) { #else - if (sscanf(width_height_str, "%u%u", &w, &h) != 2) { + if (sscanf(str, "%u%u", &w, &h) != 2) { #endif SAIL_LOG_ERROR("PNM: Failed to read image dimensions"); SAIL_LOG_AND_RETURN(SAIL_ERROR_BROKEN_IMAGE); } - enum SailPixelFormat pixel_format = pnm_private_rgb_sail_pixel_format(pnm_state->version); + unsigned bpp; + + /* Maximum color. */ + if (pnm_state->version == SAIL_PNM_VERSION_P2 || + pnm_state->version == SAIL_PNM_VERSION_P3 || + pnm_state->version == SAIL_PNM_VERSION_P5 || + pnm_state->version == SAIL_PNM_VERSION_P6) { + SAIL_TRY(pnm_private_skip_to_data(pnm_state->io, &first_char)); + + str[0] = first_char; + SAIL_TRY(sail_read_string_from_io(pnm_state->io, str + 1, sizeof(str) - 1)); + + unsigned max_color; +#ifdef _MSC_VER + if (sscanf_s(str, "%u", &max_color) != 1) { +#else + if (sscanf(str, "%u", &max_color) != 1) { +#endif + SAIL_LOG_ERROR("PNM: Failed to read maximum color value"); + SAIL_LOG_AND_RETURN(SAIL_ERROR_BROKEN_IMAGE); + } + + if (max_color <= 255) { + bpp = 8; + pnm_state->multiplier_to_full_range = 255.0 / max_color; + } else if (max_color <= 65535) { + bpp = 16; + pnm_state->multiplier_to_full_range = 65535.0 / max_color; + } else { + SAIL_LOG_ERROR("PNM: BPP more than 16 is not supported"); + SAIL_LOG_AND_RETURN(SAIL_ERROR_UNSUPPORTED_FORMAT); + } + + SAIL_LOG_TRACE("PNM: Max color(%u), scale(%.1f)", max_color, pnm_state->multiplier_to_full_range); + } else { + pnm_state->multiplier_to_full_range = 1; + bpp = 1; + } + + enum SailPixelFormat pixel_format = pnm_private_rgb_sail_pixel_format(pnm_state->version, bpp); if (pixel_format == SAIL_PIXEL_FORMAT_UNKNOWN) { SAIL_LOG_ERROR("PNM: Unsupported pixel format"); @@ -185,6 +227,26 @@ SAIL_EXPORT sail_status_t sail_codec_load_frame_v8_pnm(void *state, struct sail_ const struct pnm_state *pnm_state = state; + switch (pnm_state->version) { + case SAIL_PNM_VERSION_P1: { + break; + } + case SAIL_PNM_VERSION_P2: { + break; + } + case SAIL_PNM_VERSION_P3: { + break; + } + case SAIL_PNM_VERSION_P4: + case SAIL_PNM_VERSION_P5: + case SAIL_PNM_VERSION_P6: { + for (unsigned row = 0; row < image->height; row++) { + SAIL_TRY(pnm_state->io->strict_read(pnm_state->io->stream, sail_scan_line(image, row), image->bytes_per_line)); + } + break; + } + } + return SAIL_OK; } From acfd17249b562acb409d22e0db30c3516dae09a7 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshev Date: Wed, 15 Nov 2023 16:24:15 +0300 Subject: [PATCH 03/23] LIBSAIL: Clarify more on io_file API --- src/sail/io_file.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sail/io_file.h b/src/sail/io_file.h index 9d6b757a..cfb221c2 100644 --- a/src/sail/io_file.h +++ b/src/sail/io_file.h @@ -37,7 +37,7 @@ struct sail_io; /* * Opens the specified image file for reading and allocates a new I/O object for it. - * sail_io.stream is a pointer to a FILE. + * sail_io.stream is a pointer to a FILE. fread/fwrite/fseek/feof are used underneath. * * Returns SAIL_OK on success. */ From a5dc6a8d6be972bfd63edce81779fc3b476ef9a1 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshev Date: Wed, 15 Nov 2023 16:41:14 +0300 Subject: [PATCH 04/23] PNM: WIP in reading ASCII files --- src/sail-codecs/pnm/helpers.c | 51 ++++++++++++++++++++- src/sail-codecs/pnm/helpers.h | 8 +++- src/sail-codecs/pnm/pnm.c | 84 +++++++++++++++++++++++++++++------ 3 files changed, 126 insertions(+), 17 deletions(-) diff --git a/src/sail-codecs/pnm/helpers.c b/src/sail-codecs/pnm/helpers.c index b508f40e..c03e4fda 100644 --- a/src/sail-codecs/pnm/helpers.c +++ b/src/sail-codecs/pnm/helpers.c @@ -23,11 +23,19 @@ SOFTWARE. */ +#include +#include + #include #include "helpers.h" -sail_status_t pnm_private_skip_to_data(struct sail_io *io, char *first_char) { +sail_status_t pnm_private_skip_to_letters_numbers(struct sail_io *io, char starting_char, char *first_char) { + + if (isalnum(starting_char)) { + *first_char = starting_char; + return SAIL_OK; + } char c; @@ -39,13 +47,52 @@ sail_status_t pnm_private_skip_to_data(struct sail_io *io, char *first_char) { SAIL_TRY(io->strict_read(io->stream, &c, 1)); } while(c != '\n'); } - } while(c < '0' || c > '9'); + } while (!isalnum(c)); *first_char = c; return SAIL_OK; } +sail_status_t pnm_private_read_word(struct sail_io *io, char *str, size_t str_size) { + + if (str_size < 2) { + SAIL_LOG_AND_RETURN(SAIL_ERROR_INVALID_ARGUMENT); + } + + char first_char; + SAIL_TRY(pnm_private_skip_to_letters_numbers(io, PNM_INVALID_STARTING_CHAR, &first_char)); + + unsigned i = 0; + char c = first_char; + + bool eof; + SAIL_TRY(io->eof(io->stream, &eof)); + + sail_status_t saved_status = SAIL_OK; + + while (isalnum(c) && i < str_size - 1 && !eof) { + *(str + i++) = c; + SAIL_TRY_OR_EXECUTE(io->strict_read(io->stream, &c, 1), + /* on error */ saved_status = __sail_status); + SAIL_TRY(io->eof(io->stream, &eof)); + + if (saved_status != SAIL_OK && !eof) { + return saved_status; + } + } + + /* The buffer is full but no word delimiter found. */ + if (i == str_size - 1 && !eof) { + SAIL_LOG_ERROR("PNM: No word delimiter found"); + SAIL_LOG_AND_RETURN(SAIL_ERROR_BROKEN_IMAGE); + } + + *(str + i) = '\0'; + + return SAIL_OK; +} + enum SailPixelFormat pnm_private_rgb_sail_pixel_format(enum SailPnmVersion pnm_version, unsigned bpp) { switch (pnm_version) { diff --git a/src/sail-codecs/pnm/helpers.h b/src/sail-codecs/pnm/helpers.h index a17afe3f..cf3a7702 100644 --- a/src/sail-codecs/pnm/helpers.h +++ b/src/sail-codecs/pnm/helpers.h @@ -26,6 +26,8 @@ #ifndef SAIL_PNM_HELPERS_H #define SAIL_PNM_HELPERS_H +#include /* size_t */ + #include #include #include @@ -41,7 +43,11 @@ enum SailPnmVersion { SAIL_PNM_VERSION_P6, }; -SAIL_HIDDEN sail_status_t pnm_private_skip_to_data(struct sail_io *io, char *first_char); +static const char PNM_INVALID_STARTING_CHAR = '\0'; + +SAIL_HIDDEN sail_status_t pnm_private_skip_to_letters_numbers(struct sail_io *io, char starting_char, char *first_char); + +SAIL_HIDDEN sail_status_t pnm_private_read_word(struct sail_io *io, char *str, size_t str_size); SAIL_HIDDEN enum SailPixelFormat pnm_private_rgb_sail_pixel_format(enum SailPnmVersion pnm_version, unsigned bpp); diff --git a/src/sail-codecs/pnm/pnm.c b/src/sail-codecs/pnm/pnm.c index bdb2519e..29d7f20c 100644 --- a/src/sail-codecs/pnm/pnm.c +++ b/src/sail-codecs/pnm/pnm.c @@ -90,7 +90,7 @@ SAIL_EXPORT sail_status_t sail_codec_load_init_v8_pnm(struct sail_io *io, const /* Init decoder. */ char str[8]; - SAIL_TRY(sail_read_string_from_io(pnm_state->io, str, sizeof(str))); + SAIL_TRY(pnm_private_read_word(pnm_state->io, str, sizeof(str))); const char pnm = str[1]; @@ -123,18 +123,28 @@ SAIL_EXPORT sail_status_t sail_codec_load_seek_next_frame_v8_pnm(void *state, st pnm_state->frame_loaded = true; - char first_char; - SAIL_TRY(pnm_private_skip_to_data(pnm_state->io, &first_char)); - - char str[32] = { first_char }; - SAIL_TRY(sail_read_string_from_io(pnm_state->io, str + 1, sizeof(str) - 1)); + char buffer[32]; /* Dimensions. */ - unsigned w, h; + unsigned w; + SAIL_TRY(pnm_private_read_word(pnm_state->io, buffer, sizeof(buffer))); + +#ifdef _MSC_VER + if (sscanf_s(buffer, "%u", &w) != 1) { +#else + if (sscanf(buffer, "%u", &w) != 1) { +#endif + SAIL_LOG_ERROR("PNM: Failed to read image dimensions"); + SAIL_LOG_AND_RETURN(SAIL_ERROR_BROKEN_IMAGE); + } + + unsigned h; + SAIL_TRY(pnm_private_read_word(pnm_state->io, buffer, sizeof(buffer))); + #ifdef _MSC_VER - if (sscanf_s(str, "%u%u", &w, &h) != 2) { + if (sscanf_s(buffer, "%u", &h) != 1) { #else - if (sscanf(str, "%u%u", &w, &h) != 2) { + if (sscanf(buffer, "%u", &h) != 1) { #endif SAIL_LOG_ERROR("PNM: Failed to read image dimensions"); SAIL_LOG_AND_RETURN(SAIL_ERROR_BROKEN_IMAGE); @@ -147,16 +157,14 @@ SAIL_EXPORT sail_status_t sail_codec_load_seek_next_frame_v8_pnm(void *state, st pnm_state->version == SAIL_PNM_VERSION_P3 || pnm_state->version == SAIL_PNM_VERSION_P5 || pnm_state->version == SAIL_PNM_VERSION_P6) { - SAIL_TRY(pnm_private_skip_to_data(pnm_state->io, &first_char)); - str[0] = first_char; - SAIL_TRY(sail_read_string_from_io(pnm_state->io, str + 1, sizeof(str) - 1)); + SAIL_TRY(pnm_private_read_word(pnm_state->io, buffer, sizeof(buffer))); unsigned max_color; #ifdef _MSC_VER - if (sscanf_s(str, "%u", &max_color) != 1) { + if (sscanf_s(buffer, "%u", &max_color) != 1) { #else - if (sscanf(str, "%u", &max_color) != 1) { + if (sscanf(buffer, "%u", &max_color) != 1) { #endif SAIL_LOG_ERROR("PNM: Failed to read maximum color value"); SAIL_LOG_AND_RETURN(SAIL_ERROR_BROKEN_IMAGE); @@ -232,9 +240,57 @@ SAIL_EXPORT sail_status_t sail_codec_load_frame_v8_pnm(void *state, struct sail_ break; } case SAIL_PNM_VERSION_P2: { + char buffer[8]; + + for (unsigned row = 0; row < image->height; row++) { + unsigned char *scanline = sail_scan_line(image, row); + + for (unsigned column = 0; column < image->width; column++) { + for(unsigned channel = 0; channel < 1; channel++) { + SAIL_TRY(pnm_private_read_word(pnm_state->io, buffer, sizeof(buffer))); + + unsigned value; + #ifdef _MSC_VER + if (sscanf_s(buffer, "%u", &value) != 1) { + #else + if (sscanf(buffer, "%u", &value) != 1) { + #endif + SAIL_LOG_ERROR("PNM: Failed to read color value"); + SAIL_LOG_AND_RETURN(SAIL_ERROR_BROKEN_IMAGE); + } + + // TODO 16-bit + *scanline++ = (unsigned char)value; + } + } + } break; } case SAIL_PNM_VERSION_P3: { + char buffer[8]; + + for (unsigned row = 0; row < image->height; row++) { + unsigned char *scanline = sail_scan_line(image, row); + + for (unsigned column = 0; column < image->width; column++) { + for(unsigned channel = 0; channel < 3; channel++) { + SAIL_TRY(pnm_private_read_word(pnm_state->io, buffer, sizeof(buffer))); + + unsigned value; + #ifdef _MSC_VER + if (sscanf_s(buffer, "%u", &value) != 1) { + #else + if (sscanf(buffer, "%u", &value) != 1) { + #endif + SAIL_LOG_ERROR("PNM: Failed to read color value"); + SAIL_LOG_AND_RETURN(SAIL_ERROR_BROKEN_IMAGE); + } + + // TODO 16-bit + *scanline++ = (unsigned char)value; + } + } + } break; } case SAIL_PNM_VERSION_P4: From a141b3d861ce347d9931fa70e5cd0dc78c67bb7e Mon Sep 17 00:00:00 2001 From: Dmitry Baryshev Date: Thu, 16 Nov 2023 09:22:04 +0300 Subject: [PATCH 05/23] PNM: Load P2 and P3 --- src/sail-codecs/pnm/helpers.c | 40 ++++++++++++++++++++-- src/sail-codecs/pnm/helpers.h | 5 ++- src/sail-codecs/pnm/pnm.c | 63 +++++------------------------------ 3 files changed, 50 insertions(+), 58 deletions(-) diff --git a/src/sail-codecs/pnm/helpers.c b/src/sail-codecs/pnm/helpers.c index c03e4fda..915217bb 100644 --- a/src/sail-codecs/pnm/helpers.c +++ b/src/sail-codecs/pnm/helpers.c @@ -25,6 +25,7 @@ #include #include +#include #include @@ -93,7 +94,40 @@ sail_status_t pnm_private_read_word(struct sail_io *io, char *str, size_t str_si return SAIL_OK; } -enum SailPixelFormat pnm_private_rgb_sail_pixel_format(enum SailPnmVersion pnm_version, unsigned bpp) { +sail_status_t pnm_private_read_pixels(struct sail_io *io, struct sail_image *image, unsigned channels, unsigned bpc, double multiplier_to_full_range) { + + for (unsigned row = 0; row < image->height; row++) { + uint8_t *scan8 = sail_scan_line(image, row); + uint16_t *scan16 = sail_scan_line(image, row); + + for (unsigned column = 0; column < image->width; column++) { + for(unsigned channel = 0; channel < channels; channel++) { + char buffer[8]; + SAIL_TRY(pnm_private_read_word(io, buffer, sizeof(buffer))); + + unsigned value; + #ifdef _MSC_VER + if (sscanf_s(buffer, "%u", &value) != 1) { + #else + if (sscanf(buffer, "%u", &value) != 1) { + #endif + SAIL_LOG_ERROR("PNM: Failed to read color value"); + SAIL_LOG_AND_RETURN(SAIL_ERROR_BROKEN_IMAGE); + } + + if (SAIL_LIKELY(bpc == 8)) { + *scan8++ = (uint8_t)(value * multiplier_to_full_range); + } else { + *scan16++ = (uint16_t)(value * multiplier_to_full_range); + } + } + } + } + + return SAIL_OK; +} + +enum SailPixelFormat pnm_private_rgb_sail_pixel_format(enum SailPnmVersion pnm_version, unsigned bpc) { switch (pnm_version) { case SAIL_PNM_VERSION_P1: @@ -101,7 +135,7 @@ enum SailPixelFormat pnm_private_rgb_sail_pixel_format(enum SailPnmVersion pnm_v case SAIL_PNM_VERSION_P2: case SAIL_PNM_VERSION_P5: { - switch (bpp) { + switch (bpc) { case 8: return SAIL_PIXEL_FORMAT_BPP8_GRAYSCALE; case 16: return SAIL_PIXEL_FORMAT_BPP16_GRAYSCALE; @@ -111,7 +145,7 @@ enum SailPixelFormat pnm_private_rgb_sail_pixel_format(enum SailPnmVersion pnm_v case SAIL_PNM_VERSION_P3: case SAIL_PNM_VERSION_P6: { - switch (bpp) { + switch (bpc) { case 8: return SAIL_PIXEL_FORMAT_BPP24_RGB; case 16: return SAIL_PIXEL_FORMAT_BPP48_RGB; diff --git a/src/sail-codecs/pnm/helpers.h b/src/sail-codecs/pnm/helpers.h index cf3a7702..a8ca2fb5 100644 --- a/src/sail-codecs/pnm/helpers.h +++ b/src/sail-codecs/pnm/helpers.h @@ -32,6 +32,7 @@ #include #include +struct sail_image; struct sail_io; enum SailPnmVersion { @@ -49,6 +50,8 @@ SAIL_HIDDEN sail_status_t pnm_private_skip_to_letters_numbers(struct sail_io *io SAIL_HIDDEN sail_status_t pnm_private_read_word(struct sail_io *io, char *str, size_t str_size); -SAIL_HIDDEN enum SailPixelFormat pnm_private_rgb_sail_pixel_format(enum SailPnmVersion pnm_version, unsigned bpp); +SAIL_HIDDEN sail_status_t pnm_private_read_pixels(struct sail_io *io, struct sail_image *image, unsigned channels, unsigned bpc, double multiplier_to_full_range); + +SAIL_HIDDEN enum SailPixelFormat pnm_private_rgb_sail_pixel_format(enum SailPnmVersion pnm_version, unsigned bpc); #endif diff --git a/src/sail-codecs/pnm/pnm.c b/src/sail-codecs/pnm/pnm.c index 29d7f20c..a0568e6f 100644 --- a/src/sail-codecs/pnm/pnm.c +++ b/src/sail-codecs/pnm/pnm.c @@ -43,6 +43,7 @@ struct pnm_state { bool frame_loaded; enum SailPnmVersion version; double multiplier_to_full_range; + unsigned bpc; }; static sail_status_t alloc_pnm_state(struct sail_io *io, @@ -60,7 +61,9 @@ static sail_status_t alloc_pnm_state(struct sail_io *io, .save_options = save_options, .frame_loaded = false, + .multiplier_to_full_range = 0, + .bpc = 0, }; return SAIL_OK; @@ -150,8 +153,6 @@ SAIL_EXPORT sail_status_t sail_codec_load_seek_next_frame_v8_pnm(void *state, st SAIL_LOG_AND_RETURN(SAIL_ERROR_BROKEN_IMAGE); } - unsigned bpp; - /* Maximum color. */ if (pnm_state->version == SAIL_PNM_VERSION_P2 || pnm_state->version == SAIL_PNM_VERSION_P3 || @@ -171,10 +172,10 @@ SAIL_EXPORT sail_status_t sail_codec_load_seek_next_frame_v8_pnm(void *state, st } if (max_color <= 255) { - bpp = 8; + pnm_state->bpc = 8; pnm_state->multiplier_to_full_range = 255.0 / max_color; } else if (max_color <= 65535) { - bpp = 16; + pnm_state->bpc = 16; pnm_state->multiplier_to_full_range = 65535.0 / max_color; } else { SAIL_LOG_ERROR("PNM: BPP more than 16 is not supported"); @@ -184,10 +185,10 @@ SAIL_EXPORT sail_status_t sail_codec_load_seek_next_frame_v8_pnm(void *state, st SAIL_LOG_TRACE("PNM: Max color(%u), scale(%.1f)", max_color, pnm_state->multiplier_to_full_range); } else { pnm_state->multiplier_to_full_range = 1; - bpp = 1; + pnm_state->bpc = 1; } - enum SailPixelFormat pixel_format = pnm_private_rgb_sail_pixel_format(pnm_state->version, bpp); + enum SailPixelFormat pixel_format = pnm_private_rgb_sail_pixel_format(pnm_state->version, pnm_state->bpc); if (pixel_format == SAIL_PIXEL_FORMAT_UNKNOWN) { SAIL_LOG_ERROR("PNM: Unsupported pixel format"); @@ -240,57 +241,11 @@ SAIL_EXPORT sail_status_t sail_codec_load_frame_v8_pnm(void *state, struct sail_ break; } case SAIL_PNM_VERSION_P2: { - char buffer[8]; - - for (unsigned row = 0; row < image->height; row++) { - unsigned char *scanline = sail_scan_line(image, row); - - for (unsigned column = 0; column < image->width; column++) { - for(unsigned channel = 0; channel < 1; channel++) { - SAIL_TRY(pnm_private_read_word(pnm_state->io, buffer, sizeof(buffer))); - - unsigned value; - #ifdef _MSC_VER - if (sscanf_s(buffer, "%u", &value) != 1) { - #else - if (sscanf(buffer, "%u", &value) != 1) { - #endif - SAIL_LOG_ERROR("PNM: Failed to read color value"); - SAIL_LOG_AND_RETURN(SAIL_ERROR_BROKEN_IMAGE); - } - - // TODO 16-bit - *scanline++ = (unsigned char)value; - } - } - } + SAIL_TRY(pnm_private_read_pixels(pnm_state->io, image, 1, pnm_state->bpc, pnm_state->multiplier_to_full_range)); break; } case SAIL_PNM_VERSION_P3: { - char buffer[8]; - - for (unsigned row = 0; row < image->height; row++) { - unsigned char *scanline = sail_scan_line(image, row); - - for (unsigned column = 0; column < image->width; column++) { - for(unsigned channel = 0; channel < 3; channel++) { - SAIL_TRY(pnm_private_read_word(pnm_state->io, buffer, sizeof(buffer))); - - unsigned value; - #ifdef _MSC_VER - if (sscanf_s(buffer, "%u", &value) != 1) { - #else - if (sscanf(buffer, "%u", &value) != 1) { - #endif - SAIL_LOG_ERROR("PNM: Failed to read color value"); - SAIL_LOG_AND_RETURN(SAIL_ERROR_BROKEN_IMAGE); - } - - // TODO 16-bit - *scanline++ = (unsigned char)value; - } - } - } + SAIL_TRY(pnm_private_read_pixels(pnm_state->io, image, 3, pnm_state->bpc, pnm_state->multiplier_to_full_range)); break; } case SAIL_PNM_VERSION_P4: From 20660ff735dd3ec302bbb773185f9caa7c351cce Mon Sep 17 00:00:00 2001 From: Dmitry Baryshev Date: Thu, 16 Nov 2023 09:27:49 +0300 Subject: [PATCH 06/23] PNM: Use memcpy to copy mono palette --- src/sail-codecs/pnm/helpers.c | 1 + src/sail-codecs/pnm/pnm.c | 13 ++++--------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/sail-codecs/pnm/helpers.c b/src/sail-codecs/pnm/helpers.c index 915217bb..b5ca2ce5 100644 --- a/src/sail-codecs/pnm/helpers.c +++ b/src/sail-codecs/pnm/helpers.c @@ -26,6 +26,7 @@ #include #include #include +#include #include diff --git a/src/sail-codecs/pnm/pnm.c b/src/sail-codecs/pnm/pnm.c index a0568e6f..915fbbaa 100644 --- a/src/sail-codecs/pnm/pnm.c +++ b/src/sail-codecs/pnm/pnm.c @@ -27,11 +27,14 @@ #include #include #include +#include #include #include "helpers.h" +static const uint8_t PNM_MONO_PALETTE[] = { 255, 255, 255, 0, 0, 0 }; + /* * Codec-specific state. */ @@ -216,15 +219,7 @@ SAIL_EXPORT sail_status_t sail_codec_load_seek_next_frame_v8_pnm(void *state, st SAIL_TRY_OR_CLEANUP(sail_alloc_palette_for_data(SAIL_PIXEL_FORMAT_BPP24_RGB, 2, &image_local->palette), /* cleanup */ sail_destroy_image(image_local)); - unsigned char *palette_data = image_local->palette->data; - - *palette_data++ = 255; - *palette_data++ = 255; - *palette_data++ = 255; - - *palette_data++ = 0; - *palette_data++ = 0; - *palette_data++ = 0; + memcpy(image_local->palette->data, PNM_MONO_PALETTE, 6); } *image = image_local; From 9ebd8f0a646c23679fabbb8119f665fcc189318d Mon Sep 17 00:00:00 2001 From: Dmitry Baryshev Date: Thu, 16 Nov 2023 09:37:28 +0300 Subject: [PATCH 07/23] PNM: Rename PNM_MONO_PALETTE --- src/sail-codecs/pnm/pnm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sail-codecs/pnm/pnm.c b/src/sail-codecs/pnm/pnm.c index 915fbbaa..b0d28ac3 100644 --- a/src/sail-codecs/pnm/pnm.c +++ b/src/sail-codecs/pnm/pnm.c @@ -33,7 +33,7 @@ #include "helpers.h" -static const uint8_t PNM_MONO_PALETTE[] = { 255, 255, 255, 0, 0, 0 }; +static const uint8_t SAIL_PNM_MONO_PALETTE[] = { 255, 255, 255, 0, 0, 0 }; /* * Codec-specific state. @@ -219,7 +219,7 @@ SAIL_EXPORT sail_status_t sail_codec_load_seek_next_frame_v8_pnm(void *state, st SAIL_TRY_OR_CLEANUP(sail_alloc_palette_for_data(SAIL_PIXEL_FORMAT_BPP24_RGB, 2, &image_local->palette), /* cleanup */ sail_destroy_image(image_local)); - memcpy(image_local->palette->data, PNM_MONO_PALETTE, 6); + memcpy(image_local->palette->data, SAIL_PNM_MONO_PALETTE, 6); } *image = image_local; From 01ea4297ae88099834d8e647bbee952c2a64ce0c Mon Sep 17 00:00:00 2001 From: Dmitry Baryshev Date: Thu, 16 Nov 2023 09:41:11 +0300 Subject: [PATCH 08/23] PNM: Rename PNM_INVALID_STARTING_CHAR --- src/sail-codecs/pnm/helpers.c | 2 +- src/sail-codecs/pnm/helpers.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sail-codecs/pnm/helpers.c b/src/sail-codecs/pnm/helpers.c index b5ca2ce5..3ba01dd3 100644 --- a/src/sail-codecs/pnm/helpers.c +++ b/src/sail-codecs/pnm/helpers.c @@ -63,7 +63,7 @@ sail_status_t pnm_private_read_word(struct sail_io *io, char *str, size_t str_si } char first_char; - SAIL_TRY(pnm_private_skip_to_letters_numbers(io, PNM_INVALID_STARTING_CHAR, &first_char)); + SAIL_TRY(pnm_private_skip_to_letters_numbers(io, SAIL_PNM_INVALID_STARTING_CHAR, &first_char)); unsigned i = 0; char c = first_char; diff --git a/src/sail-codecs/pnm/helpers.h b/src/sail-codecs/pnm/helpers.h index a8ca2fb5..e45a15c8 100644 --- a/src/sail-codecs/pnm/helpers.h +++ b/src/sail-codecs/pnm/helpers.h @@ -44,7 +44,7 @@ enum SailPnmVersion { SAIL_PNM_VERSION_P6, }; -static const char PNM_INVALID_STARTING_CHAR = '\0'; +static const char SAIL_PNM_INVALID_STARTING_CHAR = '\0'; SAIL_HIDDEN sail_status_t pnm_private_skip_to_letters_numbers(struct sail_io *io, char starting_char, char *first_char); From 2e432aef2bbd035e45963fad6612197df4997b83 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshev Date: Thu, 16 Nov 2023 10:50:09 +0300 Subject: [PATCH 09/23] PNM: Load P1 --- src/sail-codecs/pnm/helpers.c | 19 +++++++++++++------ src/sail-codecs/pnm/helpers.h | 2 ++ src/sail-codecs/pnm/pnm.c | 27 +++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/sail-codecs/pnm/helpers.c b/src/sail-codecs/pnm/helpers.c index 3ba01dd3..8148514a 100644 --- a/src/sail-codecs/pnm/helpers.c +++ b/src/sail-codecs/pnm/helpers.c @@ -32,12 +32,7 @@ #include "helpers.h" -sail_status_t pnm_private_skip_to_letters_numbers(struct sail_io *io, char starting_char, char *first_char) { - - if (isalnum(starting_char)) { - *first_char = starting_char; - return SAIL_OK; - } +sail_status_t pnm_private_skip_to_letters_numbers_force_read(struct sail_io *io, char *first_char) { char c; @@ -56,6 +51,18 @@ sail_status_t pnm_private_skip_to_letters_numbers(struct sail_io *io, char start return SAIL_OK; } +sail_status_t pnm_private_skip_to_letters_numbers(struct sail_io *io, char starting_char, char *first_char) { + + if (isalnum(starting_char)) { + *first_char = starting_char; + return SAIL_OK; + } + + SAIL_TRY(pnm_private_skip_to_letters_numbers_force_read(io, first_char)); + + return SAIL_OK; +} + sail_status_t pnm_private_read_word(struct sail_io *io, char *str, size_t str_size) { if (str_size < 2) { diff --git a/src/sail-codecs/pnm/helpers.h b/src/sail-codecs/pnm/helpers.h index e45a15c8..dcec56e9 100644 --- a/src/sail-codecs/pnm/helpers.h +++ b/src/sail-codecs/pnm/helpers.h @@ -46,6 +46,8 @@ enum SailPnmVersion { static const char SAIL_PNM_INVALID_STARTING_CHAR = '\0'; +SAIL_HIDDEN sail_status_t pnm_private_skip_to_letters_numbers_force_read(struct sail_io *io, char *first_char); + SAIL_HIDDEN sail_status_t pnm_private_skip_to_letters_numbers(struct sail_io *io, char starting_char, char *first_char); SAIL_HIDDEN sail_status_t pnm_private_read_word(struct sail_io *io, char *str, size_t str_size); diff --git a/src/sail-codecs/pnm/pnm.c b/src/sail-codecs/pnm/pnm.c index b0d28ac3..886cf459 100644 --- a/src/sail-codecs/pnm/pnm.c +++ b/src/sail-codecs/pnm/pnm.c @@ -233,6 +233,33 @@ SAIL_EXPORT sail_status_t sail_codec_load_frame_v8_pnm(void *state, struct sail_ switch (pnm_state->version) { case SAIL_PNM_VERSION_P1: { + for (unsigned row = 0; row < image->height; row++) { + uint8_t *scan = sail_scan_line(image, row); + unsigned shift = 8; + + for (unsigned column = 0; column < image->width; column++) { + char first_char; + SAIL_TRY(pnm_private_skip_to_letters_numbers_force_read(pnm_state->io, &first_char)); + + const unsigned value = first_char - '0'; + + if (value != 0 && value != 1) { + SAIL_LOG_ERROR("PNM: Unexpected character '%c'", first_char); + SAIL_LOG_AND_RETURN(SAIL_ERROR_BROKEN_IMAGE); + } + + if (shift == 8) { + *scan = 0; + } + + *scan |= (value << --shift); + + if (shift == 0) { + scan++; + shift = 8; + } + } + } break; } case SAIL_PNM_VERSION_P2: { From e98852208eda94d0369fc7eee8f5a2650e094baf Mon Sep 17 00:00:00 2001 From: Dmitry Baryshev Date: Thu, 16 Nov 2023 11:06:25 +0300 Subject: [PATCH 10/23] TESTS: Added PNM test images --- tests/images/pnm/bpp1-grayscale.ascii.pbm | 34 + tests/images/pnm/bpp1-grayscale.raw.pbm | Bin 0 -> 137 bytes tests/images/pnm/bpp24-rgb.ascii.pnm | 3076 +++++++++++++++++++++ tests/images/pnm/bpp24-rgb.raw.pnm | Bin 0 -> 3131 bytes tests/images/pnm/bpp8-grayscale.ascii.pgm | 1028 +++++++ tests/images/pnm/bpp8-grayscale.raw.pgm | Bin 0 -> 1083 bytes tests/images/test-images.h.in | 9 + 7 files changed, 4147 insertions(+) create mode 100644 tests/images/pnm/bpp1-grayscale.ascii.pbm create mode 100644 tests/images/pnm/bpp1-grayscale.raw.pbm create mode 100644 tests/images/pnm/bpp24-rgb.ascii.pnm create mode 100644 tests/images/pnm/bpp24-rgb.raw.pnm create mode 100644 tests/images/pnm/bpp8-grayscale.ascii.pgm create mode 100644 tests/images/pnm/bpp8-grayscale.raw.pgm diff --git a/tests/images/pnm/bpp1-grayscale.ascii.pbm b/tests/images/pnm/bpp1-grayscale.ascii.pbm new file mode 100644 index 00000000..caa729d6 --- /dev/null +++ b/tests/images/pnm/bpp1-grayscale.ascii.pbm @@ -0,0 +1,34 @@ +P1 +32 32 +11111111 11111111 11111111 11111111 +11111111 11111111 11111111 11111111 +11111111 11111111 11111111 11111111 +11111111 11111111 11111111 11111111 +11111111 11111111 11111111 11111111 +11111111 11111111 11111111 11111111 +11111111 11111111 11111111 11111111 +11111111 11111111 11111111 11111111 +11111111 11111111 11111111 00000000 +11111111 11111111 11111111 00000000 +11111111 11111111 11111111 00000000 +11111111 11111111 11111111 00000000 +11111111 11111111 11111111 00000000 +11111111 11111111 11111111 00000000 +11111111 11111111 11111111 00000000 +11111111 11111111 11111111 00000000 +00000000 00000000 00000000 00000000 +00000000 00000000 00000000 00000000 +00000000 00000000 00000000 00000000 +00000000 00000000 00000000 00000000 +00000000 00000000 00000000 00000000 +00000000 00000000 00000000 00000000 +00000000 00000000 00000000 00000000 +00000000 00000000 00000000 00000000 +11111111 00000000 00000000 00000000 +11111111 00000000 00000000 00000000 +11111111 00000000 00000000 00000000 +11111111 00000000 00000000 00000000 +11111111 00000000 00000000 00000000 +11111111 00000000 00000000 00000000 +11111111 00000000 00000000 00000000 +11111111 00000000 00000000 00000000 \ No newline at end of file diff --git a/tests/images/pnm/bpp1-grayscale.raw.pbm b/tests/images/pnm/bpp1-grayscale.raw.pbm new file mode 100644 index 0000000000000000000000000000000000000000..8ebfe9486eaad71fb3a28851de9779b4afb9dfdc GIT binary patch literal 137 jcmWGA;W9Q-FgD`)PZ%%&mEgn-{}~wYVW3u^UfdV}`w~$z literal 0 HcmV?d00001 diff --git a/tests/images/pnm/bpp24-rgb.ascii.pnm b/tests/images/pnm/bpp24-rgb.ascii.pnm new file mode 100644 index 00000000..6e82e9bd --- /dev/null +++ b/tests/images/pnm/bpp24-rgb.ascii.pnm @@ -0,0 +1,3076 @@ +P3 +# Created by GIMP version 2.10.36 PNM plug-in +32 32 +255 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 diff --git a/tests/images/pnm/bpp24-rgb.raw.pnm b/tests/images/pnm/bpp24-rgb.raw.pnm new file mode 100644 index 0000000000000000000000000000000000000000..77c672944dc3320161baa5a3600bb37fb41b1b04 GIT binary patch literal 3131 zcmeH{Jqp4=5QQi0o?^h-pc~8uEW{#`D<}pDNR;>kc6+qkY+P8=$h^WLl{38R1-^xk zN9xkec-=SqdvoN&i#OY<=4aF2+DpeiUoP^Z#b;EbP)0X^t9VE#YCrrysRr%)Zp literal 0 HcmV?d00001 diff --git a/tests/images/pnm/bpp8-grayscale.ascii.pgm b/tests/images/pnm/bpp8-grayscale.ascii.pgm new file mode 100644 index 00000000..207de6e1 --- /dev/null +++ b/tests/images/pnm/bpp8-grayscale.ascii.pgm @@ -0,0 +1,1028 @@ +P2 +# Created by GIMP version 2.10.36 PNM plug-in +32 32 +255 +0 +0 +0 +0 +0 +0 +0 +0 +62 +62 +62 +62 +62 +62 +62 +62 +110 +110 +110 +110 +110 +110 +110 +110 +124 +124 +124 +124 +124 +124 +124 +124 +0 +0 +0 +0 +0 +0 +0 +0 +62 +62 +62 +62 +62 +62 +62 +62 +110 +110 +110 +110 +110 +110 +110 +110 +124 +124 +124 +124 +124 +124 +124 +124 +0 +0 +0 +0 +0 +0 +0 +0 +62 +62 +62 +62 +62 +62 +62 +62 +110 +110 +110 +110 +110 +110 +110 +110 +124 +124 +124 +124 +124 +124 +124 +124 +0 +0 +0 +0 +0 +0 +0 +0 +62 +62 +62 +62 +62 +62 +62 +62 +110 +110 +110 +110 +110 +110 +110 +110 +124 +124 +124 +124 +124 +124 +124 +124 +0 +0 +0 +0 +0 +0 +0 +0 +62 +62 +62 +62 +62 +62 +62 +62 +110 +110 +110 +110 +110 +110 +110 +110 +124 +124 +124 +124 +124 +124 +124 +124 +0 +0 +0 +0 +0 +0 +0 +0 +62 +62 +62 +62 +62 +62 +62 +62 +110 +110 +110 +110 +110 +110 +110 +110 +124 +124 +124 +124 +124 +124 +124 +124 +0 +0 +0 +0 +0 +0 +0 +0 +62 +62 +62 +62 +62 +62 +62 +62 +110 +110 +110 +110 +110 +110 +110 +110 +124 +124 +124 +124 +124 +124 +124 +124 +0 +0 +0 +0 +0 +0 +0 +0 +62 +62 +62 +62 +62 +62 +62 +62 +110 +110 +110 +110 +110 +110 +110 +110 +124 +124 +124 +124 +124 +124 +124 +124 +30 +30 +30 +30 +30 +30 +30 +30 +70 +70 +70 +70 +70 +70 +70 +70 +114 +114 +114 +114 +114 +114 +114 +114 +192 +192 +192 +192 +192 +192 +192 +192 +30 +30 +30 +30 +30 +30 +30 +30 +70 +70 +70 +70 +70 +70 +70 +70 +114 +114 +114 +114 +114 +114 +114 +114 +192 +192 +192 +192 +192 +192 +192 +192 +30 +30 +30 +30 +30 +30 +30 +30 +70 +70 +70 +70 +70 +70 +70 +70 +114 +114 +114 +114 +114 +114 +114 +114 +192 +192 +192 +192 +192 +192 +192 +192 +30 +30 +30 +30 +30 +30 +30 +30 +70 +70 +70 +70 +70 +70 +70 +70 +114 +114 +114 +114 +114 +114 +114 +114 +192 +192 +192 +192 +192 +192 +192 +192 +30 +30 +30 +30 +30 +30 +30 +30 +70 +70 +70 +70 +70 +70 +70 +70 +114 +114 +114 +114 +114 +114 +114 +114 +192 +192 +192 +192 +192 +192 +192 +192 +30 +30 +30 +30 +30 +30 +30 +30 +70 +70 +70 +70 +70 +70 +70 +70 +114 +114 +114 +114 +114 +114 +114 +114 +192 +192 +192 +192 +192 +192 +192 +192 +30 +30 +30 +30 +30 +30 +30 +30 +70 +70 +70 +70 +70 +70 +70 +70 +114 +114 +114 +114 +114 +114 +114 +114 +192 +192 +192 +192 +192 +192 +192 +192 +30 +30 +30 +30 +30 +30 +30 +30 +70 +70 +70 +70 +70 +70 +70 +70 +114 +114 +114 +114 +114 +114 +114 +114 +192 +192 +192 +192 +192 +192 +192 +192 +128 +128 +128 +128 +128 +128 +128 +128 +130 +130 +130 +130 +130 +130 +130 +130 +220 +220 +220 +220 +220 +220 +220 +220 +248 +248 +248 +248 +248 +248 +248 +248 +128 +128 +128 +128 +128 +128 +128 +128 +130 +130 +130 +130 +130 +130 +130 +130 +220 +220 +220 +220 +220 +220 +220 +220 +248 +248 +248 +248 +248 +248 +248 +248 +128 +128 +128 +128 +128 +128 +128 +128 +130 +130 +130 +130 +130 +130 +130 +130 +220 +220 +220 +220 +220 +220 +220 +220 +248 +248 +248 +248 +248 +248 +248 +248 +128 +128 +128 +128 +128 +128 +128 +128 +130 +130 +130 +130 +130 +130 +130 +130 +220 +220 +220 +220 +220 +220 +220 +220 +248 +248 +248 +248 +248 +248 +248 +248 +128 +128 +128 +128 +128 +128 +128 +128 +130 +130 +130 +130 +130 +130 +130 +130 +220 +220 +220 +220 +220 +220 +220 +220 +248 +248 +248 +248 +248 +248 +248 +248 +128 +128 +128 +128 +128 +128 +128 +128 +130 +130 +130 +130 +130 +130 +130 +130 +220 +220 +220 +220 +220 +220 +220 +220 +248 +248 +248 +248 +248 +248 +248 +248 +128 +128 +128 +128 +128 +128 +128 +128 +130 +130 +130 +130 +130 +130 +130 +130 +220 +220 +220 +220 +220 +220 +220 +220 +248 +248 +248 +248 +248 +248 +248 +248 +128 +128 +128 +128 +128 +128 +128 +128 +130 +130 +130 +130 +130 +130 +130 +130 +220 +220 +220 +220 +220 +220 +220 +220 +248 +248 +248 +248 +248 +248 +248 +248 +70 +70 +70 +70 +70 +70 +70 +70 +145 +145 +145 +145 +145 +145 +145 +145 +228 +228 +228 +228 +228 +228 +228 +228 +255 +255 +255 +255 +255 +255 +255 +255 +70 +70 +70 +70 +70 +70 +70 +70 +145 +145 +145 +145 +145 +145 +145 +145 +228 +228 +228 +228 +228 +228 +228 +228 +255 +255 +255 +255 +255 +255 +255 +255 +70 +70 +70 +70 +70 +70 +70 +70 +145 +145 +145 +145 +145 +145 +145 +145 +228 +228 +228 +228 +228 +228 +228 +228 +255 +255 +255 +255 +255 +255 +255 +255 +70 +70 +70 +70 +70 +70 +70 +70 +145 +145 +145 +145 +145 +145 +145 +145 +228 +228 +228 +228 +228 +228 +228 +228 +255 +255 +255 +255 +255 +255 +255 +255 +70 +70 +70 +70 +70 +70 +70 +70 +145 +145 +145 +145 +145 +145 +145 +145 +228 +228 +228 +228 +228 +228 +228 +228 +255 +255 +255 +255 +255 +255 +255 +255 +70 +70 +70 +70 +70 +70 +70 +70 +145 +145 +145 +145 +145 +145 +145 +145 +228 +228 +228 +228 +228 +228 +228 +228 +255 +255 +255 +255 +255 +255 +255 +255 +70 +70 +70 +70 +70 +70 +70 +70 +145 +145 +145 +145 +145 +145 +145 +145 +228 +228 +228 +228 +228 +228 +228 +228 +255 +255 +255 +255 +255 +255 +255 +255 +70 +70 +70 +70 +70 +70 +70 +70 +145 +145 +145 +145 +145 +145 +145 +145 +228 +228 +228 +228 +228 +228 +228 +228 +255 +255 +255 +255 +255 +255 +255 +255 diff --git a/tests/images/pnm/bpp8-grayscale.raw.pgm b/tests/images/pnm/bpp8-grayscale.raw.pgm new file mode 100644 index 0000000000000000000000000000000000000000..3dc480799fa1eb29b868c1e6718af93c049f0751 GIT binary patch literal 1083 zcmWGA9Vqw#1;bq)7Vi_G N;0YA`hl1fQ4*+?KBbopJ literal 0 HcmV?d00001 diff --git a/tests/images/test-images.h.in b/tests/images/test-images.h.in index 20092bc0..93b18856 100644 --- a/tests/images/test-images.h.in +++ b/tests/images/test-images.h.in @@ -58,6 +58,15 @@ static const char * const SAIL_TEST_IMAGES[] = { "@SAIL_TEST_IMAGES_PATH@/png/bpp4-indexed.comment.iccp.png", #endif +#ifdef SAIL_HAVE_BUILTIN_PNM + "@SAIL_TEST_IMAGES_PATH@/pnm/bpp1-grayscale.ascii.pbm", + "@SAIL_TEST_IMAGES_PATH@/pnm/bpp1-grayscale.raw.pbm", + "@SAIL_TEST_IMAGES_PATH@/pnm/bpp24-rgb.ascii.pnm", + "@SAIL_TEST_IMAGES_PATH@/pnm/bpp24-rgb.raw.pnm", + "@SAIL_TEST_IMAGES_PATH@/pnm/bpp8-grayscale.ascii.pgm", + "@SAIL_TEST_IMAGES_PATH@/pnm/bpp8-grayscale.raw.pgm", +#endif + #ifdef SAIL_HAVE_BUILTIN_PSD "@SAIL_TEST_IMAGES_PATH@/psd/bpp8-indexed.psd", "@SAIL_TEST_IMAGES_PATH@/psd/bpp24-rgb.psd", From 3f0a6e51a4e5b6f761781f39ec91d2cccdf76634 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshev Date: Thu, 16 Nov 2023 11:10:56 +0300 Subject: [PATCH 11/23] DOC: Added PNM --- FORMATS.md | 29 ++++++++++++++++++++++------- README.md | 13 +++++++------ 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/FORMATS.md b/FORMATS.md index fbd206a0..cfd4192b 100644 --- a/FORMATS.md +++ b/FORMATS.md @@ -239,6 +239,21 @@ 11 + PNM + + Grayscale: 1-bit, 8-bit, 16-bit. + Indexed: 1-bit, 8-bit. + RGB: 24-bit, 48-bit. +

+ Content: Static. + + - + Unsupported + - + - + + + 12 PSD Grayscale: 8-bit, 16-bit. @@ -265,7 +280,7 @@ - - 12 + 13 QOI RGB: 24-bit. @@ -284,7 +299,7 @@ - - 13 + 14 SVG Bit depth: 32-bit. @@ -303,7 +318,7 @@ resvg or nanosvg - 14 + 15 TGA Grayscale: 8-bit. @@ -319,7 +334,7 @@ - - 15 + 16 TIFF Bit depth: 1-bit, 2-bit, 4-bit, 8-bit, 16-bit, 24-bit, 32-bit, 48-bit, 64-bit. @@ -340,7 +355,7 @@ libtiff - 16 + 17 WAL Indexed: 8-bit. @@ -353,7 +368,7 @@ - - 17 + 18 WEBP Bit depth: 24-bit, 32-bit. @@ -366,7 +381,7 @@ libwebp - 18 + 19 XBM Bit depth: 1-bit. diff --git a/README.md b/README.md index 11f997c7..49ca0115 100644 --- a/README.md +++ b/README.md @@ -79,13 +79,14 @@ images with the help of [ksquirrel-libs](FAQ.md#how-old-is-sail), the predecesso | 8 | [JPEG XL](https://wikipedia.org/wiki/JPEG_XL) | R | libjxl | | 9 | [PCX](https://wikipedia.org/wiki/PCX) | R | | | 10 | [PNG](https://wikipedia.org/wiki/Portable_Network_Graphics) | RW | libpng | -| 11 | [PSD](https://en.wikipedia.org/wiki/Adobe_Photoshop#File_format) | R | | -| 12 | [QOI](http://qoiformat.org) | RW | | -| 13 | [SVG](https://wikipedia.org/wiki/Scalable_Vector_Graphics) | R | resvg | -| 14 | [TGA](https://wikipedia.org/wiki/Truevision_TGA) | R | | -| 15 | [TIFF](https://wikipedia.org/wiki/TIFF) | RW | libtiff | | .. | ... | | | -| 17 | [WEBP](https://wikipedia.org/wiki/WebP) | R | libwebp | +| 12 | [PSD](https://en.wikipedia.org/wiki/Adobe_Photoshop#File_format) | R | | +| 13 | [QOI](http://qoiformat.org) | RW | | +| 14 | [SVG](https://wikipedia.org/wiki/Scalable_Vector_Graphics) | R | resvg | +| 15 | [TGA](https://wikipedia.org/wiki/Truevision_TGA) | R | | +| 16 | [TIFF](https://wikipedia.org/wiki/TIFF) | RW | libtiff | +| .. | ... | | | +| 18 | [WEBP](https://wikipedia.org/wiki/WebP) | R | libwebp | | .. | ... | | | See the full list [here](FORMATS.md). Work to add more image formats is ongoing. From 700727285e7c0f24db812711850b24b4bfbf9b6b Mon Sep 17 00:00:00 2001 From: Dmitry Baryshev Date: Thu, 16 Nov 2023 11:28:16 +0300 Subject: [PATCH 12/23] SAIL: Set version to 0.9.1 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e2709046..f56da3ec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.12) -project(SAIL VERSION 0.9.0 +project(SAIL VERSION 0.9.1 DESCRIPTION "Squirrel Abstract Image Library" LANGUAGES C CXX) From 456dad1e69ff865eb4cc812e89fb53da945d9afa Mon Sep 17 00:00:00 2001 From: Dmitry Baryshev Date: Tue, 14 Nov 2023 13:27:01 +0300 Subject: [PATCH 13/23] PNM: PNM codec skeleton --- src/sail-codecs/CMakeLists.txt | 2 +- src/sail-codecs/pnm/CMakeLists.txt | 3 + src/sail-codecs/pnm/helpers.c | 66 +++++++ src/sail-codecs/pnm/helpers.h | 48 ++++++ src/sail-codecs/pnm/pnm.c | 236 ++++++++++++++++++++++++++ src/sail-codecs/pnm/pnm.codec.info.in | 26 +++ src/sail-codecs/pnm/pnm.png | Bin 0 -> 314 bytes 7 files changed, 380 insertions(+), 1 deletion(-) create mode 100644 src/sail-codecs/pnm/CMakeLists.txt create mode 100644 src/sail-codecs/pnm/helpers.c create mode 100644 src/sail-codecs/pnm/helpers.h create mode 100644 src/sail-codecs/pnm/pnm.c create mode 100644 src/sail-codecs/pnm/pnm.codec.info.in create mode 100644 src/sail-codecs/pnm/pnm.png diff --git a/src/sail-codecs/CMakeLists.txt b/src/sail-codecs/CMakeLists.txt index 2996212c..457f3a69 100644 --- a/src/sail-codecs/CMakeLists.txt +++ b/src/sail-codecs/CMakeLists.txt @@ -7,7 +7,7 @@ add_subdirectory(common/bmp) set(HIGHEST_PRIORITY_CODECS gif jpeg png tiff) set(HIGH_PRIORITY_CODECS bmp svg) set(MEDIUM_PRIORITY_CODECS avif jpeg2000 jpegxl webp) -set(LOW_PRIORITY_CODECS ico pcx psd qoi tga) +set(LOW_PRIORITY_CODECS ico pcx pnm psd qoi tga) set(LOWEST_PRIORITY_CODECS wal xbm) set(CODECS ${HIGHEST_PRIORITY_CODECS} diff --git a/src/sail-codecs/pnm/CMakeLists.txt b/src/sail-codecs/pnm/CMakeLists.txt new file mode 100644 index 00000000..632a0f97 --- /dev/null +++ b/src/sail-codecs/pnm/CMakeLists.txt @@ -0,0 +1,3 @@ +# Common codec configuration +# +sail_codec(NAME pnm SOURCES helpers.h helpers.c pnm.c ICON pnm.png) diff --git a/src/sail-codecs/pnm/helpers.c b/src/sail-codecs/pnm/helpers.c new file mode 100644 index 00000000..208c2d03 --- /dev/null +++ b/src/sail-codecs/pnm/helpers.c @@ -0,0 +1,66 @@ +/* This file is part of SAIL (https://github.com/HappySeaFox/sail) + + Copyright (c) 2023 Dmitry Baryshev + + The MIT License + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +#include + +#include "helpers.h" + +sail_status_t pnm_private_skip_to_data(struct sail_io *io, char *first_char) { + + char c; + + do { + SAIL_TRY(io->strict_read(io->stream, &c, 1)); + + if (c == '#') { + do { + SAIL_TRY(io->strict_read(io->stream, &c, 1)); + } while(c != '\n'); + } + } while(c < '0' || c > '9'); + + *first_char = c; + + return SAIL_OK; +} + +enum SailPixelFormat pnm_private_rgb_sail_pixel_format(enum SailPnmVersion pnm_version) { + + switch (pnm_version) { + case SAIL_PNM_VERSION_P1: + case SAIL_PNM_VERSION_P4: return SAIL_PIXEL_FORMAT_BPP1_INDEXED; + + case SAIL_PNM_VERSION_P2: + case SAIL_PNM_VERSION_P5: return SAIL_PIXEL_FORMAT_BPP8_GRAYSCALE; + + case SAIL_PNM_VERSION_P3: + case SAIL_PNM_VERSION_P6: return SAIL_PIXEL_FORMAT_BPP24_RGB; + + default: { + return SAIL_PIXEL_FORMAT_UNKNOWN; + } + } +} + diff --git a/src/sail-codecs/pnm/helpers.h b/src/sail-codecs/pnm/helpers.h new file mode 100644 index 00000000..086e8c67 --- /dev/null +++ b/src/sail-codecs/pnm/helpers.h @@ -0,0 +1,48 @@ +/* This file is part of SAIL (https://github.com/HappySeaFox/sail) + + Copyright (c) 2023 Dmitry Baryshev + + The MIT License + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +#ifndef SAIL_PNM_HELPERS_H +#define SAIL_PNM_HELPERS_H + +#include +#include +#include + +struct sail_io; + +enum SailPnmVersion { + SAIL_PNM_VERSION_P1, + SAIL_PNM_VERSION_P2, + SAIL_PNM_VERSION_P3, + SAIL_PNM_VERSION_P4, + SAIL_PNM_VERSION_P5, + SAIL_PNM_VERSION_P6, +}; + +SAIL_HIDDEN sail_status_t pnm_private_skip_to_data(struct sail_io *io, char *first_char); + +SAIL_HIDDEN enum SailPixelFormat pnm_private_rgb_sail_pixel_format(enum SailPnmVersion pnm_version); + +#endif diff --git a/src/sail-codecs/pnm/pnm.c b/src/sail-codecs/pnm/pnm.c new file mode 100644 index 00000000..15382b23 --- /dev/null +++ b/src/sail-codecs/pnm/pnm.c @@ -0,0 +1,236 @@ +/* This file is part of SAIL (https://github.com/HappySeaFox/sail) + + Copyright (c) 2023 Dmitry Baryshev + + The MIT License + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +#include +#include +#include +#include + +#include + +#include "helpers.h" + +/* + * Codec-specific state. + */ +struct pnm_state { + struct sail_io *io; + const struct sail_load_options *load_options; + const struct sail_save_options *save_options; + + bool frame_loaded; + enum SailPnmVersion version; +}; + +static sail_status_t alloc_pnm_state(struct sail_io *io, + const struct sail_load_options *load_options, + const struct sail_save_options *save_options, + struct pnm_state **pnm_state) { + + void *ptr; + SAIL_TRY(sail_malloc(sizeof(struct pnm_state), &ptr)); + *pnm_state = ptr; + + **pnm_state = (struct pnm_state) { + .io = io, + .load_options = load_options, + .save_options = save_options, + + .frame_loaded = false, + }; + + return SAIL_OK; +} + +static void destroy_pnm_state(struct pnm_state *pnm_state) { + + if (pnm_state == NULL) { + return; + } + + sail_free(pnm_state); +} + +/* + * Decoding functions. + */ + +SAIL_EXPORT sail_status_t sail_codec_load_init_v8_pnm(struct sail_io *io, const struct sail_load_options *load_options, void **state) { + + *state = NULL; + + /* Allocate a new state. */ + struct pnm_state *pnm_state; + SAIL_TRY(alloc_pnm_state(io, load_options, NULL, &pnm_state)); + *state = pnm_state; + + /* Init decoder. */ + char str[8]; + SAIL_TRY(sail_read_string_from_io(pnm_state->io, str, sizeof(str))); + + const char pnm = str[1]; + + SAIL_LOG_TRACE("PNM: Version '%c'", pnm); + + switch (pnm) { + case '1': pnm_state->version = SAIL_PNM_VERSION_P1; break; + case '2': pnm_state->version = SAIL_PNM_VERSION_P2; break; + case '3': pnm_state->version = SAIL_PNM_VERSION_P3; break; + case '4': pnm_state->version = SAIL_PNM_VERSION_P4; break; + case '5': pnm_state->version = SAIL_PNM_VERSION_P5; break; + case '6': pnm_state->version = SAIL_PNM_VERSION_P6; break; + + default: { + SAIL_LOG_ERROR("PNM: Unsupported version '%c'", pnm); + SAIL_LOG_AND_RETURN(SAIL_ERROR_UNSUPPORTED_FORMAT); + } + } + + return SAIL_OK; +} + +SAIL_EXPORT sail_status_t sail_codec_load_seek_next_frame_v8_pnm(void *state, struct sail_image **image) { + + struct pnm_state *pnm_state = state; + + if (pnm_state->frame_loaded) { + SAIL_LOG_AND_RETURN(SAIL_ERROR_NO_MORE_FRAMES); + } + + pnm_state->frame_loaded = true; + + char first_char; + SAIL_TRY(pnm_private_skip_to_data(pnm_state->io, &first_char)); + + char width_height_str[32] = { first_char }; + SAIL_TRY(sail_read_string_from_io(pnm_state->io, width_height_str + 1, sizeof(width_height_str) - 1)); + + unsigned w, h; +#ifdef _MSC_VER + if (sscanf_s(width_height_str, "%u%u", &w, &h) != 2) { +#else + if (sscanf(width_height_str, "%u%u", &w, &h) != 2) { +#endif + SAIL_LOG_ERROR("PNM: Failed to read image dimensions"); + SAIL_LOG_AND_RETURN(SAIL_ERROR_BROKEN_IMAGE); + } + + enum SailPixelFormat pixel_format = pnm_private_rgb_sail_pixel_format(pnm_state->version); + + if (pixel_format == SAIL_PIXEL_FORMAT_UNKNOWN) { + SAIL_LOG_ERROR("PNM: Unsupported pixel format"); + SAIL_LOG_AND_RETURN(SAIL_ERROR_UNSUPPORTED_PIXEL_FORMAT); + } + + struct sail_image *image_local; + SAIL_TRY(sail_alloc_image(&image_local)); + + if (pnm_state->load_options->options & SAIL_OPTION_SOURCE_IMAGE) { + SAIL_TRY_OR_CLEANUP(sail_alloc_source_image(&image_local->source_image), + /* cleanup */ sail_destroy_image(image_local)); + + image_local->source_image->pixel_format = pixel_format; + image_local->source_image->compression = SAIL_COMPRESSION_NONE; + } + + image_local->width = w; + image_local->height = h; + image_local->pixel_format = pixel_format; + image_local->delay = -1; + image_local->bytes_per_line = sail_bytes_per_line(image_local->width, image_local->pixel_format); + + if (pixel_format == SAIL_PIXEL_FORMAT_BPP1_INDEXED) { + SAIL_TRY_OR_CLEANUP(sail_alloc_palette_for_data(SAIL_PIXEL_FORMAT_BPP24_RGB, 2, &image_local->palette), + /* cleanup */ sail_destroy_image(image_local)); + + unsigned char *palette_data = image_local->palette->data; + + *palette_data++ = 255; + *palette_data++ = 255; + *palette_data++ = 255; + + *palette_data++ = 0; + *palette_data++ = 0; + *palette_data++ = 0; + } + + *image = image_local; + + return SAIL_OK; +} + +SAIL_EXPORT sail_status_t sail_codec_load_frame_v8_pnm(void *state, struct sail_image *image) { + + const struct pnm_state *pnm_state = state; + + return SAIL_OK; +} + +SAIL_EXPORT sail_status_t sail_codec_load_finish_v8_pnm(void **state) { + + struct pnm_state *pnm_state = *state; + + *state = NULL; + + destroy_pnm_state(pnm_state); + + return SAIL_OK; +} + +/* + * Encoding functions. + */ + +SAIL_EXPORT sail_status_t sail_codec_save_init_v8_pnm(struct sail_io *io, const struct sail_save_options *save_options, void **state) { + + (void)io; + (void)save_options; + (void)state; + + SAIL_LOG_AND_RETURN(SAIL_ERROR_NOT_IMPLEMENTED); +} + +SAIL_EXPORT sail_status_t sail_codec_save_seek_next_frame_v8_pnm(void *state, const struct sail_image *image) { + + (void)state; + (void)image; + + SAIL_LOG_AND_RETURN(SAIL_ERROR_NOT_IMPLEMENTED); +} + +SAIL_EXPORT sail_status_t sail_codec_save_frame_v8_pnm(void *state, const struct sail_image *image) { + + (void)state; + (void)image; + + SAIL_LOG_AND_RETURN(SAIL_ERROR_NOT_IMPLEMENTED); +} + +SAIL_EXPORT sail_status_t sail_codec_save_finish_v8_pnm(void **state) { + + (void)state; + + SAIL_LOG_AND_RETURN(SAIL_ERROR_NOT_IMPLEMENTED); +} diff --git a/src/sail-codecs/pnm/pnm.codec.info.in b/src/sail-codecs/pnm/pnm.codec.info.in new file mode 100644 index 00000000..6e4e991a --- /dev/null +++ b/src/sail-codecs/pnm/pnm.codec.info.in @@ -0,0 +1,26 @@ +# PNM codec information +# +[codec] +layout=8 +version=0.6.5 +priority=LOW +name=PNM +description=Portable aNy Map +magic-numbers=50 31;50 32;50 33;50 34;50 35;50 36 +extensions=pbm;pgm;ppm;pnm +mime-types=image/x-portable-bitmap;image/x-portable-graymap;image/x-portable-pixmap;image/x-portable-anymap + +[load-features] +features=STATIC;SOURCE-IMAGE +tuning= + +[save-features] +features= +pixel-formats= +compressions= +default-compression= +compression-level-min=0 +compression-level-max=0 +compression-level-default=0 +compression-level-step=0 +tuning= diff --git a/src/sail-codecs/pnm/pnm.png b/src/sail-codecs/pnm/pnm.png new file mode 100644 index 0000000000000000000000000000000000000000..0f448d2ae0d1e0c752f9134c9d4cd8315bec7cff GIT binary patch literal 314 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Ea{HEjtmSN`?>!lvI6;>1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP_Hy@V>PnGCRkRc~MT^vI!PA{Eo$k%Kjz;gVAtnGe> zDSs5MiaNNTH-53>yTFowr|dQzO{X-4gxW0xm9*!U-21%l+NNBWBO950F9(RU-uxuC zAouqCq)=7g;9vX7LqlisGdI|rZ+?_Hi@{@3i_U3@wu3)Cb*uxgmrl5!`anJ~^nRL~ z%biU+GOesTj(t@8m^rVL!D4>=R;4TKJ6?EBdAfJs%pY@(-|jz~dUE#5YbkTn>Ahs?720@fA9EF0z=%wY%Ma&hbVC=qUzIS3j3^ HP6kfPK literal 0 HcmV?d00001 From 35a3c7f28621e358f9196265c8c8da43236aa267 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshev Date: Tue, 14 Nov 2023 19:08:46 +0300 Subject: [PATCH 14/23] PNM: Read P4, P5, P6 --- src/sail-codecs/pnm/helpers.c | 20 ++++++++-- src/sail-codecs/pnm/helpers.h | 2 +- src/sail-codecs/pnm/pnm.c | 72 ++++++++++++++++++++++++++++++++--- 3 files changed, 85 insertions(+), 9 deletions(-) diff --git a/src/sail-codecs/pnm/helpers.c b/src/sail-codecs/pnm/helpers.c index 208c2d03..b508f40e 100644 --- a/src/sail-codecs/pnm/helpers.c +++ b/src/sail-codecs/pnm/helpers.c @@ -46,17 +46,31 @@ sail_status_t pnm_private_skip_to_data(struct sail_io *io, char *first_char) { return SAIL_OK; } -enum SailPixelFormat pnm_private_rgb_sail_pixel_format(enum SailPnmVersion pnm_version) { +enum SailPixelFormat pnm_private_rgb_sail_pixel_format(enum SailPnmVersion pnm_version, unsigned bpp) { switch (pnm_version) { case SAIL_PNM_VERSION_P1: case SAIL_PNM_VERSION_P4: return SAIL_PIXEL_FORMAT_BPP1_INDEXED; case SAIL_PNM_VERSION_P2: - case SAIL_PNM_VERSION_P5: return SAIL_PIXEL_FORMAT_BPP8_GRAYSCALE; + case SAIL_PNM_VERSION_P5: { + switch (bpp) { + case 8: return SAIL_PIXEL_FORMAT_BPP8_GRAYSCALE; + case 16: return SAIL_PIXEL_FORMAT_BPP16_GRAYSCALE; + + default: return SAIL_PIXEL_FORMAT_UNKNOWN; + } + } case SAIL_PNM_VERSION_P3: - case SAIL_PNM_VERSION_P6: return SAIL_PIXEL_FORMAT_BPP24_RGB; + case SAIL_PNM_VERSION_P6: { + switch (bpp) { + case 8: return SAIL_PIXEL_FORMAT_BPP24_RGB; + case 16: return SAIL_PIXEL_FORMAT_BPP48_RGB; + + default: return SAIL_PIXEL_FORMAT_UNKNOWN; + } + } default: { return SAIL_PIXEL_FORMAT_UNKNOWN; diff --git a/src/sail-codecs/pnm/helpers.h b/src/sail-codecs/pnm/helpers.h index 086e8c67..a17afe3f 100644 --- a/src/sail-codecs/pnm/helpers.h +++ b/src/sail-codecs/pnm/helpers.h @@ -43,6 +43,6 @@ enum SailPnmVersion { SAIL_HIDDEN sail_status_t pnm_private_skip_to_data(struct sail_io *io, char *first_char); -SAIL_HIDDEN enum SailPixelFormat pnm_private_rgb_sail_pixel_format(enum SailPnmVersion pnm_version); +SAIL_HIDDEN enum SailPixelFormat pnm_private_rgb_sail_pixel_format(enum SailPnmVersion pnm_version, unsigned bpp); #endif diff --git a/src/sail-codecs/pnm/pnm.c b/src/sail-codecs/pnm/pnm.c index 15382b23..bdb2519e 100644 --- a/src/sail-codecs/pnm/pnm.c +++ b/src/sail-codecs/pnm/pnm.c @@ -42,6 +42,7 @@ struct pnm_state { bool frame_loaded; enum SailPnmVersion version; + double multiplier_to_full_range; }; static sail_status_t alloc_pnm_state(struct sail_io *io, @@ -59,6 +60,7 @@ static sail_status_t alloc_pnm_state(struct sail_io *io, .save_options = save_options, .frame_loaded = false, + .multiplier_to_full_range = 0, }; return SAIL_OK; @@ -124,20 +126,60 @@ SAIL_EXPORT sail_status_t sail_codec_load_seek_next_frame_v8_pnm(void *state, st char first_char; SAIL_TRY(pnm_private_skip_to_data(pnm_state->io, &first_char)); - char width_height_str[32] = { first_char }; - SAIL_TRY(sail_read_string_from_io(pnm_state->io, width_height_str + 1, sizeof(width_height_str) - 1)); + char str[32] = { first_char }; + SAIL_TRY(sail_read_string_from_io(pnm_state->io, str + 1, sizeof(str) - 1)); + /* Dimensions. */ unsigned w, h; #ifdef _MSC_VER - if (sscanf_s(width_height_str, "%u%u", &w, &h) != 2) { + if (sscanf_s(str, "%u%u", &w, &h) != 2) { #else - if (sscanf(width_height_str, "%u%u", &w, &h) != 2) { + if (sscanf(str, "%u%u", &w, &h) != 2) { #endif SAIL_LOG_ERROR("PNM: Failed to read image dimensions"); SAIL_LOG_AND_RETURN(SAIL_ERROR_BROKEN_IMAGE); } - enum SailPixelFormat pixel_format = pnm_private_rgb_sail_pixel_format(pnm_state->version); + unsigned bpp; + + /* Maximum color. */ + if (pnm_state->version == SAIL_PNM_VERSION_P2 || + pnm_state->version == SAIL_PNM_VERSION_P3 || + pnm_state->version == SAIL_PNM_VERSION_P5 || + pnm_state->version == SAIL_PNM_VERSION_P6) { + SAIL_TRY(pnm_private_skip_to_data(pnm_state->io, &first_char)); + + str[0] = first_char; + SAIL_TRY(sail_read_string_from_io(pnm_state->io, str + 1, sizeof(str) - 1)); + + unsigned max_color; +#ifdef _MSC_VER + if (sscanf_s(str, "%u", &max_color) != 1) { +#else + if (sscanf(str, "%u", &max_color) != 1) { +#endif + SAIL_LOG_ERROR("PNM: Failed to read maximum color value"); + SAIL_LOG_AND_RETURN(SAIL_ERROR_BROKEN_IMAGE); + } + + if (max_color <= 255) { + bpp = 8; + pnm_state->multiplier_to_full_range = 255.0 / max_color; + } else if (max_color <= 65535) { + bpp = 16; + pnm_state->multiplier_to_full_range = 65535.0 / max_color; + } else { + SAIL_LOG_ERROR("PNM: BPP more than 16 is not supported"); + SAIL_LOG_AND_RETURN(SAIL_ERROR_UNSUPPORTED_FORMAT); + } + + SAIL_LOG_TRACE("PNM: Max color(%u), scale(%.1f)", max_color, pnm_state->multiplier_to_full_range); + } else { + pnm_state->multiplier_to_full_range = 1; + bpp = 1; + } + + enum SailPixelFormat pixel_format = pnm_private_rgb_sail_pixel_format(pnm_state->version, bpp); if (pixel_format == SAIL_PIXEL_FORMAT_UNKNOWN) { SAIL_LOG_ERROR("PNM: Unsupported pixel format"); @@ -185,6 +227,26 @@ SAIL_EXPORT sail_status_t sail_codec_load_frame_v8_pnm(void *state, struct sail_ const struct pnm_state *pnm_state = state; + switch (pnm_state->version) { + case SAIL_PNM_VERSION_P1: { + break; + } + case SAIL_PNM_VERSION_P2: { + break; + } + case SAIL_PNM_VERSION_P3: { + break; + } + case SAIL_PNM_VERSION_P4: + case SAIL_PNM_VERSION_P5: + case SAIL_PNM_VERSION_P6: { + for (unsigned row = 0; row < image->height; row++) { + SAIL_TRY(pnm_state->io->strict_read(pnm_state->io->stream, sail_scan_line(image, row), image->bytes_per_line)); + } + break; + } + } + return SAIL_OK; } From 6d3b5d1a34da392a1522ae9b4c4ee05a0d2f43a7 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshev Date: Wed, 15 Nov 2023 16:24:15 +0300 Subject: [PATCH 15/23] LIBSAIL: Clarify more on io_file API --- src/sail/io_file.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sail/io_file.h b/src/sail/io_file.h index 9d6b757a..cfb221c2 100644 --- a/src/sail/io_file.h +++ b/src/sail/io_file.h @@ -37,7 +37,7 @@ struct sail_io; /* * Opens the specified image file for reading and allocates a new I/O object for it. - * sail_io.stream is a pointer to a FILE. + * sail_io.stream is a pointer to a FILE. fread/fwrite/fseek/feof are used underneath. * * Returns SAIL_OK on success. */ From d745678b099b7fcc617c5215ae7a83119b928958 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshev Date: Wed, 15 Nov 2023 16:41:14 +0300 Subject: [PATCH 16/23] PNM: WIP in reading ASCII files --- src/sail-codecs/pnm/helpers.c | 51 ++++++++++++++++++++- src/sail-codecs/pnm/helpers.h | 8 +++- src/sail-codecs/pnm/pnm.c | 84 +++++++++++++++++++++++++++++------ 3 files changed, 126 insertions(+), 17 deletions(-) diff --git a/src/sail-codecs/pnm/helpers.c b/src/sail-codecs/pnm/helpers.c index b508f40e..c03e4fda 100644 --- a/src/sail-codecs/pnm/helpers.c +++ b/src/sail-codecs/pnm/helpers.c @@ -23,11 +23,19 @@ SOFTWARE. */ +#include +#include + #include #include "helpers.h" -sail_status_t pnm_private_skip_to_data(struct sail_io *io, char *first_char) { +sail_status_t pnm_private_skip_to_letters_numbers(struct sail_io *io, char starting_char, char *first_char) { + + if (isalnum(starting_char)) { + *first_char = starting_char; + return SAIL_OK; + } char c; @@ -39,13 +47,52 @@ sail_status_t pnm_private_skip_to_data(struct sail_io *io, char *first_char) { SAIL_TRY(io->strict_read(io->stream, &c, 1)); } while(c != '\n'); } - } while(c < '0' || c > '9'); + } while (!isalnum(c)); *first_char = c; return SAIL_OK; } +sail_status_t pnm_private_read_word(struct sail_io *io, char *str, size_t str_size) { + + if (str_size < 2) { + SAIL_LOG_AND_RETURN(SAIL_ERROR_INVALID_ARGUMENT); + } + + char first_char; + SAIL_TRY(pnm_private_skip_to_letters_numbers(io, PNM_INVALID_STARTING_CHAR, &first_char)); + + unsigned i = 0; + char c = first_char; + + bool eof; + SAIL_TRY(io->eof(io->stream, &eof)); + + sail_status_t saved_status = SAIL_OK; + + while (isalnum(c) && i < str_size - 1 && !eof) { + *(str + i++) = c; + SAIL_TRY_OR_EXECUTE(io->strict_read(io->stream, &c, 1), + /* on error */ saved_status = __sail_status); + SAIL_TRY(io->eof(io->stream, &eof)); + + if (saved_status != SAIL_OK && !eof) { + return saved_status; + } + } + + /* The buffer is full but no word delimiter found. */ + if (i == str_size - 1 && !eof) { + SAIL_LOG_ERROR("PNM: No word delimiter found"); + SAIL_LOG_AND_RETURN(SAIL_ERROR_BROKEN_IMAGE); + } + + *(str + i) = '\0'; + + return SAIL_OK; +} + enum SailPixelFormat pnm_private_rgb_sail_pixel_format(enum SailPnmVersion pnm_version, unsigned bpp) { switch (pnm_version) { diff --git a/src/sail-codecs/pnm/helpers.h b/src/sail-codecs/pnm/helpers.h index a17afe3f..cf3a7702 100644 --- a/src/sail-codecs/pnm/helpers.h +++ b/src/sail-codecs/pnm/helpers.h @@ -26,6 +26,8 @@ #ifndef SAIL_PNM_HELPERS_H #define SAIL_PNM_HELPERS_H +#include /* size_t */ + #include #include #include @@ -41,7 +43,11 @@ enum SailPnmVersion { SAIL_PNM_VERSION_P6, }; -SAIL_HIDDEN sail_status_t pnm_private_skip_to_data(struct sail_io *io, char *first_char); +static const char PNM_INVALID_STARTING_CHAR = '\0'; + +SAIL_HIDDEN sail_status_t pnm_private_skip_to_letters_numbers(struct sail_io *io, char starting_char, char *first_char); + +SAIL_HIDDEN sail_status_t pnm_private_read_word(struct sail_io *io, char *str, size_t str_size); SAIL_HIDDEN enum SailPixelFormat pnm_private_rgb_sail_pixel_format(enum SailPnmVersion pnm_version, unsigned bpp); diff --git a/src/sail-codecs/pnm/pnm.c b/src/sail-codecs/pnm/pnm.c index bdb2519e..29d7f20c 100644 --- a/src/sail-codecs/pnm/pnm.c +++ b/src/sail-codecs/pnm/pnm.c @@ -90,7 +90,7 @@ SAIL_EXPORT sail_status_t sail_codec_load_init_v8_pnm(struct sail_io *io, const /* Init decoder. */ char str[8]; - SAIL_TRY(sail_read_string_from_io(pnm_state->io, str, sizeof(str))); + SAIL_TRY(pnm_private_read_word(pnm_state->io, str, sizeof(str))); const char pnm = str[1]; @@ -123,18 +123,28 @@ SAIL_EXPORT sail_status_t sail_codec_load_seek_next_frame_v8_pnm(void *state, st pnm_state->frame_loaded = true; - char first_char; - SAIL_TRY(pnm_private_skip_to_data(pnm_state->io, &first_char)); - - char str[32] = { first_char }; - SAIL_TRY(sail_read_string_from_io(pnm_state->io, str + 1, sizeof(str) - 1)); + char buffer[32]; /* Dimensions. */ - unsigned w, h; + unsigned w; + SAIL_TRY(pnm_private_read_word(pnm_state->io, buffer, sizeof(buffer))); + +#ifdef _MSC_VER + if (sscanf_s(buffer, "%u", &w) != 1) { +#else + if (sscanf(buffer, "%u", &w) != 1) { +#endif + SAIL_LOG_ERROR("PNM: Failed to read image dimensions"); + SAIL_LOG_AND_RETURN(SAIL_ERROR_BROKEN_IMAGE); + } + + unsigned h; + SAIL_TRY(pnm_private_read_word(pnm_state->io, buffer, sizeof(buffer))); + #ifdef _MSC_VER - if (sscanf_s(str, "%u%u", &w, &h) != 2) { + if (sscanf_s(buffer, "%u", &h) != 1) { #else - if (sscanf(str, "%u%u", &w, &h) != 2) { + if (sscanf(buffer, "%u", &h) != 1) { #endif SAIL_LOG_ERROR("PNM: Failed to read image dimensions"); SAIL_LOG_AND_RETURN(SAIL_ERROR_BROKEN_IMAGE); @@ -147,16 +157,14 @@ SAIL_EXPORT sail_status_t sail_codec_load_seek_next_frame_v8_pnm(void *state, st pnm_state->version == SAIL_PNM_VERSION_P3 || pnm_state->version == SAIL_PNM_VERSION_P5 || pnm_state->version == SAIL_PNM_VERSION_P6) { - SAIL_TRY(pnm_private_skip_to_data(pnm_state->io, &first_char)); - str[0] = first_char; - SAIL_TRY(sail_read_string_from_io(pnm_state->io, str + 1, sizeof(str) - 1)); + SAIL_TRY(pnm_private_read_word(pnm_state->io, buffer, sizeof(buffer))); unsigned max_color; #ifdef _MSC_VER - if (sscanf_s(str, "%u", &max_color) != 1) { + if (sscanf_s(buffer, "%u", &max_color) != 1) { #else - if (sscanf(str, "%u", &max_color) != 1) { + if (sscanf(buffer, "%u", &max_color) != 1) { #endif SAIL_LOG_ERROR("PNM: Failed to read maximum color value"); SAIL_LOG_AND_RETURN(SAIL_ERROR_BROKEN_IMAGE); @@ -232,9 +240,57 @@ SAIL_EXPORT sail_status_t sail_codec_load_frame_v8_pnm(void *state, struct sail_ break; } case SAIL_PNM_VERSION_P2: { + char buffer[8]; + + for (unsigned row = 0; row < image->height; row++) { + unsigned char *scanline = sail_scan_line(image, row); + + for (unsigned column = 0; column < image->width; column++) { + for(unsigned channel = 0; channel < 1; channel++) { + SAIL_TRY(pnm_private_read_word(pnm_state->io, buffer, sizeof(buffer))); + + unsigned value; + #ifdef _MSC_VER + if (sscanf_s(buffer, "%u", &value) != 1) { + #else + if (sscanf(buffer, "%u", &value) != 1) { + #endif + SAIL_LOG_ERROR("PNM: Failed to read color value"); + SAIL_LOG_AND_RETURN(SAIL_ERROR_BROKEN_IMAGE); + } + + // TODO 16-bit + *scanline++ = (unsigned char)value; + } + } + } break; } case SAIL_PNM_VERSION_P3: { + char buffer[8]; + + for (unsigned row = 0; row < image->height; row++) { + unsigned char *scanline = sail_scan_line(image, row); + + for (unsigned column = 0; column < image->width; column++) { + for(unsigned channel = 0; channel < 3; channel++) { + SAIL_TRY(pnm_private_read_word(pnm_state->io, buffer, sizeof(buffer))); + + unsigned value; + #ifdef _MSC_VER + if (sscanf_s(buffer, "%u", &value) != 1) { + #else + if (sscanf(buffer, "%u", &value) != 1) { + #endif + SAIL_LOG_ERROR("PNM: Failed to read color value"); + SAIL_LOG_AND_RETURN(SAIL_ERROR_BROKEN_IMAGE); + } + + // TODO 16-bit + *scanline++ = (unsigned char)value; + } + } + } break; } case SAIL_PNM_VERSION_P4: From 5e589dcc90ba5bdbe6666b35131656e0f0364758 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshev Date: Thu, 16 Nov 2023 09:22:04 +0300 Subject: [PATCH 17/23] PNM: Load P2 and P3 --- src/sail-codecs/pnm/helpers.c | 40 ++++++++++++++++++++-- src/sail-codecs/pnm/helpers.h | 5 ++- src/sail-codecs/pnm/pnm.c | 63 +++++------------------------------ 3 files changed, 50 insertions(+), 58 deletions(-) diff --git a/src/sail-codecs/pnm/helpers.c b/src/sail-codecs/pnm/helpers.c index c03e4fda..915217bb 100644 --- a/src/sail-codecs/pnm/helpers.c +++ b/src/sail-codecs/pnm/helpers.c @@ -25,6 +25,7 @@ #include #include +#include #include @@ -93,7 +94,40 @@ sail_status_t pnm_private_read_word(struct sail_io *io, char *str, size_t str_si return SAIL_OK; } -enum SailPixelFormat pnm_private_rgb_sail_pixel_format(enum SailPnmVersion pnm_version, unsigned bpp) { +sail_status_t pnm_private_read_pixels(struct sail_io *io, struct sail_image *image, unsigned channels, unsigned bpc, double multiplier_to_full_range) { + + for (unsigned row = 0; row < image->height; row++) { + uint8_t *scan8 = sail_scan_line(image, row); + uint16_t *scan16 = sail_scan_line(image, row); + + for (unsigned column = 0; column < image->width; column++) { + for(unsigned channel = 0; channel < channels; channel++) { + char buffer[8]; + SAIL_TRY(pnm_private_read_word(io, buffer, sizeof(buffer))); + + unsigned value; + #ifdef _MSC_VER + if (sscanf_s(buffer, "%u", &value) != 1) { + #else + if (sscanf(buffer, "%u", &value) != 1) { + #endif + SAIL_LOG_ERROR("PNM: Failed to read color value"); + SAIL_LOG_AND_RETURN(SAIL_ERROR_BROKEN_IMAGE); + } + + if (SAIL_LIKELY(bpc == 8)) { + *scan8++ = (uint8_t)(value * multiplier_to_full_range); + } else { + *scan16++ = (uint16_t)(value * multiplier_to_full_range); + } + } + } + } + + return SAIL_OK; +} + +enum SailPixelFormat pnm_private_rgb_sail_pixel_format(enum SailPnmVersion pnm_version, unsigned bpc) { switch (pnm_version) { case SAIL_PNM_VERSION_P1: @@ -101,7 +135,7 @@ enum SailPixelFormat pnm_private_rgb_sail_pixel_format(enum SailPnmVersion pnm_v case SAIL_PNM_VERSION_P2: case SAIL_PNM_VERSION_P5: { - switch (bpp) { + switch (bpc) { case 8: return SAIL_PIXEL_FORMAT_BPP8_GRAYSCALE; case 16: return SAIL_PIXEL_FORMAT_BPP16_GRAYSCALE; @@ -111,7 +145,7 @@ enum SailPixelFormat pnm_private_rgb_sail_pixel_format(enum SailPnmVersion pnm_v case SAIL_PNM_VERSION_P3: case SAIL_PNM_VERSION_P6: { - switch (bpp) { + switch (bpc) { case 8: return SAIL_PIXEL_FORMAT_BPP24_RGB; case 16: return SAIL_PIXEL_FORMAT_BPP48_RGB; diff --git a/src/sail-codecs/pnm/helpers.h b/src/sail-codecs/pnm/helpers.h index cf3a7702..a8ca2fb5 100644 --- a/src/sail-codecs/pnm/helpers.h +++ b/src/sail-codecs/pnm/helpers.h @@ -32,6 +32,7 @@ #include #include +struct sail_image; struct sail_io; enum SailPnmVersion { @@ -49,6 +50,8 @@ SAIL_HIDDEN sail_status_t pnm_private_skip_to_letters_numbers(struct sail_io *io SAIL_HIDDEN sail_status_t pnm_private_read_word(struct sail_io *io, char *str, size_t str_size); -SAIL_HIDDEN enum SailPixelFormat pnm_private_rgb_sail_pixel_format(enum SailPnmVersion pnm_version, unsigned bpp); +SAIL_HIDDEN sail_status_t pnm_private_read_pixels(struct sail_io *io, struct sail_image *image, unsigned channels, unsigned bpc, double multiplier_to_full_range); + +SAIL_HIDDEN enum SailPixelFormat pnm_private_rgb_sail_pixel_format(enum SailPnmVersion pnm_version, unsigned bpc); #endif diff --git a/src/sail-codecs/pnm/pnm.c b/src/sail-codecs/pnm/pnm.c index 29d7f20c..a0568e6f 100644 --- a/src/sail-codecs/pnm/pnm.c +++ b/src/sail-codecs/pnm/pnm.c @@ -43,6 +43,7 @@ struct pnm_state { bool frame_loaded; enum SailPnmVersion version; double multiplier_to_full_range; + unsigned bpc; }; static sail_status_t alloc_pnm_state(struct sail_io *io, @@ -60,7 +61,9 @@ static sail_status_t alloc_pnm_state(struct sail_io *io, .save_options = save_options, .frame_loaded = false, + .multiplier_to_full_range = 0, + .bpc = 0, }; return SAIL_OK; @@ -150,8 +153,6 @@ SAIL_EXPORT sail_status_t sail_codec_load_seek_next_frame_v8_pnm(void *state, st SAIL_LOG_AND_RETURN(SAIL_ERROR_BROKEN_IMAGE); } - unsigned bpp; - /* Maximum color. */ if (pnm_state->version == SAIL_PNM_VERSION_P2 || pnm_state->version == SAIL_PNM_VERSION_P3 || @@ -171,10 +172,10 @@ SAIL_EXPORT sail_status_t sail_codec_load_seek_next_frame_v8_pnm(void *state, st } if (max_color <= 255) { - bpp = 8; + pnm_state->bpc = 8; pnm_state->multiplier_to_full_range = 255.0 / max_color; } else if (max_color <= 65535) { - bpp = 16; + pnm_state->bpc = 16; pnm_state->multiplier_to_full_range = 65535.0 / max_color; } else { SAIL_LOG_ERROR("PNM: BPP more than 16 is not supported"); @@ -184,10 +185,10 @@ SAIL_EXPORT sail_status_t sail_codec_load_seek_next_frame_v8_pnm(void *state, st SAIL_LOG_TRACE("PNM: Max color(%u), scale(%.1f)", max_color, pnm_state->multiplier_to_full_range); } else { pnm_state->multiplier_to_full_range = 1; - bpp = 1; + pnm_state->bpc = 1; } - enum SailPixelFormat pixel_format = pnm_private_rgb_sail_pixel_format(pnm_state->version, bpp); + enum SailPixelFormat pixel_format = pnm_private_rgb_sail_pixel_format(pnm_state->version, pnm_state->bpc); if (pixel_format == SAIL_PIXEL_FORMAT_UNKNOWN) { SAIL_LOG_ERROR("PNM: Unsupported pixel format"); @@ -240,57 +241,11 @@ SAIL_EXPORT sail_status_t sail_codec_load_frame_v8_pnm(void *state, struct sail_ break; } case SAIL_PNM_VERSION_P2: { - char buffer[8]; - - for (unsigned row = 0; row < image->height; row++) { - unsigned char *scanline = sail_scan_line(image, row); - - for (unsigned column = 0; column < image->width; column++) { - for(unsigned channel = 0; channel < 1; channel++) { - SAIL_TRY(pnm_private_read_word(pnm_state->io, buffer, sizeof(buffer))); - - unsigned value; - #ifdef _MSC_VER - if (sscanf_s(buffer, "%u", &value) != 1) { - #else - if (sscanf(buffer, "%u", &value) != 1) { - #endif - SAIL_LOG_ERROR("PNM: Failed to read color value"); - SAIL_LOG_AND_RETURN(SAIL_ERROR_BROKEN_IMAGE); - } - - // TODO 16-bit - *scanline++ = (unsigned char)value; - } - } - } + SAIL_TRY(pnm_private_read_pixels(pnm_state->io, image, 1, pnm_state->bpc, pnm_state->multiplier_to_full_range)); break; } case SAIL_PNM_VERSION_P3: { - char buffer[8]; - - for (unsigned row = 0; row < image->height; row++) { - unsigned char *scanline = sail_scan_line(image, row); - - for (unsigned column = 0; column < image->width; column++) { - for(unsigned channel = 0; channel < 3; channel++) { - SAIL_TRY(pnm_private_read_word(pnm_state->io, buffer, sizeof(buffer))); - - unsigned value; - #ifdef _MSC_VER - if (sscanf_s(buffer, "%u", &value) != 1) { - #else - if (sscanf(buffer, "%u", &value) != 1) { - #endif - SAIL_LOG_ERROR("PNM: Failed to read color value"); - SAIL_LOG_AND_RETURN(SAIL_ERROR_BROKEN_IMAGE); - } - - // TODO 16-bit - *scanline++ = (unsigned char)value; - } - } - } + SAIL_TRY(pnm_private_read_pixels(pnm_state->io, image, 3, pnm_state->bpc, pnm_state->multiplier_to_full_range)); break; } case SAIL_PNM_VERSION_P4: From b406e8cbea6c46e33afbc994cdd9f9a4362f6ba2 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshev Date: Thu, 16 Nov 2023 09:27:49 +0300 Subject: [PATCH 18/23] PNM: Use memcpy to copy mono palette --- src/sail-codecs/pnm/helpers.c | 1 + src/sail-codecs/pnm/pnm.c | 13 ++++--------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/sail-codecs/pnm/helpers.c b/src/sail-codecs/pnm/helpers.c index 915217bb..b5ca2ce5 100644 --- a/src/sail-codecs/pnm/helpers.c +++ b/src/sail-codecs/pnm/helpers.c @@ -26,6 +26,7 @@ #include #include #include +#include #include diff --git a/src/sail-codecs/pnm/pnm.c b/src/sail-codecs/pnm/pnm.c index a0568e6f..915fbbaa 100644 --- a/src/sail-codecs/pnm/pnm.c +++ b/src/sail-codecs/pnm/pnm.c @@ -27,11 +27,14 @@ #include #include #include +#include #include #include "helpers.h" +static const uint8_t PNM_MONO_PALETTE[] = { 255, 255, 255, 0, 0, 0 }; + /* * Codec-specific state. */ @@ -216,15 +219,7 @@ SAIL_EXPORT sail_status_t sail_codec_load_seek_next_frame_v8_pnm(void *state, st SAIL_TRY_OR_CLEANUP(sail_alloc_palette_for_data(SAIL_PIXEL_FORMAT_BPP24_RGB, 2, &image_local->palette), /* cleanup */ sail_destroy_image(image_local)); - unsigned char *palette_data = image_local->palette->data; - - *palette_data++ = 255; - *palette_data++ = 255; - *palette_data++ = 255; - - *palette_data++ = 0; - *palette_data++ = 0; - *palette_data++ = 0; + memcpy(image_local->palette->data, PNM_MONO_PALETTE, 6); } *image = image_local; From fb091df1bdaa918ef10b2119c0ce1374c8921de9 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshev Date: Thu, 16 Nov 2023 09:37:28 +0300 Subject: [PATCH 19/23] PNM: Rename PNM_MONO_PALETTE --- src/sail-codecs/pnm/pnm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sail-codecs/pnm/pnm.c b/src/sail-codecs/pnm/pnm.c index 915fbbaa..b0d28ac3 100644 --- a/src/sail-codecs/pnm/pnm.c +++ b/src/sail-codecs/pnm/pnm.c @@ -33,7 +33,7 @@ #include "helpers.h" -static const uint8_t PNM_MONO_PALETTE[] = { 255, 255, 255, 0, 0, 0 }; +static const uint8_t SAIL_PNM_MONO_PALETTE[] = { 255, 255, 255, 0, 0, 0 }; /* * Codec-specific state. @@ -219,7 +219,7 @@ SAIL_EXPORT sail_status_t sail_codec_load_seek_next_frame_v8_pnm(void *state, st SAIL_TRY_OR_CLEANUP(sail_alloc_palette_for_data(SAIL_PIXEL_FORMAT_BPP24_RGB, 2, &image_local->palette), /* cleanup */ sail_destroy_image(image_local)); - memcpy(image_local->palette->data, PNM_MONO_PALETTE, 6); + memcpy(image_local->palette->data, SAIL_PNM_MONO_PALETTE, 6); } *image = image_local; From 4912bc365e8b2377922101b4234fd7ab0ba0d831 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshev Date: Thu, 16 Nov 2023 09:41:11 +0300 Subject: [PATCH 20/23] PNM: Rename PNM_INVALID_STARTING_CHAR --- src/sail-codecs/pnm/helpers.c | 2 +- src/sail-codecs/pnm/helpers.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sail-codecs/pnm/helpers.c b/src/sail-codecs/pnm/helpers.c index b5ca2ce5..3ba01dd3 100644 --- a/src/sail-codecs/pnm/helpers.c +++ b/src/sail-codecs/pnm/helpers.c @@ -63,7 +63,7 @@ sail_status_t pnm_private_read_word(struct sail_io *io, char *str, size_t str_si } char first_char; - SAIL_TRY(pnm_private_skip_to_letters_numbers(io, PNM_INVALID_STARTING_CHAR, &first_char)); + SAIL_TRY(pnm_private_skip_to_letters_numbers(io, SAIL_PNM_INVALID_STARTING_CHAR, &first_char)); unsigned i = 0; char c = first_char; diff --git a/src/sail-codecs/pnm/helpers.h b/src/sail-codecs/pnm/helpers.h index a8ca2fb5..e45a15c8 100644 --- a/src/sail-codecs/pnm/helpers.h +++ b/src/sail-codecs/pnm/helpers.h @@ -44,7 +44,7 @@ enum SailPnmVersion { SAIL_PNM_VERSION_P6, }; -static const char PNM_INVALID_STARTING_CHAR = '\0'; +static const char SAIL_PNM_INVALID_STARTING_CHAR = '\0'; SAIL_HIDDEN sail_status_t pnm_private_skip_to_letters_numbers(struct sail_io *io, char starting_char, char *first_char); From 20b91185901d3d55c614592e0cd8d4e4c87edb89 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshev Date: Thu, 16 Nov 2023 10:50:09 +0300 Subject: [PATCH 21/23] PNM: Load P1 --- src/sail-codecs/pnm/helpers.c | 19 +++++++++++++------ src/sail-codecs/pnm/helpers.h | 2 ++ src/sail-codecs/pnm/pnm.c | 27 +++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/sail-codecs/pnm/helpers.c b/src/sail-codecs/pnm/helpers.c index 3ba01dd3..8148514a 100644 --- a/src/sail-codecs/pnm/helpers.c +++ b/src/sail-codecs/pnm/helpers.c @@ -32,12 +32,7 @@ #include "helpers.h" -sail_status_t pnm_private_skip_to_letters_numbers(struct sail_io *io, char starting_char, char *first_char) { - - if (isalnum(starting_char)) { - *first_char = starting_char; - return SAIL_OK; - } +sail_status_t pnm_private_skip_to_letters_numbers_force_read(struct sail_io *io, char *first_char) { char c; @@ -56,6 +51,18 @@ sail_status_t pnm_private_skip_to_letters_numbers(struct sail_io *io, char start return SAIL_OK; } +sail_status_t pnm_private_skip_to_letters_numbers(struct sail_io *io, char starting_char, char *first_char) { + + if (isalnum(starting_char)) { + *first_char = starting_char; + return SAIL_OK; + } + + SAIL_TRY(pnm_private_skip_to_letters_numbers_force_read(io, first_char)); + + return SAIL_OK; +} + sail_status_t pnm_private_read_word(struct sail_io *io, char *str, size_t str_size) { if (str_size < 2) { diff --git a/src/sail-codecs/pnm/helpers.h b/src/sail-codecs/pnm/helpers.h index e45a15c8..dcec56e9 100644 --- a/src/sail-codecs/pnm/helpers.h +++ b/src/sail-codecs/pnm/helpers.h @@ -46,6 +46,8 @@ enum SailPnmVersion { static const char SAIL_PNM_INVALID_STARTING_CHAR = '\0'; +SAIL_HIDDEN sail_status_t pnm_private_skip_to_letters_numbers_force_read(struct sail_io *io, char *first_char); + SAIL_HIDDEN sail_status_t pnm_private_skip_to_letters_numbers(struct sail_io *io, char starting_char, char *first_char); SAIL_HIDDEN sail_status_t pnm_private_read_word(struct sail_io *io, char *str, size_t str_size); diff --git a/src/sail-codecs/pnm/pnm.c b/src/sail-codecs/pnm/pnm.c index b0d28ac3..886cf459 100644 --- a/src/sail-codecs/pnm/pnm.c +++ b/src/sail-codecs/pnm/pnm.c @@ -233,6 +233,33 @@ SAIL_EXPORT sail_status_t sail_codec_load_frame_v8_pnm(void *state, struct sail_ switch (pnm_state->version) { case SAIL_PNM_VERSION_P1: { + for (unsigned row = 0; row < image->height; row++) { + uint8_t *scan = sail_scan_line(image, row); + unsigned shift = 8; + + for (unsigned column = 0; column < image->width; column++) { + char first_char; + SAIL_TRY(pnm_private_skip_to_letters_numbers_force_read(pnm_state->io, &first_char)); + + const unsigned value = first_char - '0'; + + if (value != 0 && value != 1) { + SAIL_LOG_ERROR("PNM: Unexpected character '%c'", first_char); + SAIL_LOG_AND_RETURN(SAIL_ERROR_BROKEN_IMAGE); + } + + if (shift == 8) { + *scan = 0; + } + + *scan |= (value << --shift); + + if (shift == 0) { + scan++; + shift = 8; + } + } + } break; } case SAIL_PNM_VERSION_P2: { From e8274b85b31af12756bec3d38cb65e48dd705e22 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshev Date: Thu, 16 Nov 2023 11:06:25 +0300 Subject: [PATCH 22/23] TESTS: Added PNM test images --- tests/images/pnm/bpp1-grayscale.ascii.pbm | 34 + tests/images/pnm/bpp1-grayscale.raw.pbm | Bin 0 -> 137 bytes tests/images/pnm/bpp24-rgb.ascii.pnm | 3076 +++++++++++++++++++++ tests/images/pnm/bpp24-rgb.raw.pnm | Bin 0 -> 3131 bytes tests/images/pnm/bpp8-grayscale.ascii.pgm | 1028 +++++++ tests/images/pnm/bpp8-grayscale.raw.pgm | Bin 0 -> 1083 bytes tests/images/test-images.h.in | 9 + 7 files changed, 4147 insertions(+) create mode 100644 tests/images/pnm/bpp1-grayscale.ascii.pbm create mode 100644 tests/images/pnm/bpp1-grayscale.raw.pbm create mode 100644 tests/images/pnm/bpp24-rgb.ascii.pnm create mode 100644 tests/images/pnm/bpp24-rgb.raw.pnm create mode 100644 tests/images/pnm/bpp8-grayscale.ascii.pgm create mode 100644 tests/images/pnm/bpp8-grayscale.raw.pgm diff --git a/tests/images/pnm/bpp1-grayscale.ascii.pbm b/tests/images/pnm/bpp1-grayscale.ascii.pbm new file mode 100644 index 00000000..caa729d6 --- /dev/null +++ b/tests/images/pnm/bpp1-grayscale.ascii.pbm @@ -0,0 +1,34 @@ +P1 +32 32 +11111111 11111111 11111111 11111111 +11111111 11111111 11111111 11111111 +11111111 11111111 11111111 11111111 +11111111 11111111 11111111 11111111 +11111111 11111111 11111111 11111111 +11111111 11111111 11111111 11111111 +11111111 11111111 11111111 11111111 +11111111 11111111 11111111 11111111 +11111111 11111111 11111111 00000000 +11111111 11111111 11111111 00000000 +11111111 11111111 11111111 00000000 +11111111 11111111 11111111 00000000 +11111111 11111111 11111111 00000000 +11111111 11111111 11111111 00000000 +11111111 11111111 11111111 00000000 +11111111 11111111 11111111 00000000 +00000000 00000000 00000000 00000000 +00000000 00000000 00000000 00000000 +00000000 00000000 00000000 00000000 +00000000 00000000 00000000 00000000 +00000000 00000000 00000000 00000000 +00000000 00000000 00000000 00000000 +00000000 00000000 00000000 00000000 +00000000 00000000 00000000 00000000 +11111111 00000000 00000000 00000000 +11111111 00000000 00000000 00000000 +11111111 00000000 00000000 00000000 +11111111 00000000 00000000 00000000 +11111111 00000000 00000000 00000000 +11111111 00000000 00000000 00000000 +11111111 00000000 00000000 00000000 +11111111 00000000 00000000 00000000 \ No newline at end of file diff --git a/tests/images/pnm/bpp1-grayscale.raw.pbm b/tests/images/pnm/bpp1-grayscale.raw.pbm new file mode 100644 index 0000000000000000000000000000000000000000..8ebfe9486eaad71fb3a28851de9779b4afb9dfdc GIT binary patch literal 137 jcmWGA;W9Q-FgD`)PZ%%&mEgn-{}~wYVW3u^UfdV}`w~$z literal 0 HcmV?d00001 diff --git a/tests/images/pnm/bpp24-rgb.ascii.pnm b/tests/images/pnm/bpp24-rgb.ascii.pnm new file mode 100644 index 00000000..6e82e9bd --- /dev/null +++ b/tests/images/pnm/bpp24-rgb.ascii.pnm @@ -0,0 +1,3076 @@ +P3 +# Created by GIMP version 2.10.36 PNM plug-in +32 32 +255 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +0 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +0 +128 +128 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +192 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +128 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +1 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +0 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +255 +0 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +1 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 +255 diff --git a/tests/images/pnm/bpp24-rgb.raw.pnm b/tests/images/pnm/bpp24-rgb.raw.pnm new file mode 100644 index 0000000000000000000000000000000000000000..77c672944dc3320161baa5a3600bb37fb41b1b04 GIT binary patch literal 3131 zcmeH{Jqp4=5QQi0o?^h-pc~8uEW{#`D<}pDNR;>kc6+qkY+P8=$h^WLl{38R1-^xk zN9xkec-=SqdvoN&i#OY<=4aF2+DpeiUoP^Z#b;EbP)0X^t9VE#YCrrysRr%)Zp literal 0 HcmV?d00001 diff --git a/tests/images/pnm/bpp8-grayscale.ascii.pgm b/tests/images/pnm/bpp8-grayscale.ascii.pgm new file mode 100644 index 00000000..207de6e1 --- /dev/null +++ b/tests/images/pnm/bpp8-grayscale.ascii.pgm @@ -0,0 +1,1028 @@ +P2 +# Created by GIMP version 2.10.36 PNM plug-in +32 32 +255 +0 +0 +0 +0 +0 +0 +0 +0 +62 +62 +62 +62 +62 +62 +62 +62 +110 +110 +110 +110 +110 +110 +110 +110 +124 +124 +124 +124 +124 +124 +124 +124 +0 +0 +0 +0 +0 +0 +0 +0 +62 +62 +62 +62 +62 +62 +62 +62 +110 +110 +110 +110 +110 +110 +110 +110 +124 +124 +124 +124 +124 +124 +124 +124 +0 +0 +0 +0 +0 +0 +0 +0 +62 +62 +62 +62 +62 +62 +62 +62 +110 +110 +110 +110 +110 +110 +110 +110 +124 +124 +124 +124 +124 +124 +124 +124 +0 +0 +0 +0 +0 +0 +0 +0 +62 +62 +62 +62 +62 +62 +62 +62 +110 +110 +110 +110 +110 +110 +110 +110 +124 +124 +124 +124 +124 +124 +124 +124 +0 +0 +0 +0 +0 +0 +0 +0 +62 +62 +62 +62 +62 +62 +62 +62 +110 +110 +110 +110 +110 +110 +110 +110 +124 +124 +124 +124 +124 +124 +124 +124 +0 +0 +0 +0 +0 +0 +0 +0 +62 +62 +62 +62 +62 +62 +62 +62 +110 +110 +110 +110 +110 +110 +110 +110 +124 +124 +124 +124 +124 +124 +124 +124 +0 +0 +0 +0 +0 +0 +0 +0 +62 +62 +62 +62 +62 +62 +62 +62 +110 +110 +110 +110 +110 +110 +110 +110 +124 +124 +124 +124 +124 +124 +124 +124 +0 +0 +0 +0 +0 +0 +0 +0 +62 +62 +62 +62 +62 +62 +62 +62 +110 +110 +110 +110 +110 +110 +110 +110 +124 +124 +124 +124 +124 +124 +124 +124 +30 +30 +30 +30 +30 +30 +30 +30 +70 +70 +70 +70 +70 +70 +70 +70 +114 +114 +114 +114 +114 +114 +114 +114 +192 +192 +192 +192 +192 +192 +192 +192 +30 +30 +30 +30 +30 +30 +30 +30 +70 +70 +70 +70 +70 +70 +70 +70 +114 +114 +114 +114 +114 +114 +114 +114 +192 +192 +192 +192 +192 +192 +192 +192 +30 +30 +30 +30 +30 +30 +30 +30 +70 +70 +70 +70 +70 +70 +70 +70 +114 +114 +114 +114 +114 +114 +114 +114 +192 +192 +192 +192 +192 +192 +192 +192 +30 +30 +30 +30 +30 +30 +30 +30 +70 +70 +70 +70 +70 +70 +70 +70 +114 +114 +114 +114 +114 +114 +114 +114 +192 +192 +192 +192 +192 +192 +192 +192 +30 +30 +30 +30 +30 +30 +30 +30 +70 +70 +70 +70 +70 +70 +70 +70 +114 +114 +114 +114 +114 +114 +114 +114 +192 +192 +192 +192 +192 +192 +192 +192 +30 +30 +30 +30 +30 +30 +30 +30 +70 +70 +70 +70 +70 +70 +70 +70 +114 +114 +114 +114 +114 +114 +114 +114 +192 +192 +192 +192 +192 +192 +192 +192 +30 +30 +30 +30 +30 +30 +30 +30 +70 +70 +70 +70 +70 +70 +70 +70 +114 +114 +114 +114 +114 +114 +114 +114 +192 +192 +192 +192 +192 +192 +192 +192 +30 +30 +30 +30 +30 +30 +30 +30 +70 +70 +70 +70 +70 +70 +70 +70 +114 +114 +114 +114 +114 +114 +114 +114 +192 +192 +192 +192 +192 +192 +192 +192 +128 +128 +128 +128 +128 +128 +128 +128 +130 +130 +130 +130 +130 +130 +130 +130 +220 +220 +220 +220 +220 +220 +220 +220 +248 +248 +248 +248 +248 +248 +248 +248 +128 +128 +128 +128 +128 +128 +128 +128 +130 +130 +130 +130 +130 +130 +130 +130 +220 +220 +220 +220 +220 +220 +220 +220 +248 +248 +248 +248 +248 +248 +248 +248 +128 +128 +128 +128 +128 +128 +128 +128 +130 +130 +130 +130 +130 +130 +130 +130 +220 +220 +220 +220 +220 +220 +220 +220 +248 +248 +248 +248 +248 +248 +248 +248 +128 +128 +128 +128 +128 +128 +128 +128 +130 +130 +130 +130 +130 +130 +130 +130 +220 +220 +220 +220 +220 +220 +220 +220 +248 +248 +248 +248 +248 +248 +248 +248 +128 +128 +128 +128 +128 +128 +128 +128 +130 +130 +130 +130 +130 +130 +130 +130 +220 +220 +220 +220 +220 +220 +220 +220 +248 +248 +248 +248 +248 +248 +248 +248 +128 +128 +128 +128 +128 +128 +128 +128 +130 +130 +130 +130 +130 +130 +130 +130 +220 +220 +220 +220 +220 +220 +220 +220 +248 +248 +248 +248 +248 +248 +248 +248 +128 +128 +128 +128 +128 +128 +128 +128 +130 +130 +130 +130 +130 +130 +130 +130 +220 +220 +220 +220 +220 +220 +220 +220 +248 +248 +248 +248 +248 +248 +248 +248 +128 +128 +128 +128 +128 +128 +128 +128 +130 +130 +130 +130 +130 +130 +130 +130 +220 +220 +220 +220 +220 +220 +220 +220 +248 +248 +248 +248 +248 +248 +248 +248 +70 +70 +70 +70 +70 +70 +70 +70 +145 +145 +145 +145 +145 +145 +145 +145 +228 +228 +228 +228 +228 +228 +228 +228 +255 +255 +255 +255 +255 +255 +255 +255 +70 +70 +70 +70 +70 +70 +70 +70 +145 +145 +145 +145 +145 +145 +145 +145 +228 +228 +228 +228 +228 +228 +228 +228 +255 +255 +255 +255 +255 +255 +255 +255 +70 +70 +70 +70 +70 +70 +70 +70 +145 +145 +145 +145 +145 +145 +145 +145 +228 +228 +228 +228 +228 +228 +228 +228 +255 +255 +255 +255 +255 +255 +255 +255 +70 +70 +70 +70 +70 +70 +70 +70 +145 +145 +145 +145 +145 +145 +145 +145 +228 +228 +228 +228 +228 +228 +228 +228 +255 +255 +255 +255 +255 +255 +255 +255 +70 +70 +70 +70 +70 +70 +70 +70 +145 +145 +145 +145 +145 +145 +145 +145 +228 +228 +228 +228 +228 +228 +228 +228 +255 +255 +255 +255 +255 +255 +255 +255 +70 +70 +70 +70 +70 +70 +70 +70 +145 +145 +145 +145 +145 +145 +145 +145 +228 +228 +228 +228 +228 +228 +228 +228 +255 +255 +255 +255 +255 +255 +255 +255 +70 +70 +70 +70 +70 +70 +70 +70 +145 +145 +145 +145 +145 +145 +145 +145 +228 +228 +228 +228 +228 +228 +228 +228 +255 +255 +255 +255 +255 +255 +255 +255 +70 +70 +70 +70 +70 +70 +70 +70 +145 +145 +145 +145 +145 +145 +145 +145 +228 +228 +228 +228 +228 +228 +228 +228 +255 +255 +255 +255 +255 +255 +255 +255 diff --git a/tests/images/pnm/bpp8-grayscale.raw.pgm b/tests/images/pnm/bpp8-grayscale.raw.pgm new file mode 100644 index 0000000000000000000000000000000000000000..3dc480799fa1eb29b868c1e6718af93c049f0751 GIT binary patch literal 1083 zcmWGA9Vqw#1;bq)7Vi_G N;0YA`hl1fQ4*+?KBbopJ literal 0 HcmV?d00001 diff --git a/tests/images/test-images.h.in b/tests/images/test-images.h.in index 20092bc0..93b18856 100644 --- a/tests/images/test-images.h.in +++ b/tests/images/test-images.h.in @@ -58,6 +58,15 @@ static const char * const SAIL_TEST_IMAGES[] = { "@SAIL_TEST_IMAGES_PATH@/png/bpp4-indexed.comment.iccp.png", #endif +#ifdef SAIL_HAVE_BUILTIN_PNM + "@SAIL_TEST_IMAGES_PATH@/pnm/bpp1-grayscale.ascii.pbm", + "@SAIL_TEST_IMAGES_PATH@/pnm/bpp1-grayscale.raw.pbm", + "@SAIL_TEST_IMAGES_PATH@/pnm/bpp24-rgb.ascii.pnm", + "@SAIL_TEST_IMAGES_PATH@/pnm/bpp24-rgb.raw.pnm", + "@SAIL_TEST_IMAGES_PATH@/pnm/bpp8-grayscale.ascii.pgm", + "@SAIL_TEST_IMAGES_PATH@/pnm/bpp8-grayscale.raw.pgm", +#endif + #ifdef SAIL_HAVE_BUILTIN_PSD "@SAIL_TEST_IMAGES_PATH@/psd/bpp8-indexed.psd", "@SAIL_TEST_IMAGES_PATH@/psd/bpp24-rgb.psd", From c0ce34c0e20ba7917eddc5bb23718c9886805bd5 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshev Date: Thu, 16 Nov 2023 11:10:56 +0300 Subject: [PATCH 23/23] DOC: Added PNM --- FORMATS.md | 29 ++++++++++++++++++++++------- README.md | 13 +++++++------ 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/FORMATS.md b/FORMATS.md index fbd206a0..cfd4192b 100644 --- a/FORMATS.md +++ b/FORMATS.md @@ -239,6 +239,21 @@ 11 + PNM + + Grayscale: 1-bit, 8-bit, 16-bit. + Indexed: 1-bit, 8-bit. + RGB: 24-bit, 48-bit. +

+ Content: Static. + + - + Unsupported + - + - + + + 12 PSD Grayscale: 8-bit, 16-bit. @@ -265,7 +280,7 @@ - - 12 + 13 QOI RGB: 24-bit. @@ -284,7 +299,7 @@ - - 13 + 14 SVG Bit depth: 32-bit. @@ -303,7 +318,7 @@ resvg or nanosvg - 14 + 15 TGA Grayscale: 8-bit. @@ -319,7 +334,7 @@ - - 15 + 16 TIFF Bit depth: 1-bit, 2-bit, 4-bit, 8-bit, 16-bit, 24-bit, 32-bit, 48-bit, 64-bit. @@ -340,7 +355,7 @@ libtiff - 16 + 17 WAL Indexed: 8-bit. @@ -353,7 +368,7 @@ - - 17 + 18 WEBP Bit depth: 24-bit, 32-bit. @@ -366,7 +381,7 @@ libwebp - 18 + 19 XBM Bit depth: 1-bit. diff --git a/README.md b/README.md index 11f997c7..49ca0115 100644 --- a/README.md +++ b/README.md @@ -79,13 +79,14 @@ images with the help of [ksquirrel-libs](FAQ.md#how-old-is-sail), the predecesso | 8 | [JPEG XL](https://wikipedia.org/wiki/JPEG_XL) | R | libjxl | | 9 | [PCX](https://wikipedia.org/wiki/PCX) | R | | | 10 | [PNG](https://wikipedia.org/wiki/Portable_Network_Graphics) | RW | libpng | -| 11 | [PSD](https://en.wikipedia.org/wiki/Adobe_Photoshop#File_format) | R | | -| 12 | [QOI](http://qoiformat.org) | RW | | -| 13 | [SVG](https://wikipedia.org/wiki/Scalable_Vector_Graphics) | R | resvg | -| 14 | [TGA](https://wikipedia.org/wiki/Truevision_TGA) | R | | -| 15 | [TIFF](https://wikipedia.org/wiki/TIFF) | RW | libtiff | | .. | ... | | | -| 17 | [WEBP](https://wikipedia.org/wiki/WebP) | R | libwebp | +| 12 | [PSD](https://en.wikipedia.org/wiki/Adobe_Photoshop#File_format) | R | | +| 13 | [QOI](http://qoiformat.org) | RW | | +| 14 | [SVG](https://wikipedia.org/wiki/Scalable_Vector_Graphics) | R | resvg | +| 15 | [TGA](https://wikipedia.org/wiki/Truevision_TGA) | R | | +| 16 | [TIFF](https://wikipedia.org/wiki/TIFF) | RW | libtiff | +| .. | ... | | | +| 18 | [WEBP](https://wikipedia.org/wiki/WebP) | R | libwebp | | .. | ... | | | See the full list [here](FORMATS.md). Work to add more image formats is ongoing.