Selects an above decoder and runs it for each scan line of the file. * Returns 0 if there's an error or 1 if it's gravy. */
| 811 | * Returns 0 if there's an error or 1 if it's gravy. |
| 812 | */ |
| 813 | static int Decode(read_context * p_ctx) |
| 814 | { |
| 815 | void (* decoder)(uint8_t *, const uint8_t *, const uint8_t *, |
| 816 | const read_context *); |
| 817 | |
| 818 | uint8_t * p_out; /* Pointer to current scan line in output buffer. */ |
| 819 | uint8_t * p_out_end; /* End marker for output buffer. */ |
| 820 | uint8_t * p_line_end; /* Pointer to end of current scan line in output. */ |
| 821 | |
| 822 | /* out_inc is an incrementor for p_out to advance it one scan line. I'm |
| 823 | * not exactly sure what the correct type for it would be, perhaps ssize_t, |
| 824 | * but that's not C standard. I went with ptrdiff_t because its value |
| 825 | * will be equivalent to the difference between two pointers, whether it |
| 826 | * was derived that way or not. |
| 827 | */ |
| 828 | ptrdiff_t out_inc; |
| 829 | |
| 830 | /* Double check this won't overflow. Who knows, man. */ |
| 831 | #if SIZE_MAX > PTRDIFF_MAX |
| 832 | if(p_ctx->out_line_len > PTRDIFF_MAX) return 0; |
| 833 | #endif |
| 834 | out_inc = p_ctx->out_line_len; |
| 835 | |
| 836 | if(!(p_ctx->info.height < 0) == !(p_ctx->flags & BMPREAD_TOP_DOWN)) |
| 837 | { |
| 838 | /* We're keeping scan lines in order. These and subsequent operations |
| 839 | * have all been checked earlier. |
| 840 | */ |
| 841 | p_out = p_ctx->data_out; |
| 842 | p_out_end = p_ctx->data_out + |
| 843 | ((size_t)p_ctx->lines * p_ctx->out_line_len); |
| 844 | } |
| 845 | else /* We're reversing scan lines. */ |
| 846 | { |
| 847 | /* TODO: I'm not 100% sure about the legality, purely C spec-wise, of |
| 848 | * this subtraction. |
| 849 | */ |
| 850 | p_out_end = p_ctx->data_out - p_ctx->out_line_len; |
| 851 | p_out = p_ctx->data_out + |
| 852 | (((size_t)p_ctx->lines - 1) * p_ctx->out_line_len); |
| 853 | |
| 854 | /* Always safe, given two's complement, since it was positive. */ |
| 855 | out_inc = -out_inc; |
| 856 | } |
| 857 | |
| 858 | p_line_end = p_out + (size_t)p_ctx->info.width * p_ctx->out_channels; |
| 859 | |
| 860 | switch(p_ctx->info.bits) |
| 861 | { |
| 862 | case 32: decoder = Decode32; break; |
| 863 | case 24: decoder = Decode24; break; |
| 864 | case 16: decoder = Decode16; break; |
| 865 | case 8: decoder = Decode8; break; |
| 866 | case 4: decoder = Decode4; break; |
| 867 | case 1: decoder = Decode1; break; |
| 868 | default: return 0; |
| 869 | } |
| 870 |
no test coverage detected