├── Code128_CPlusPlus.sdf ├── Code128_CPlusPlus ├── test.bmp ├── C128_Defines.h ├── makefile ├── Main.cpp ├── Code128_CPlusPlus.vcxproj.filters ├── Code128_CPlusPlus.vcxproj ├── bmpfile.h ├── bmpfile.cpp └── C128.h ├── README.md ├── .github └── workflows │ └── c-cpp.yml ├── .gitignore ├── Code128_CPlusPlus.sln └── LICENSE /Code128_CPlusPlus.sdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barnhill/Code128_CPP/HEAD/Code128_CPlusPlus.sdf -------------------------------------------------------------------------------- /Code128_CPlusPlus/test.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barnhill/Code128_CPP/HEAD/Code128_CPlusPlus/test.bmp -------------------------------------------------------------------------------- /Code128_CPlusPlus/C128_Defines.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barnhill/Code128_CPP/HEAD/Code128_CPlusPlus/C128_Defines.h -------------------------------------------------------------------------------- /Code128_CPlusPlus/makefile: -------------------------------------------------------------------------------- 1 | barcode-make: Main.cpp bmpfile.cpp bmpfile.h C128.h C128_Defines.h 2 | g++ Main.cpp bmpfile.cpp bmpfile.h C128.h C128_Defines.h 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Code128_CPP ![Code128 CI](https://github.com/barnhill/Code128_CPP/workflows/C/C++%20CI/badge.svg) 2 | Code 128 barcode image generation library in C++ 3 | -------------------------------------------------------------------------------- /.github/workflows/c-cpp.yml: -------------------------------------------------------------------------------- 1 | name: C/C++ CI 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: make 17 | run: cd Code128_CPlusPlus && make 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | Debug/ 3 | *.slo 4 | *.lo 5 | *.o 6 | *.obj 7 | 8 | # Precompiled Headers 9 | *.gch 10 | *.pch 11 | 12 | # Compiled Dynamic libraries 13 | *.so 14 | *.dylib 15 | *.dll 16 | 17 | # Fortran module files 18 | *.mod 19 | 20 | # Compiled Static libraries 21 | *.lai 22 | *.la 23 | *.a 24 | *.lib 25 | 26 | # Executables 27 | *.exe 28 | *.out 29 | *.app 30 | -------------------------------------------------------------------------------- /Code128_CPlusPlus/Main.cpp: -------------------------------------------------------------------------------- 1 | #include "C128.h" 2 | #include 3 | using namespace std; 4 | 5 | int main(int argc, char **argv) 6 | { 7 | if (argc != 4) 8 | { 9 | printf("Usage: %s barWidthInPx heightInPx filename\n", argv[0]); 10 | return 1; 11 | } 12 | 13 | printf("Code 128 Test Util\n"); 14 | printf("==================\n"); 15 | 16 | Code128 code128("038000356216", DYNAMIC); 17 | printf("Barcode object created\n"); 18 | 19 | code128.writeImage(atoi(argv[1]), atoi(argv[2]), argv[3]); 20 | printf("File write complete.\n"); 21 | } -------------------------------------------------------------------------------- /Code128_CPlusPlus.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Code128_CPlusPlus", "Code128_CPlusPlus\Code128_CPlusPlus.vcxproj", "{8B5C62D9-9BC5-41F8-9859-B64C27D26A53}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {8B5C62D9-9BC5-41F8-9859-B64C27D26A53}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {8B5C62D9-9BC5-41F8-9859-B64C27D26A53}.Debug|Win32.Build.0 = Debug|Win32 14 | {8B5C62D9-9BC5-41F8-9859-B64C27D26A53}.Release|Win32.ActiveCfg = Release|Win32 15 | {8B5C62D9-9BC5-41F8-9859-B64C27D26A53}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /Code128_CPlusPlus/Code128_CPlusPlus.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | 29 | 30 | Source Files 31 | 32 | 33 | Source Files 34 | 35 | 36 | -------------------------------------------------------------------------------- /Code128_CPlusPlus/Code128_CPlusPlus.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {8B5C62D9-9BC5-41F8-9859-B64C27D26A53} 15 | Win32Proj 16 | ConsoleApplication1 17 | Code128_CPlusPlus 18 | 19 | 20 | 21 | Application 22 | true 23 | v110 24 | Unicode 25 | 26 | 27 | Application 28 | false 29 | v110 30 | true 31 | Unicode 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | true 45 | 46 | 47 | false 48 | 49 | 50 | 51 | 52 | 53 | Level3 54 | Disabled 55 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 56 | 57 | 58 | Console 59 | true 60 | 61 | 62 | 63 | 64 | Level3 65 | 66 | 67 | MaxSpeed 68 | true 69 | true 70 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 71 | 72 | 73 | Console 74 | true 75 | true 76 | true 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /Code128_CPlusPlus/bmpfile.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file bmpfile.h 3 | * @brief The BMP library header 4 | * 5 | * libbmp - BMP library 6 | * Copyright (C) 2009 lidaibin(超越无限) 7 | * mail: lidaibin@gmail.com 8 | * 9 | * This library is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU Lesser General Public 11 | * License as published by the Free Software Foundation; either 12 | * version 2 of the License, or (at your option) any later version. 13 | * 14 | * This library is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | * Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public 20 | * License along with this library; if not, write to the 21 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 22 | * Boston, MA 02111-1307, USA. 23 | * 24 | * $Id$ 25 | */ 26 | 27 | #ifndef __bmpfile_h__ 28 | #define __bmpfile_h__ 29 | 30 | #ifdef __cplusplus 31 | #define BMP_BEGIN_DECLS extern "C" { 32 | #define BMP_END_DECLS } 33 | #else 34 | #define BMP_BEGIN_DECLS 35 | #define BMP_END_DECLS 36 | #endif 37 | 38 | BMP_BEGIN_DECLS 39 | 40 | //#ifndef bool 41 | //typedef int bool; 42 | #define FALSE (0) 43 | #define TRUE !FALSE 44 | //#endif 45 | 46 | #ifndef uint8_t 47 | typedef unsigned char uint8_t; 48 | #endif 49 | 50 | #ifndef uint16_t 51 | typedef unsigned short uint16_t; 52 | #endif 53 | 54 | #ifndef uint32_t 55 | typedef unsigned int uint32_t; 56 | #endif 57 | 58 | typedef enum { 59 | BI_RGB = 0, 60 | BI_RLE8, 61 | BI_RLE4, 62 | BI_BITFIELDS, 63 | BI_JPEG, 64 | BI_PNG, 65 | } bmp_compression_method_t; 66 | 67 | typedef struct { 68 | uint8_t blue; 69 | uint8_t green; 70 | uint8_t red; 71 | uint8_t alpha; 72 | } rgb_pixel_t; 73 | 74 | typedef struct { 75 | uint8_t magic[2]; /* the magic number used to identify the BMP file: 76 | 0x42 0x4D (Hex code points for B and M). 77 | The following entries are possible: 78 | BM - Windows 3.1x, 95, NT, ... etc 79 | BA - OS/2 Bitmap Array 80 | CI - OS/2 Color Icon 81 | CP - OS/2 Color Pointer 82 | IC - OS/2 Icon 83 | PT - OS/2 Pointer. */ 84 | uint32_t filesz; /* the size of the BMP file in bytes */ 85 | uint16_t creator1; /* reserved. */ 86 | uint16_t creator2; /* reserved. */ 87 | uint32_t offset; /* the offset, i.e. starting address, 88 | of the byte where the bitmap data can be found. */ 89 | } bmp_header_t; 90 | 91 | typedef struct { 92 | uint32_t header_sz; /* the size of this header (40 bytes) */ 93 | uint32_t width; /* the bitmap width in pixels */ 94 | uint32_t height; /* the bitmap height in pixels */ 95 | uint16_t nplanes; /* the number of color planes being used. 96 | Must be set to 1. */ 97 | uint16_t depth; /* the number of bits per pixel, 98 | which is the color depth of the image. 99 | Typical values are 1, 4, 8, 16, 24 and 32. */ 100 | uint32_t compress_type; /* the compression method being used. 101 | See also bmp_compression_method_t. */ 102 | uint32_t bmp_bytesz; /* the image size. This is the size of the raw bitmap 103 | data (see below), and should not be confused 104 | with the file size. */ 105 | uint32_t hres; /* the horizontal resolution of the image. 106 | (pixel per meter) */ 107 | uint32_t vres; /* the vertical resolution of the image. 108 | (pixel per meter) */ 109 | uint32_t ncolors; /* the number of colors in the color palette, 110 | or 0 to default to 2n. */ 111 | uint32_t nimpcolors; /* the number of important colors used, 112 | or 0 when every color is important; 113 | generally ignored. */ 114 | } bmp_dib_v3_header_t; 115 | 116 | typedef struct _bmpfile bmpfile_t; 117 | 118 | bmpfile_t *bmp_create(uint32_t width, uint32_t height, uint32_t depth); 119 | /* TODO */ 120 | /* bmpfile_t *bmp_create_from_file(const char *filename); */ 121 | void bmp_destroy(bmpfile_t *bmp); 122 | 123 | bmp_header_t bmp_get_header(bmpfile_t *bmp); 124 | bmp_dib_v3_header_t bmp_get_dib(bmpfile_t *bmp); 125 | 126 | uint32_t bmp_get_width(bmpfile_t *bmp); 127 | uint32_t bmp_get_height(bmpfile_t *bmp); 128 | uint32_t bmp_get_depth(bmpfile_t *bmp); 129 | 130 | uint32_t bmp_get_dpi_x(bmpfile_t *bmp); 131 | uint32_t bmp_get_dpi_y(bmpfile_t *bmp); 132 | void bmp_set_dpi(bmpfile_t *bmp, uint32_t x, uint32_t y); 133 | 134 | rgb_pixel_t *bmp_get_pixel(bmpfile_t *bmp, uint32_t x, uint32_t y); 135 | int bmp_set_pixel(bmpfile_t *bmp, uint32_t x, uint32_t y, rgb_pixel_t pixel); 136 | 137 | int bmp_save(bmpfile_t *bmp, const char *filename); 138 | 139 | BMP_END_DECLS 140 | 141 | #endif /* __bmpfile_h__ */ 142 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Code128_CPlusPlus/bmpfile.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file bmpfile.cpp 3 | * @brief The BMP library implementation 4 | * 5 | * libbmp - BMP library 6 | * Copyright (C) 2009 lidaibin(超越无限) 7 | * mail: lidaibin@gmail.com 8 | * 9 | * This library is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU Lesser General Public 11 | * License as published by the Free Software Foundation; either 12 | * version 2 of the License, or (at your option) any later version. 13 | * 14 | * This library is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | * Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public 20 | * License along with this library; if not, write to the 21 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 22 | * Boston, MA 02111-1307, USA. 23 | * 24 | * $Id$ 25 | */ 26 | 27 | 28 | /* 29 | * BMP File Header Stores general information about the BMP file. 30 | * DIB header Stores detailed information about the bitmap image. 31 | * Color Palette Stores the definition of the colors being used for 32 | * indexed color bitmaps. 33 | * Bitmap Data Stores the actual image, pixel by pixel. 34 | */ 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | #include "bmpfile.h" 42 | 43 | #define DEFAULT_DPI_X 3780 44 | #define DEFAULT_DPI_Y 3780 45 | #define DPI_FACTOR 39.37007874015748 46 | 47 | struct _bmpfile { 48 | bmp_header_t header; 49 | bmp_dib_v3_header_t dib; 50 | 51 | rgb_pixel_t **pixels; 52 | rgb_pixel_t *colors; 53 | }; 54 | 55 | static uint32_t 56 | uint32_pow(uint32_t base, uint32_t depth) 57 | { 58 | uint32_t i, result = 1; 59 | 60 | for (i = 0; i < depth; ++i) 61 | result *= base; 62 | 63 | return result; 64 | } 65 | 66 | /** 67 | * Create the standard color table for BMP object 68 | */ 69 | static void 70 | bmp_create_standard_color_table(bmpfile_t *bmp) 71 | { 72 | int i, j, k, ell; 73 | 74 | switch (bmp->dib.depth) { 75 | case 1: 76 | for (i = 0; i < 2; ++i) { 77 | bmp->colors[i].red = i * 255; 78 | bmp->colors[i].green = i * 255; 79 | bmp->colors[i].blue = i * 255; 80 | bmp->colors[i].alpha = 0; 81 | } 82 | break; 83 | 84 | case 4: 85 | i = 0; 86 | for (ell = 0; ell < 2; ++ell) { 87 | for (k = 0; k < 2; ++k) { 88 | for (j = 0; j < 2; ++j) { 89 | bmp->colors[i].red = j * 128; 90 | bmp->colors[i].green = k * 128; 91 | bmp->colors[i].blue = ell * 128; 92 | bmp->colors[i].alpha = 0; 93 | ++i; 94 | } 95 | } 96 | } 97 | 98 | for (ell = 0; ell < 2; ++ell) { 99 | for (k = 0; k < 2; ++k) { 100 | for (j = 0; j < 2; ++j) { 101 | bmp->colors[i].red = j * 255; 102 | bmp->colors[i].green = k * 255; 103 | bmp->colors[i].blue = ell * 255; 104 | bmp->colors[i].alpha = 0; 105 | ++i; 106 | } 107 | } 108 | } 109 | 110 | i = 8; 111 | bmp->colors[i].red = 192; 112 | bmp->colors[i].green = 192; 113 | bmp->colors[i].blue = 192; 114 | bmp->colors[i].alpha = 0; 115 | 116 | break; 117 | 118 | case 8: 119 | i = 0; 120 | for (ell = 0; ell < 4; ++ell) { 121 | for (k = 0; k < 8; ++k) { 122 | for (j = 0; j < 8; ++j) { 123 | bmp->colors[i].red = j * 32; 124 | bmp->colors[i].green = k * 32; 125 | bmp->colors[i].blue = ell * 64; 126 | bmp->colors[i].alpha = 0; 127 | ++i; 128 | } 129 | } 130 | } 131 | 132 | i = 0; 133 | for (ell = 0; ell < 2; ++ell) { 134 | for (k = 0; k < 2; ++k) { 135 | for (j = 0; j < 2; ++j) { 136 | bmp->colors[i].red = j * 128; 137 | bmp->colors[i].green = k * 128; 138 | bmp->colors[i].blue = ell * 128; 139 | ++i; 140 | } 141 | } 142 | } 143 | 144 | // overwrite colors 7, 8, 9 145 | i = 7; 146 | bmp->colors[i].red = 192; 147 | bmp->colors[i].green = 192; 148 | bmp->colors[i].blue = 192; 149 | i++; // 8 150 | bmp->colors[i].red = 192; 151 | bmp->colors[i].green = 220; 152 | bmp->colors[i].blue = 192; 153 | i++; // 9 154 | bmp->colors[i].red = 166; 155 | bmp->colors[i].green = 202; 156 | bmp->colors[i].blue = 240; 157 | 158 | // overwrite colors 246 to 255 159 | i = 246; 160 | bmp->colors[i].red = 255; 161 | bmp->colors[i].green = 251; 162 | bmp->colors[i].blue = 240; 163 | i++; // 247 164 | bmp->colors[i].red = 160; 165 | bmp->colors[i].green = 160; 166 | bmp->colors[i].blue = 164; 167 | i++; // 248 168 | bmp->colors[i].red = 128; 169 | bmp->colors[i].green = 128; 170 | bmp->colors[i].blue = 128; 171 | i++; // 249 172 | bmp->colors[i].red = 255; 173 | bmp->colors[i].green = 0; 174 | bmp->colors[i].blue = 0; 175 | i++; // 250 176 | bmp->colors[i].red = 0; 177 | bmp->colors[i].green = 255; 178 | bmp->colors[i].blue = 0; 179 | i++; // 251 180 | bmp->colors[i].red = 255; 181 | bmp->colors[i].green = 255; 182 | bmp->colors[i].blue = 0; 183 | i++; // 252 184 | bmp->colors[i].red = 0; 185 | bmp->colors[i].green = 0; 186 | bmp->colors[i].blue = 255; 187 | i++; // 253 188 | bmp->colors[i].red = 255; 189 | bmp->colors[i].green = 0; 190 | bmp->colors[i].blue = 255; 191 | i++; // 254 192 | bmp->colors[i].red = 0; 193 | bmp->colors[i].green = 255; 194 | bmp->colors[i].blue = 255; 195 | i++; // 255 196 | bmp->colors[i].red = 255; 197 | bmp->colors[i].green = 255; 198 | bmp->colors[i].blue = 255; 199 | break; 200 | } 201 | } 202 | 203 | /** 204 | * Create grayscale color table for BMP object 205 | */ 206 | static void 207 | bmp_create_grayscale_color_table(bmpfile_t *bmp) 208 | { 209 | unsigned int i; 210 | uint8_t step_size; 211 | 212 | if (!bmp->colors) return; 213 | 214 | if (bmp->dib.depth != 1) 215 | step_size = 255 / (bmp->dib.ncolors - 1); 216 | else 217 | step_size = 255; 218 | 219 | for (i = 0; i < bmp->dib.ncolors; ++i) { 220 | uint8_t value = i * step_size; 221 | rgb_pixel_t color = {value, value, value, 0}; 222 | bmp->colors[i] = color; 223 | } 224 | } 225 | 226 | /** 227 | * Malloc the memory for color palette 228 | */ 229 | static void 230 | bmp_malloc_colors(bmpfile_t *bmp) 231 | { 232 | bmp->dib.ncolors = uint32_pow(2, bmp->dib.depth); 233 | if (bmp->dib.depth == 1 || bmp->dib.depth == 4 || bmp->dib.depth == 8) { 234 | bmp->colors = (rgb_pixel_t *)malloc(sizeof(rgb_pixel_t) * bmp->dib.ncolors); 235 | bmp_create_standard_color_table(bmp); 236 | } 237 | } 238 | 239 | /** 240 | * Free the memory of color palette 241 | */ 242 | static void 243 | bmp_free_colors(bmpfile_t *bmp) 244 | { 245 | if (bmp->colors) 246 | free(bmp->colors); 247 | } 248 | 249 | /** 250 | * Malloc the memory for pixels 251 | */ 252 | static void 253 | bmp_malloc_pixels(bmpfile_t *bmp) 254 | { 255 | unsigned int i, j; 256 | 257 | bmp->pixels = (rgb_pixel_t **)malloc(sizeof(rgb_pixel_t *) * bmp->dib.width); 258 | for (i = 0; i < bmp->dib.width; ++i) { 259 | bmp->pixels[i] = (rgb_pixel_t *)malloc(sizeof(rgb_pixel_t) * bmp->dib.height); 260 | for (j = 0; j < bmp->dib.height; ++j) { 261 | bmp->pixels[i][j].red = 255; 262 | bmp->pixels[i][j].green = 255; 263 | bmp->pixels[i][j].blue = 255; 264 | bmp->pixels[i][j].alpha = 0; 265 | } 266 | } 267 | } 268 | 269 | /** 270 | * Free the memory of pixels 271 | */ 272 | static void 273 | bmp_free_pixels(bmpfile_t *bmp) 274 | { 275 | unsigned int i; 276 | 277 | for (i = 0; i < bmp->dib.width; ++i) 278 | free(bmp->pixels[i]); 279 | 280 | free(bmp->pixels), bmp->pixels = NULL; 281 | } 282 | 283 | /** 284 | * Create the BMP object with specified width and height and depth. 285 | */ 286 | bmpfile_t * 287 | bmp_create(uint32_t width, uint32_t height, uint32_t depth) 288 | { 289 | bmpfile_t *result; 290 | double bytes_per_pixel; 291 | uint32_t bytes_per_line; 292 | uint32_t palette_size; 293 | 294 | if (depth != 1 && depth != 4 && depth != 8 && depth != 16 && depth != 24 && 295 | depth != 32) 296 | return NULL; 297 | 298 | result = (bmpfile_t *)malloc(sizeof(bmpfile_t)); 299 | 300 | memset(result, 0, sizeof(bmpfile_t)); 301 | 302 | result->header.magic[0] = 'B'; 303 | result->header.magic[1] = 'M'; 304 | 305 | result->dib.header_sz = 40; 306 | result->dib.width = width; 307 | result->dib.height = height; 308 | result->dib.nplanes = 1; 309 | result->dib.depth = depth; 310 | result->dib.hres = DEFAULT_DPI_X; 311 | result->dib.vres = DEFAULT_DPI_Y; 312 | 313 | if (depth == 16) 314 | result->dib.compress_type = BI_BITFIELDS; 315 | else 316 | result->dib.compress_type = BI_RGB; 317 | 318 | bmp_malloc_pixels(result); 319 | bmp_malloc_colors(result); 320 | 321 | /* Calculate the field value of header and DIB */ 322 | bytes_per_pixel = (result->dib.depth * 1.0) / 8.0; 323 | bytes_per_line = (int)ceil(bytes_per_pixel * result->dib.width); 324 | if (bytes_per_line % 4 != 0) 325 | bytes_per_line += 4 - bytes_per_line % 4; 326 | 327 | result->dib.bmp_bytesz = bytes_per_line * result->dib.height; 328 | 329 | palette_size = 0; 330 | if (depth == 1 || depth == 4 || depth == 8) 331 | palette_size = uint32_pow(2, result->dib.depth) * 4; 332 | else if (result->dib.depth == 16) 333 | palette_size = 3 * 4; 334 | 335 | result->header.offset = 14 + result->dib.header_sz + palette_size; 336 | result->header.filesz = result->header.offset + result->dib.bmp_bytesz; 337 | 338 | return result; 339 | } 340 | 341 | void 342 | bmp_destroy(bmpfile_t *bmp) 343 | { 344 | bmp_free_pixels(bmp); 345 | bmp_free_colors(bmp); 346 | free(bmp); 347 | } 348 | 349 | uint32_t 350 | bmp_get_width(bmpfile_t *bmp) 351 | { 352 | return bmp->dib.width; 353 | } 354 | 355 | uint32_t 356 | bmp_get_height(bmpfile_t *bmp) 357 | { 358 | return bmp->dib.height; 359 | } 360 | 361 | uint32_t 362 | bmp_get_depth(bmpfile_t *bmp) 363 | { 364 | return bmp->dib.depth; 365 | } 366 | 367 | bmp_header_t 368 | bmp_get_header(bmpfile_t *bmp) 369 | { 370 | return bmp->header; 371 | } 372 | 373 | bmp_dib_v3_header_t 374 | bmp_get_dib(bmpfile_t *bmp) 375 | { 376 | return bmp->dib; 377 | } 378 | 379 | uint32_t 380 | bmp_get_dpi_x(bmpfile_t *bmp) 381 | { 382 | return (uint32_t)(bmp->dib.hres / DPI_FACTOR); 383 | } 384 | 385 | uint32_t 386 | bmp_get_dpi_y(bmpfile_t *bmp) 387 | { 388 | return (uint32_t)(bmp->dib.vres / DPI_FACTOR); 389 | } 390 | 391 | void 392 | bmp_set_dpi(bmpfile_t *bmp, uint32_t x, uint32_t y) 393 | { 394 | bmp->dib.hres = (uint32_t)(x * DPI_FACTOR); 395 | bmp->dib.vres = (uint32_t)(y * DPI_FACTOR); 396 | } 397 | 398 | rgb_pixel_t * 399 | bmp_get_pixel(bmpfile_t *bmp, uint32_t x, uint32_t y) 400 | { 401 | if ((x >= bmp->dib.width) || (y >= bmp->dib.height)) 402 | return NULL; 403 | 404 | return &(bmp->pixels[x][y]); 405 | } 406 | 407 | int 408 | bmp_set_pixel(bmpfile_t *bmp, uint32_t x, uint32_t y, rgb_pixel_t pixel) 409 | { 410 | if ((x >= bmp->dib.width) || (y >= bmp->dib.height)) 411 | return FALSE; 412 | 413 | bmp->pixels[x][y] = pixel; 414 | return TRUE; 415 | } 416 | 417 | static int 418 | _is_big_endian(void) 419 | { 420 | uint16_t value = 0x0001; 421 | 422 | return (*(uint8_t *)&value) != 0x01; 423 | } 424 | 425 | #define UINT16_SWAP_LE_BE_CONSTANT(val) \ 426 | ((uint16_t) \ 427 | ( \ 428 | (uint16_t) ((uint16_t) (val) >> 8) | \ 429 | (uint16_t) ((uint16_t) (val) << 8))) 430 | 431 | #define UINT32_SWAP_LE_BE_CONSTANT(val) \ 432 | ((uint32_t) \ 433 | ( \ 434 | (((uint32_t) (val) & (uint32_t) 0x000000ffU) << 24) | \ 435 | (((uint32_t) (val) & (uint32_t) 0x0000ff00U) << 8) | \ 436 | (((uint32_t) (val) & (uint32_t) 0x00ff0000U) >> 8) | \ 437 | (((uint32_t) (val) & (uint32_t) 0xff000000U) >> 24))) 438 | 439 | static void 440 | bmp_header_swap_endianess(bmp_header_t *header) 441 | { 442 | header->filesz = UINT32_SWAP_LE_BE_CONSTANT(header->filesz); 443 | header->creator1 = UINT16_SWAP_LE_BE_CONSTANT(header->creator1); 444 | header->creator2 = UINT16_SWAP_LE_BE_CONSTANT(header->creator2); 445 | header->offset = UINT32_SWAP_LE_BE_CONSTANT(header->offset); 446 | } 447 | 448 | static void 449 | bmp_dib_v3_header_swap_endianess(bmp_dib_v3_header_t *dib) 450 | { 451 | dib->header_sz = UINT32_SWAP_LE_BE_CONSTANT(dib->header_sz); 452 | dib->width = UINT32_SWAP_LE_BE_CONSTANT(dib->width); 453 | dib->height = UINT32_SWAP_LE_BE_CONSTANT(dib->height); 454 | dib->nplanes = UINT16_SWAP_LE_BE_CONSTANT(dib->nplanes); 455 | dib->depth = UINT16_SWAP_LE_BE_CONSTANT(dib->depth); 456 | dib->compress_type = UINT32_SWAP_LE_BE_CONSTANT(dib->compress_type); 457 | dib->bmp_bytesz = UINT32_SWAP_LE_BE_CONSTANT(dib->bmp_bytesz); 458 | dib->hres = UINT32_SWAP_LE_BE_CONSTANT(dib->hres); 459 | dib->vres = UINT32_SWAP_LE_BE_CONSTANT(dib->vres); 460 | dib->ncolors = UINT32_SWAP_LE_BE_CONSTANT(dib->ncolors); 461 | dib->nimpcolors = UINT32_SWAP_LE_BE_CONSTANT(dib->nimpcolors); 462 | } 463 | 464 | static void 465 | bmp_write_header(bmpfile_t *bmp, FILE *fp) 466 | { 467 | bmp_header_t header = bmp->header; 468 | 469 | if (_is_big_endian()) bmp_header_swap_endianess(&header); 470 | 471 | fwrite(header.magic, sizeof(header.magic), 1, fp); 472 | fwrite(&(header.filesz), sizeof(uint32_t), 1, fp); 473 | fwrite(&(header.creator1), sizeof(uint16_t), 1, fp); 474 | fwrite(&(header.creator2), sizeof(uint16_t), 1, fp); 475 | fwrite(&(header.offset), sizeof(uint32_t), 1, fp); 476 | } 477 | 478 | static void 479 | bmp_write_dib(bmpfile_t *bmp, FILE *fp) 480 | { 481 | bmp_dib_v3_header_t dib = bmp->dib; 482 | 483 | if (_is_big_endian()) bmp_dib_v3_header_swap_endianess(&dib); 484 | 485 | fwrite(&(dib.header_sz), sizeof(uint32_t), 1, fp); 486 | fwrite(&(dib.width), sizeof(uint32_t), 1, fp); 487 | fwrite(&(dib.height), sizeof(uint32_t), 1, fp); 488 | fwrite(&(dib.nplanes), sizeof(uint16_t), 1, fp); 489 | fwrite(&(dib.depth), sizeof(uint16_t), 1, fp); 490 | fwrite(&(dib.compress_type), sizeof(uint32_t), 1, fp); 491 | fwrite(&(dib.bmp_bytesz), sizeof(uint32_t), 1, fp); 492 | fwrite(&(dib.hres), sizeof(uint32_t), 1, fp); 493 | fwrite(&(dib.vres), sizeof(uint32_t), 1, fp); 494 | fwrite(&(dib.ncolors), sizeof(uint32_t), 1, fp); 495 | fwrite(&(dib.nimpcolors), sizeof(uint32_t), 1, fp); 496 | } 497 | 498 | static void 499 | bmp_write_palette(bmpfile_t *bmp, FILE *fp) 500 | { 501 | if (bmp->dib.depth == 1 || bmp->dib.depth == 4 || bmp->dib.depth == 8) { 502 | unsigned int i; 503 | for (i = 0; i < bmp->dib.ncolors; ++i) 504 | fwrite(&(bmp->colors[i]), sizeof(rgb_pixel_t), 1, fp); 505 | } 506 | else if (bmp->dib.depth == 16) { /* the bit masks, not palette */ 507 | uint16_t red_mask = 63488; /* bits 1-5 */ 508 | uint16_t green_mask = 2016; /* bits 6-11 */ 509 | uint16_t blue_mask = 31; /* bits 12-16 */ 510 | uint16_t zero_word = 0; 511 | 512 | if (_is_big_endian()) { 513 | red_mask = UINT16_SWAP_LE_BE_CONSTANT(red_mask); 514 | green_mask = UINT16_SWAP_LE_BE_CONSTANT(green_mask); 515 | blue_mask = UINT16_SWAP_LE_BE_CONSTANT(blue_mask); 516 | } 517 | 518 | fwrite(&red_mask, sizeof(uint16_t), 1, fp); 519 | fwrite(&zero_word, sizeof(uint16_t), 1, fp); 520 | 521 | fwrite(&green_mask, sizeof(uint16_t), 1, fp); 522 | fwrite(&zero_word, sizeof(uint16_t), 1, fp); 523 | 524 | fwrite(&blue_mask, sizeof(uint16_t), 1, fp); 525 | fwrite(&zero_word, sizeof(uint16_t), 1, fp); 526 | } 527 | } 528 | 529 | #define INT_SQUARE(v) ((int)((v) * (v))) 530 | 531 | static int 532 | find_closest_color(bmpfile_t *bmp, rgb_pixel_t pixel) 533 | { 534 | unsigned int i, best = 0; 535 | int best_match = 999999; 536 | 537 | for (i = 0; i < bmp->dib.ncolors; ++i) { 538 | rgb_pixel_t color = bmp->colors[i]; 539 | int temp_match = INT_SQUARE(color.red - pixel.red) + 540 | INT_SQUARE(color.green - pixel.green) + 541 | INT_SQUARE(color.blue - pixel.blue); 542 | 543 | if (temp_match < best_match) { 544 | best = i; 545 | best_match = temp_match; 546 | } 547 | 548 | if (best_match < 1) 549 | break; 550 | } 551 | 552 | return best; 553 | } 554 | 555 | static void 556 | bmp_get_row_data_for_1(bmpfile_t *bmp, unsigned char *buf, size_t buf_len, 557 | uint32_t row) 558 | { 559 | uint8_t pos_weights[8] = {128, 64, 32, 16, 8, 4, 2, 1}; 560 | uint32_t i = 0, j, k = 0; 561 | uint32_t index; 562 | 563 | if (bmp->dib.width > 8 * buf_len) return; 564 | 565 | while (i < bmp->dib.width) { 566 | for (j = 0, index = 0; j < 8 && i < bmp->dib.width; ++i, ++j) 567 | index += pos_weights[j] * find_closest_color(bmp, bmp->pixels[i][row]); 568 | 569 | buf[k++] = index & 0xff; 570 | } 571 | } 572 | 573 | static void 574 | bmp_get_row_data_for_4(bmpfile_t *bmp, unsigned char *buf, size_t buf_len, 575 | uint32_t row) 576 | { 577 | uint8_t pos_weights[2] = {16, 1}; 578 | uint32_t i = 0, j, k = 0; 579 | uint32_t index; 580 | 581 | if (bmp->dib.width > 2 * buf_len) return; 582 | 583 | while (i < bmp->dib.width) { 584 | for (j = 0, index = 0; j < 2 && i < bmp->dib.width; ++i, ++j) 585 | index += pos_weights[j] * find_closest_color(bmp, bmp->pixels[i][row]); 586 | 587 | buf[k++] = index & 0xff; 588 | } 589 | } 590 | 591 | static void 592 | bmp_get_row_data_for_8(bmpfile_t *bmp, unsigned char *buf, size_t buf_len, 593 | uint32_t row) 594 | { 595 | unsigned int i; 596 | 597 | if (bmp->dib.width > buf_len) return; 598 | 599 | for (i = 0; i < bmp->dib.width; ++i) 600 | buf[i] = find_closest_color(bmp, bmp->pixels[i][row]); 601 | } 602 | 603 | static void 604 | bmp_get_row_data_for_24(bmpfile_t *bmp, unsigned char *buf, size_t buf_len, 605 | uint32_t row) 606 | { 607 | unsigned int i; 608 | 609 | if (bmp->dib.width * 3 > buf_len) return; 610 | 611 | for (i = 0; i < bmp->dib.width; ++i) 612 | memcpy(buf + 3 * i, (uint8_t *)&(bmp->pixels[i][row]), 3); 613 | } 614 | 615 | static void 616 | bmp_get_row_data_for_32(bmpfile_t *bmp, unsigned char *buf, size_t buf_len, 617 | uint32_t row) 618 | { 619 | unsigned int i; 620 | 621 | if (bmp->dib.width * 4 > buf_len) return; 622 | 623 | for (i = 0; i < bmp->dib.width; ++i) 624 | memcpy(buf + 4 * i, (uint8_t *)&(bmp->pixels[i][row]), 4); 625 | } 626 | 627 | int 628 | bmp_save(bmpfile_t *bmp, const char *filename) 629 | { 630 | FILE *fp; 631 | int row; 632 | unsigned char *buf; 633 | 634 | /* Create the file */ 635 | if ((fp = fopen(filename, "wb")) == NULL) 636 | return FALSE; 637 | 638 | /* Write the file */ 639 | bmp_write_header(bmp, fp); 640 | bmp_write_dib(bmp, fp); 641 | bmp_write_palette(bmp, fp); 642 | 643 | if (bmp->dib.depth == 16) { 644 | uint32_t data_bytes = bmp->dib.width * 2; 645 | uint32_t padding_bytes = 4 - data_bytes % 4; 646 | 647 | for (row = bmp->dib.height - 1; row >= 0; --row) { 648 | int i; 649 | unsigned char zero_byte = 0; 650 | uint32_t write_number = 0; 651 | 652 | for (i = 0; write_number < data_bytes; ++i, write_number += 2) { 653 | uint16_t red = (uint16_t)(bmp->pixels[i][row].red / 8); 654 | uint16_t green = (uint16_t)(bmp->pixels[i][row].green / 4); 655 | uint16_t blue = (uint16_t)(bmp->pixels[i][row].blue / 8); 656 | uint16_t value = (red << 11) + (green << 5) + blue; 657 | 658 | if (_is_big_endian()) value = UINT16_SWAP_LE_BE_CONSTANT(value); 659 | fwrite(&value, sizeof(uint16_t), 1, fp); 660 | } 661 | 662 | for (write_number = 0; write_number < padding_bytes; ++write_number) 663 | fwrite(&zero_byte, 1, 1, fp); 664 | } 665 | } 666 | else { 667 | double bytes_per_pixel; 668 | int bytes_per_line; 669 | 670 | bytes_per_pixel = (bmp->dib.depth * 1.0) / 8.0; 671 | bytes_per_line = (int)ceil(bytes_per_pixel * bmp->dib.width); 672 | if (bytes_per_line % 4 != 0) 673 | bytes_per_line += 4 - bytes_per_line % 4; 674 | 675 | buf = (unsigned char *)malloc(bytes_per_line); 676 | 677 | for (row = bmp->dib.height - 1; row >= 0; --row) { 678 | memset(buf, 0, bytes_per_line); 679 | 680 | switch (bmp->dib.depth) { 681 | case 1: 682 | bmp_get_row_data_for_1(bmp, buf, bytes_per_line, row); 683 | break; 684 | 685 | case 4: 686 | bmp_get_row_data_for_4(bmp, buf, bytes_per_line, row); 687 | break; 688 | 689 | case 8: 690 | bmp_get_row_data_for_8(bmp, buf, bytes_per_line, row); 691 | break; 692 | 693 | case 24: 694 | bmp_get_row_data_for_24(bmp, buf, bytes_per_line, row); 695 | break; 696 | 697 | case 32: 698 | bmp_get_row_data_for_32(bmp, buf, bytes_per_line, row); 699 | break; 700 | } 701 | 702 | fwrite(buf, bytes_per_line, 1, fp); 703 | } 704 | free(buf); 705 | } 706 | 707 | fclose(fp); 708 | 709 | return TRUE; 710 | } 711 | -------------------------------------------------------------------------------- /Code128_CPlusPlus/C128.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file C128.h 3 | * @brief The Code128 encoding library 4 | * 5 | * C128 - Code 128 library 6 | * Copyright (C) 2015 Brad Barnhill 7 | * mail: bradbarnhill@hotmail.com 8 | * 9 | * This library is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU Lesser General Public 11 | * License as published by the Free Software Foundation; either 12 | * version 2 of the License, or (at your option) any later version. 13 | * 14 | * This library is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | * Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public 20 | * License along with this library; if not, write to the 21 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 22 | * Boston, MA 02111-1307, USA. 23 | * 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include "C128_Defines.h" 31 | #include "bmpfile.h" 32 | using namespace std; 33 | 34 | enum TYPES { DYNAMIC, A, B, C }; 35 | enum COLUMN { COLUMN_VALUE, COLUMN_A, COLUMN_B, COLUMN_C, COLUMN_ENCODING }; 36 | 37 | struct element_t 38 | { 39 | string Value; 40 | string A; 41 | string B; 42 | string C; 43 | string Encoding; 44 | element_t(){}; 45 | 46 | element_t(string value, string a, string b, string c, string encoding) : Value(value), A(a), B(b), C(c), Encoding(encoding) { } 47 | }; 48 | 49 | class Code128 50 | { 51 | private: 52 | string Raw_Data; 53 | string Encoded_Data; 54 | TYPES Type; 55 | element_t StartCharacter; 56 | vector* C128_Code; 57 | vector mFormattedData; 58 | string ErrorMsg; 59 | 60 | element_t startAElement; 61 | element_t startBElement; 62 | element_t startCElement; 63 | element_t codeAElement; 64 | element_t codeBElement; 65 | element_t codeCElement; 66 | element_t codeStop; 67 | 68 | void init_Code128(string, TYPES); 69 | string CalculateCheckDigit(); 70 | void BreakUpDataForEncoding(); 71 | void InsertStartandCodeCharacters(); 72 | string GetEncoding(); 73 | vector FindStartorCodeCharacter(string, int &); 74 | int findCharEncodingRow(COLUMN, string); 75 | char* intToAlpha(int value, char* result, int base); 76 | bool isNumber(const string &); 77 | void Error(string errMsg); 78 | public: 79 | Code128(string); 80 | Code128(string, TYPES); 81 | void writeImage(int, unsigned int, string); 82 | ~Code128(); 83 | }; 84 | 85 | Code128::Code128(string toEncode) 86 | { 87 | Code128(toEncode, DYNAMIC); 88 | } 89 | 90 | Code128::Code128(string toEncode, TYPES type) 91 | { 92 | Raw_Data = toEncode; 93 | 94 | init_Code128(toEncode, type); 95 | } 96 | 97 | Code128::~Code128() 98 | { 99 | delete C128_Code; 100 | } 101 | 102 | void Code128::init_Code128(string toEncode, TYPES type) 103 | { 104 | Raw_Data = toEncode; 105 | Type = type; 106 | ErrorMsg = ""; 107 | Encoded_Data = ""; 108 | 109 | C128_Code = new vector(); 110 | C128_Code->push_back(new element_t("0", " ", " ", "00", "11011001100")); 111 | C128_Code->push_back(new element_t("1", "!", "!", "01", "11001101100")); 112 | C128_Code->push_back(new element_t("2", "\"", "\"", "02", "11001100110")); 113 | C128_Code->push_back(new element_t("3", "#", "#", "03", "10010011000")); 114 | C128_Code->push_back(new element_t("4", "$", "$", "04", "10010001100")); 115 | C128_Code->push_back(new element_t("5", "%", "%", "05", "10001001100")); 116 | C128_Code->push_back(new element_t("6", "&", "&", "06", "10011001000")); 117 | C128_Code->push_back(new element_t("7", "'", "'", "07", "10011000100")); 118 | C128_Code->push_back(new element_t("8", "(", "(", "08", "10001100100")); 119 | C128_Code->push_back(new element_t("9", ")", ")", "09", "11001001000")); 120 | C128_Code->push_back(new element_t("10", "*", "*", "10", "11001000100")); 121 | C128_Code->push_back(new element_t("11", "+", "+", "11", "11000100100")); 122 | C128_Code->push_back(new element_t("12", ",", ",", "12", "10110011100")); 123 | C128_Code->push_back(new element_t("13", "-", "-", "13", "10011011100")); 124 | C128_Code->push_back(new element_t("14", ".", ".", "14", "10011001110")); 125 | C128_Code->push_back(new element_t("15", "/", "/", "15", "10111001100")); 126 | C128_Code->push_back(new element_t("16", "0", "0", "16", "10011101100")); 127 | C128_Code->push_back(new element_t("17", "1", "1", "17", "10011100110")); 128 | C128_Code->push_back(new element_t("18", "2", "2", "18", "11001110010")); 129 | C128_Code->push_back(new element_t("19", "3", "3", "19", "11001011100")); 130 | C128_Code->push_back(new element_t("20", "4", "4", "20", "11001001110")); 131 | C128_Code->push_back(new element_t("21", "5", "5", "21", "11011100100")); 132 | C128_Code->push_back(new element_t("22", "6", "6", "22", "11001110100")); 133 | C128_Code->push_back(new element_t("23", "7", "7", "23", "11101101110")); 134 | C128_Code->push_back(new element_t("24", "8", "8", "24", "11101001100")); 135 | C128_Code->push_back(new element_t("25", "9", "9", "25", "11100101100")); 136 | C128_Code->push_back(new element_t("26", ":", ":", "26", "11100100110")); 137 | C128_Code->push_back(new element_t("27", ";", ";", "27", "11101100100")); 138 | C128_Code->push_back(new element_t("28", "<", "<", "28", "11100110100")); 139 | C128_Code->push_back(new element_t("29", "=", "=", "29", "11100110010")); 140 | C128_Code->push_back(new element_t("30", ">", ">", "30", "11011011000")); 141 | C128_Code->push_back(new element_t("31", "?", "?", "31", "11011000110")); 142 | C128_Code->push_back(new element_t("32", "@", "@", "32", "11000110110")); 143 | C128_Code->push_back(new element_t("33", "A", "A", "33", "10100011000")); 144 | C128_Code->push_back(new element_t("34", "B", "B", "34", "10001011000")); 145 | C128_Code->push_back(new element_t("35", "C", "C", "35", "10001000110")); 146 | C128_Code->push_back(new element_t("36", "D", "D", "36", "10110001000")); 147 | C128_Code->push_back(new element_t("37", "E", "E", "37", "10001101000")); 148 | C128_Code->push_back(new element_t("38", "F", "F", "38", "10001100010")); 149 | C128_Code->push_back(new element_t("39", "G", "G", "39", "11010001000")); 150 | C128_Code->push_back(new element_t("40", "H", "H", "40", "11000101000")); 151 | C128_Code->push_back(new element_t("41", "I", "I", "41", "11000100010")); 152 | C128_Code->push_back(new element_t("42", "J", "J", "42", "10110111000")); 153 | C128_Code->push_back(new element_t("43", "K", "K", "43", "10110001110")); 154 | C128_Code->push_back(new element_t("44", "L", "L", "44", "10001101110")); 155 | C128_Code->push_back(new element_t("45", "M", "M", "45", "10111011000")); 156 | C128_Code->push_back(new element_t("46", "N", "N", "46", "10111000110")); 157 | C128_Code->push_back(new element_t("47", "O", "O", "47", "10001110110")); 158 | C128_Code->push_back(new element_t("48", "P", "P", "48", "11101110110")); 159 | C128_Code->push_back(new element_t("49", "Q", "Q", "49", "11010001110")); 160 | C128_Code->push_back(new element_t("50", "R", "R", "50", "11000101110")); 161 | C128_Code->push_back(new element_t("51", "S", "S", "51", "11011101000")); 162 | C128_Code->push_back(new element_t("52", "T", "T", "52", "11011100010")); 163 | C128_Code->push_back(new element_t("53", "U", "U", "53", "11011101110")); 164 | C128_Code->push_back(new element_t("54", "V", "V", "54", "11101011000")); 165 | C128_Code->push_back(new element_t("55", "W", "W", "55", "11101000110")); 166 | C128_Code->push_back(new element_t("56", "X", "X", "56", "11100010110")); 167 | C128_Code->push_back(new element_t("57", "Y", "Y", "57", "11101101000")); 168 | C128_Code->push_back(new element_t("58", "Z", "Z", "58", "11101100010")); 169 | C128_Code->push_back(new element_t("59", "[", "[", "59", "11100011010")); 170 | C128_Code->push_back(new element_t("60", "\\", "\\", "60", "11101111010")); 171 | C128_Code->push_back(new element_t("61", "]", "]", "61", "11001000010")); 172 | C128_Code->push_back(new element_t("62", "^", "^", "62", "11110001010")); 173 | C128_Code->push_back(new element_t("63", "_", "_", "63", "10100110000")); 174 | C128_Code->push_back(new element_t("64", NUL, "`", "64", "10100001100")); 175 | C128_Code->push_back(new element_t("65", SOH, "a", "65", "10010110000")); 176 | C128_Code->push_back(new element_t("66", STX, "b", "66", "10010000110")); 177 | C128_Code->push_back(new element_t("67", ETX, "c", "67", "10000101100")); 178 | C128_Code->push_back(new element_t("68", EOT, "d", "68", "10000100110")); 179 | C128_Code->push_back(new element_t("69", ENQ, "e", "69", "10110010000")); 180 | C128_Code->push_back(new element_t("70", ACK, "f", "70", "10110000100")); 181 | C128_Code->push_back(new element_t("71", BEL, "g", "71", "10011010000")); 182 | C128_Code->push_back(new element_t("72", BS, "h", "72", "10011000010")); 183 | C128_Code->push_back(new element_t("73", TAB, "i", "73", "10000110100")); 184 | C128_Code->push_back(new element_t("74", LF, "j", "74", "10000110010")); 185 | C128_Code->push_back(new element_t("75", VT, "k", "75", "11000010010")); 186 | C128_Code->push_back(new element_t("76", FF, "l", "76", "11001010000")); 187 | C128_Code->push_back(new element_t("77", CR, "m", "77", "11110111010")); 188 | C128_Code->push_back(new element_t("78", SO, "n", "78", "11000010100")); 189 | C128_Code->push_back(new element_t("79", SI, "o", "79", "10001111010")); 190 | C128_Code->push_back(new element_t("80", DLE, "p", "80", "10100111100")); 191 | C128_Code->push_back(new element_t("81", DC1, "q", "81", "10010111100")); 192 | C128_Code->push_back(new element_t("82", DC2, "r", "82", "10010011110")); 193 | C128_Code->push_back(new element_t("83", DC3, "s", "83", "10111100100")); 194 | C128_Code->push_back(new element_t("84", DC4, "t", "84", "10011110100")); 195 | C128_Code->push_back(new element_t("85", NAK, "u", "85", "10011110010")); 196 | C128_Code->push_back(new element_t("86", SYN, "v", "86", "11110100100")); 197 | C128_Code->push_back(new element_t("87", ETB, "w", "87", "11110010100")); 198 | C128_Code->push_back(new element_t("88", CAN, "x", "88", "11110010010")); 199 | C128_Code->push_back(new element_t("89", EM, "y", "89", "11011011110")); 200 | C128_Code->push_back(new element_t("90", SUB, "z", "90", "11011110110")); 201 | C128_Code->push_back(new element_t("91", ESC, "{", "91", "11110110110")); 202 | C128_Code->push_back(new element_t("92", FS, "|", "92", "10101111000")); 203 | C128_Code->push_back(new element_t("93", GS, "}", "93", "10100011110")); 204 | C128_Code->push_back(new element_t("94", RS, "~", "94", "10001011110")); 205 | C128_Code->push_back(new element_t("95", US, DEL, "95", "10111101000")); 206 | C128_Code->push_back(new element_t("96", FNC3, FNC3, "96", "10111100010")); 207 | C128_Code->push_back(new element_t("97", FNC2, FNC2, "97", "11110101000")); 208 | C128_Code->push_back(new element_t("98", SHIFT, SHIFT, "98", "11110100010")); 209 | C128_Code->push_back(new element_t("99", CODE_C, CODE_C, "99", "10111011110")); 210 | C128_Code->push_back(new element_t("100", CODE_B, FNC4, CODE_B, "10111101110")); 211 | C128_Code->push_back(new element_t("101", FNC4, CODE_A, CODE_A, "11101011110")); 212 | C128_Code->push_back(new element_t("102", FNC1, FNC1, FNC1, "11110101110")); 213 | C128_Code->push_back(new element_t("103", START_A, START_A, START_A, "11010000100")); 214 | C128_Code->push_back(new element_t("104", START_B, START_B, START_B, "11010010000")); 215 | C128_Code->push_back(new element_t("105", START_C, START_C, START_C, "11010011100")); 216 | C128_Code->push_back(new element_t("", STOP, STOP, STOP, "11000111010")); 217 | 218 | startAElement = element_t("103", START_A, START_A, START_A, "11010000100"); 219 | startBElement = element_t("104", START_B, START_B, START_B, "11010010000"); 220 | startCElement = element_t("105", START_C, START_C, START_C, "11010011100"); 221 | codeAElement = element_t("101", FNC4, CODE_A, CODE_A, "11101011110"); 222 | codeBElement = element_t("100", CODE_B, FNC4, CODE_B, "10111101110"); 223 | codeCElement = element_t("99", CODE_C, CODE_C, "99", "10111011110"); 224 | codeStop = element_t("", STOP, STOP, STOP, "11000111010"); 225 | } 226 | 227 | string Code128::CalculateCheckDigit() 228 | { 229 | string currentStartChar = mFormattedData[0]; 230 | unsigned int CheckSum = 0; 231 | string s; 232 | element_t* row = new element_t(); 233 | 234 | for (unsigned int i = 0; i < mFormattedData.size(); ++i) 235 | { 236 | //get char to find 237 | s = mFormattedData[i]; 238 | 239 | //try to find value in the A column 240 | int index = findCharEncodingRow(COLUMN_A, s); 241 | if (index > -1) 242 | { 243 | //found in encoding type A 244 | row = C128_Code->at(index); 245 | } 246 | else 247 | { 248 | index = findCharEncodingRow(COLUMN_B, s); 249 | if (index > -1) 250 | { 251 | //found in encoding B 252 | row = C128_Code->at(index); 253 | } 254 | else 255 | { 256 | index = findCharEncodingRow(COLUMN_C, s); 257 | if (index > -1) 258 | { 259 | //found in encoding C 260 | row = C128_Code->at(index); 261 | } 262 | else 263 | { 264 | //TODO: not found in A B or C so this is an invalid character, how should we handle that? 265 | } 266 | } 267 | } 268 | 269 | unsigned int value = atoi(row->Value.c_str()); 270 | unsigned int addition = value * ((i == 0) ? 1 : i); 271 | CheckSum += addition; 272 | }//for 273 | 274 | unsigned int Remainder = (CheckSum % 103); 275 | char * strRem = new char[0]; 276 | row = C128_Code->at(findCharEncodingRow(COLUMN_VALUE, intToAlpha(Remainder, strRem, 10))); 277 | return row->Encoding; 278 | } 279 | 280 | void Code128::BreakUpDataForEncoding() 281 | { 282 | string temp = ""; 283 | string tempRawData = Raw_Data; 284 | 285 | //breaking the raw data up for code A and code B will mess up the encoding 286 | if (Type == A || Type == B) 287 | { 288 | for (unsigned int i = 0; i < Raw_Data.size(); ++i) 289 | { 290 | 291 | mFormattedData.push_back("" + Raw_Data[i]); 292 | } 293 | return; 294 | }//if 295 | else if (Type == C) 296 | { 297 | if (!isNumber(Raw_Data)) 298 | { 299 | Error("EC128-6: Only numeric values can be encoded with C128-C."); 300 | } 301 | 302 | //CODE C: adds a 0 to the front of the Raw_Data if the length is not divisible by 2 303 | if (Raw_Data.size() % 2 > 0) 304 | { 305 | tempRawData = "0" + Raw_Data; 306 | } 307 | }//if 308 | 309 | for (unsigned int i = 0; i < tempRawData.size(); ++i) 310 | { 311 | char c = tempRawData[i]; 312 | if (isdigit(c)) 313 | { 314 | if (temp == "") 315 | { 316 | temp += c; 317 | }//if 318 | else 319 | { 320 | mFormattedData.push_back(temp + c); 321 | temp = ""; 322 | }//else 323 | }//if 324 | else 325 | { 326 | if (temp != "") 327 | { 328 | mFormattedData.push_back(temp); 329 | temp = ""; 330 | }//if 331 | mFormattedData.push_back("" + c); 332 | }//else 333 | }//for 334 | 335 | //if something is still in temp go ahead and push it onto the queue 336 | if (temp != "") 337 | { 338 | mFormattedData.push_back(temp); 339 | temp = ""; 340 | }//if 341 | } 342 | 343 | void Code128::InsertStartandCodeCharacters() 344 | { 345 | string currentCodeString = ""; 346 | std::vector::iterator it; 347 | it = mFormattedData.begin(); 348 | 349 | if (Type != DYNAMIC) 350 | { 351 | switch (Type) 352 | { 353 | case A: mFormattedData.insert(it, START_A); 354 | break; 355 | case B: mFormattedData.insert(it, START_B); 356 | break; 357 | case C: mFormattedData.insert(it, START_C); 358 | break; 359 | default: Error("EC128-4: Unknown start type in fixed type encoding."); 360 | break; 361 | } 362 | }//if 363 | else 364 | { 365 | try 366 | { 367 | for (unsigned int i = 0; i < (mFormattedData.size()); ++i) 368 | { 369 | int col = 0; 370 | vector tempStartChars = FindStartorCodeCharacter(mFormattedData[i], col); 371 | 372 | //check all the start characters and see if we need to stay with the same codeset or if a change of sets is required 373 | bool sameCodeSet = false; 374 | element_t row; 375 | for (unsigned int i = 0; i < tempStartChars.size(); ++i) 376 | { 377 | row = tempStartChars[i]; 378 | if (row.A == currentCodeString || row.B == currentCodeString || row.C == currentCodeString) 379 | { 380 | sameCodeSet = true; 381 | break; 382 | }//if 383 | }//foreach 384 | 385 | //only insert a new code char if starting a new codeset 386 | //if (CurrentCodeString == "" || !tempStartChars[0][col].ToString().EndsWith(CurrentCodeString)) /* Removed because of bug */ 387 | 388 | if (currentCodeString == "" || !sameCodeSet) 389 | { 390 | element_t CurrentCodeSet = tempStartChars[0]; 391 | 392 | if (CurrentCodeSet.A == START_A || CurrentCodeSet.B == START_A || CurrentCodeSet.C == START_A) 393 | { 394 | currentCodeString = START_A; 395 | } 396 | else if (CurrentCodeSet.A == START_B || CurrentCodeSet.B == START_B || CurrentCodeSet.C == START_B) 397 | { 398 | currentCodeString = START_B; 399 | } 400 | else if (CurrentCodeSet.A == START_C || CurrentCodeSet.B == START_C || CurrentCodeSet.C == START_C) 401 | { 402 | currentCodeString = START_C; 403 | } 404 | else 405 | { 406 | Error("No start character found in CurrentCodeSet."); 407 | } 408 | 409 | mFormattedData.insert(it++, currentCodeString); 410 | }//if 411 | }//for 412 | } 413 | catch (const std::exception& e) 414 | { 415 | Error("EC128-3: Could not insert start and code characters.\n Message: " + (string)e.what()); 416 | }//catch 417 | }//else 418 | } 419 | 420 | vector Code128::FindStartorCodeCharacter(string s, int &col) 421 | { 422 | vector rows = vector(); 423 | 424 | //if two chars are numbers (or FNC1) then START_C or CODE_C 425 | if (s.size() > 1 && (isdigit(s[0]) || &s[0] == FNC1) && (isdigit(s[1]) || &s[1] == FNC1)) 426 | { 427 | if (!&StartCharacter) 428 | { 429 | StartCharacter = startCElement; 430 | rows.push_back(StartCharacter); 431 | }//if 432 | else 433 | rows.push_back(startCElement); 434 | 435 | col = 1; 436 | }//if 437 | else 438 | { 439 | bool AFound = false; 440 | bool BFound = false; 441 | for (unsigned int i = 0; i < C128_Code->size(); ++i) 442 | { 443 | element_t* row = C128_Code->at(i); 444 | try 445 | { 446 | if (!AFound && s == row->A) 447 | { 448 | AFound = true; 449 | col = 2; 450 | 451 | if (!&StartCharacter) 452 | { 453 | StartCharacter = startAElement; 454 | rows.insert(rows.begin(), StartCharacter); 455 | }//if 456 | else 457 | { 458 | rows.insert(rows.begin(), codeAElement); 459 | }//else 460 | }//if 461 | else if (!BFound && s == row->B) 462 | { 463 | BFound = true; 464 | col = 1; 465 | 466 | if (!&StartCharacter) 467 | { 468 | StartCharacter = startBElement; 469 | rows.insert(rows.begin(), StartCharacter); 470 | }//if 471 | else 472 | { 473 | rows.insert(rows.begin(), codeBElement); 474 | } 475 | }//else 476 | else if (AFound && BFound) 477 | { 478 | break; 479 | } 480 | }//try 481 | catch (const std::exception& e) 482 | { 483 | Error("EC128-1: " + (string)e.what()); 484 | }//catch 485 | }//foreach 486 | 487 | if (rows.size() <= 0) 488 | { 489 | Error("EC128-2: Could not determine start character."); 490 | } 491 | }//else 492 | 493 | return rows; 494 | } 495 | 496 | string Code128::GetEncoding() 497 | { 498 | mFormattedData.clear(); 499 | 500 | //break up data for encoding 501 | BreakUpDataForEncoding(); 502 | 503 | //insert the start characters 504 | InsertStartandCodeCharacters(); 505 | 506 | string CheckDigit = CalculateCheckDigit(); 507 | 508 | Encoded_Data = ""; 509 | for (unsigned int i = 0; i < mFormattedData.size(); ++i) 510 | { 511 | string s = mFormattedData[i]; 512 | 513 | //handle exception with apostrophes in select statements 514 | element_t* E_Row = NULL; 515 | 516 | //select encoding only for type selected 517 | switch (Type) 518 | { 519 | int ind; 520 | case A: 521 | ind = findCharEncodingRow(COLUMN_A, s); 522 | if (ind >= 0) 523 | { 524 | E_Row = C128_Code->at(ind); 525 | } 526 | break; 527 | case B: 528 | ind = findCharEncodingRow(COLUMN_B, s); 529 | if (ind >= 0) 530 | { 531 | E_Row = C128_Code->at(ind); 532 | } 533 | break; 534 | case C: 535 | ind = findCharEncodingRow(COLUMN_C, s); 536 | if (ind >= 0) 537 | { 538 | E_Row = C128_Code->at(ind); 539 | } 540 | break; 541 | case DYNAMIC: 542 | ind = findCharEncodingRow(COLUMN_A, s); 543 | 544 | if (ind < 0) 545 | { 546 | ind = findCharEncodingRow(COLUMN_B, s); 547 | 548 | if (ind < 0) 549 | { 550 | ind = findCharEncodingRow(COLUMN_C, s); 551 | }//if 552 | }//if 553 | 554 | if (ind >= 0) 555 | { 556 | E_Row = C128_Code->at(ind); 557 | } 558 | break; 559 | default: 560 | break; 561 | }//switch 562 | 563 | if (E_Row == NULL) 564 | { 565 | Error("EC128-5: Could not find encoding of a value( " + s + " ) in C128"); 566 | return NULL; 567 | } 568 | 569 | Encoded_Data += E_Row->Encoding; 570 | }//foreach 571 | 572 | //add the check digit 573 | Encoded_Data += CheckDigit; 574 | 575 | //add the stop character 576 | Encoded_Data += codeStop.Encoding; 577 | 578 | //add the termination bars 579 | Encoded_Data += "11"; 580 | 581 | return Encoded_Data; 582 | } 583 | 584 | void Code128::Error(string errMsg) 585 | { 586 | //TODO: Handle exceptions uniformly 587 | } 588 | 589 | string replaceOnce(std::string str, const std::string& from, const std::string& to) { 590 | size_t start_pos = str.find(from); 591 | if(start_pos == std::string::npos) 592 | return str; 593 | str.replace(start_pos, from.length(), to); 594 | return str; 595 | } 596 | 597 | int Code128::findCharEncodingRow(COLUMN codeType, string value) 598 | { 599 | for (unsigned int i = 0; i < C128_Code->size() - 1; ++i) 600 | { 601 | switch(codeType) 602 | { 603 | case COLUMN_A: 604 | if (C128_Code->at(i)->A == value) 605 | { 606 | return i; 607 | } 608 | break; 609 | case COLUMN_B: 610 | if (C128_Code->at(i)->B == value) 611 | { 612 | return i; 613 | } 614 | break; 615 | case COLUMN_C: 616 | if (C128_Code->at(i)->C == value) 617 | { 618 | return i; 619 | } 620 | break; 621 | case COLUMN_VALUE: 622 | if (C128_Code->at(i)->Value == value) 623 | { 624 | return i; 625 | } 626 | break; 627 | default: 628 | break; 629 | }; 630 | } 631 | 632 | return -1; 633 | } 634 | 635 | /** 636 | * REQUIRED due to itoa not being a standard in ANSI C++ 637 | * 638 | * C++ version 0.4 char* style "itoa": 639 | * Written by Luk·s Chmela 640 | * Released under GPLv3. 641 | */ 642 | char* Code128::intToAlpha(int value, char* result, int base) { 643 | // check that the base if valid 644 | if (base < 2 || base > 36) 645 | { 646 | *result = '\0'; 647 | return result; 648 | } 649 | 650 | char* ptr = result, *ptr1 = result, tmp_char; 651 | int tmp_value; 652 | 653 | do { 654 | tmp_value = value; 655 | value /= base; 656 | *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)]; 657 | } while ( value ); 658 | 659 | // Apply negative sign 660 | if (tmp_value < 0) 661 | *ptr++ = '-'; 662 | 663 | *ptr-- = '\0'; 664 | 665 | while(ptr1 < ptr) { 666 | tmp_char = *ptr; 667 | *ptr--= *ptr1; 668 | *ptr1++ = tmp_char; 669 | } 670 | return result; 671 | } 672 | 673 | bool Code128::isNumber(const string& s) 674 | { 675 | return !s.empty() && s.find_first_not_of("-.0123456789") == string::npos; 676 | } 677 | 678 | void Code128::writeImage(int barWidthInPx, unsigned int heightInPx, string fileName) 679 | { 680 | string encodedValue = GetEncoding(); 681 | unsigned int widthInPx = encodedValue.size() * barWidthInPx; 682 | 683 | bmpfile_t *bmp; 684 | rgb_pixel_t wh = {255, 255, 255, 0}; 685 | rgb_pixel_t bl = {0, 0, 0, 0}; 686 | 687 | if ((bmp = bmp_create(widthInPx, heightInPx, 1)) != NULL) 688 | { 689 | for (unsigned int y = 0; y < heightInPx; ++y) 690 | { 691 | for (unsigned int x = 0; x < encodedValue.length(); ++x) 692 | { 693 | for (int pxs = 0; pxs < barWidthInPx; ++pxs) 694 | { 695 | bmp_set_pixel(bmp, ((x * barWidthInPx) + pxs), y, encodedValue[x] == '1' ? bl : wh); 696 | } 697 | } 698 | } 699 | 700 | bmp_save(bmp, fileName.c_str()); 701 | bmp_destroy(bmp); 702 | } 703 | } 704 | --------------------------------------------------------------------------------