comparison mupdf-source/thirdparty/zint/backend/pcx.c @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 /* pcx.c - Handles output to ZSoft PCX file */
2 /*
3 libzint - the open source barcode library
4 Copyright (C) 2009-2024 Robin Stuart <rstuart114@gmail.com>
5
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
8 are met:
9
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3. Neither the name of the project nor the names of its contributors
16 may be used to endorse or promote products derived from this software
17 without specific prior written permission.
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
23 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 SUCH DAMAGE.
30 */
31 /* SPDX-License-Identifier: BSD-3-Clause */
32
33 #include <errno.h>
34 #include <math.h>
35 #include <stdio.h>
36 #include "common.h"
37 #include "filemem.h"
38 #include "output.h"
39 #include "pcx.h" /* PCX header structure */
40
41 /* ZSoft PCX File Format Technical Reference Manual http://bespin.org/~qz/pc-gpe/pcx.txt */
42 INTERNAL int pcx_pixel_plot(struct zint_symbol *symbol, const unsigned char *pixelbuf) {
43 unsigned char fgred, fggrn, fgblu, fgalpha, bgred, bggrn, bgblu, bgalpha;
44 int row, column, i, colour;
45 int run_count;
46 struct filemem fm;
47 struct filemem *const fmp = &fm;
48 pcx_header_t header;
49 unsigned char previous;
50 const unsigned char *pb;
51 const int bytes_per_line = symbol->bitmap_width + (symbol->bitmap_width & 1); /* Must be even */
52 unsigned char *rle_row = (unsigned char *) z_alloca(bytes_per_line);
53
54 rle_row[bytes_per_line - 1] = 0; /* Will remain zero if bitmap_width odd */
55
56 (void) out_colour_get_rgb(symbol->fgcolour, &fgred, &fggrn, &fgblu, &fgalpha);
57 (void) out_colour_get_rgb(symbol->bgcolour, &bgred, &bggrn, &bgblu, &bgalpha);
58
59 header.manufacturer = 10; /* ZSoft */
60 header.version = 5; /* Version 3.0 */
61 header.encoding = 1; /* Run length encoding */
62 header.bits_per_pixel = 8; /* TODO: 1-bit monochrome black/white */
63 out_le_u16(header.window_xmin, 0);
64 out_le_u16(header.window_ymin, 0);
65 out_le_u16(header.window_xmax, symbol->bitmap_width - 1);
66 out_le_u16(header.window_ymax, symbol->bitmap_height - 1);
67 out_le_u16(header.horiz_dpi, symbol->dpmm ? roundf(stripf(symbol->dpmm * 25.4f)) : 300);
68 header.vert_dpi = header.horiz_dpi;
69
70 for (i = 0; i < 48; i++) {
71 header.colourmap[i] = 0x00;
72 }
73
74 header.reserved = 0;
75 header.number_of_planes = 3 + (fgalpha != 0xFF || bgalpha != 0xFF); /* TODO: 1-bit monochrome black/white */
76
77 out_le_u16(header.bytes_per_line, bytes_per_line);
78
79 out_le_u16(header.palette_info, 1); /* Colour */
80 out_le_u16(header.horiz_screen_size, 0);
81 out_le_u16(header.vert_screen_size, 0);
82
83 for (i = 0; i < 54; i++) {
84 header.filler[i] = 0x00;
85 }
86
87 /* Open output file in binary mode */
88 if (!fm_open(fmp, symbol, "wb")) {
89 return errtxtf(ZINT_ERROR_FILE_ACCESS, symbol, 621, "Could not open PCX output file (%1$d: %2$s)", fmp->err,
90 strerror(fmp->err));
91 }
92
93 fm_write(&header, sizeof(pcx_header_t), 1, fmp);
94
95 for (row = 0, pb = pixelbuf; row < symbol->bitmap_height; row++, pb += symbol->bitmap_width) {
96 for (colour = 0; colour < header.number_of_planes; colour++) {
97 for (column = 0; column < symbol->bitmap_width; column++) {
98 const unsigned char ch = pb[column];
99 switch (colour) {
100 case 0:
101 if (ch == '0' || ch == '1') {
102 rle_row[column] = ch != '0' ? fgred : bgred;
103 } else {
104 out_colour_char_to_rgb(ch, &rle_row[column], NULL, NULL);
105 }
106 break;
107 case 1:
108 if (ch == '0' || ch == '1') {
109 rle_row[column] = ch != '0' ? fggrn : bggrn;
110 } else {
111 out_colour_char_to_rgb(ch, NULL, &rle_row[column], NULL);
112 }
113 break;
114 case 2:
115 if (ch == '0' || ch == '1') {
116 rle_row[column] = ch != '0' ? fgblu : bgblu;
117 } else {
118 out_colour_char_to_rgb(ch, NULL, NULL, &rle_row[column]);
119 }
120 break;
121 case 3:
122 rle_row[column] = ch != '0' ? fgalpha : bgalpha;
123 break;
124 }
125 }
126
127 /* Based on ImageMagick/coders/pcx.c PCXWritePixels()
128 * Copyright 1999-2020 ImageMagick Studio LLC */
129 previous = rle_row[0];
130 run_count = 1;
131 for (column = 1; column < bytes_per_line; column++) { /* Note going up to bytes_per_line */
132 if ((previous == rle_row[column]) && (run_count < 63)) {
133 run_count++;
134 } else {
135 if (run_count > 1 || (previous & 0xc0) == 0xc0) {
136 run_count += 0xc0;
137 fm_putc(run_count, fmp);
138 }
139 fm_putc(previous, fmp);
140 previous = rle_row[column];
141 run_count = 1;
142 }
143 }
144
145 if (run_count > 1 || (previous & 0xc0) == 0xc0) {
146 run_count += 0xc0;
147 fm_putc(run_count, fmp);
148 }
149 fm_putc(previous, fmp);
150 }
151 }
152
153 if (fm_error(fmp)) {
154 errtxtf(0, symbol, 622, "Incomplete write of PCX output (%1$d: %2$s)", fmp->err, strerror(fmp->err));
155 (void) fm_close(fmp, symbol);
156 return ZINT_ERROR_FILE_WRITE;
157 }
158
159 if (!fm_close(fmp, symbol)) {
160 return errtxtf(ZINT_ERROR_FILE_WRITE, symbol, 624, "Failure on closing PCX output file (%1$d: %2$s)",
161 fmp->err, strerror(fmp->err));
162 }
163
164 return 0;
165 }
166
167 /* vim: set ts=4 sw=4 et : */