├── LICENSE ├── README.md ├── images ├── Pixellib_anti_aliasing.png ├── Pixellib_geometry.png ├── Pixellib_image_drawing.png ├── Pixellib_image_transform.png ├── Pixellib_image_warp.png └── Pixellib_quality.png ├── pixellib ├── ibitmap.c ├── ibitmap.h ├── iblit386.c ├── iblit386.h ├── ibmbits.c ├── ibmbits.h ├── ibmcols.c ├── ibmcols.h ├── ibmdata.c ├── ibmdata.h ├── ibmfont.c ├── ibmfont.h ├── ibmsse2.c ├── ibmsse2.h ├── ibmwink.c ├── ibmwink.h ├── ikitwin.c ├── ikitwin.h ├── ipicture.c ├── ipicture.h ├── mswindx.c ├── mswindx.h ├── npixel.c └── npixel.h └── wrap ├── PixelBitmap.cpp ├── PixelBitmap.h ├── PixelWin32.cpp └── PixelWin32.h /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | 341 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Description 2 | ----------- 3 | - High Quality Anti-Alising Vector/Raster Graphics 4 | - Multi-Pixel-Format: RGB, BGR, ARGB, ABGR, RGBA, BGRA 5 | 8 / 15 / 16 / 24 / 32 depth 6 | - Light weight 100% C implementation 7 | - SSE2/MMX Graphics Optimized 8 | 9 | Samples 10 | ------- 11 | 12 | Samples with executable can be download from [here](https://pixellib.googlecode.com/files/pixellib-samples-1.2.67.7z "here") . 13 | 14 | **Image Transform** 15 | 16 | ![Image Transform](https://raw.githubusercontent.com/skywind3000/pixellib/master/images/Pixellib_image_transform.png) 17 | 18 | **Anti Aliasing** 19 | 20 | ![Anti Alising](https://raw.githubusercontent.com/skywind3000/pixellib/master/images/Pixellib_anti_aliasing.png) 21 | 22 | **Image Drawing** 23 | 24 | ![Image Drawing](https://raw.githubusercontent.com/skywind3000/pixellib/master/images/Pixellib_image_drawing.png) 25 | 26 | **Geometry Render** 27 | 28 | ![Geometry Rendering](https://raw.githubusercontent.com/skywind3000/pixellib/master/images/Pixellib_geometry.png) 29 | 30 | **Image Warp** 31 | 32 | ![Image Warp](https://raw.githubusercontent.com/skywind3000/pixellib/master/images/Pixellib_image_warp.png) 33 | 34 | **High Quality Render** 35 | 36 | ![Image Warp](https://raw.githubusercontent.com/skywind3000/pixellib/master/images/Pixellib_quality.png) 37 | 38 | 39 | Donation 40 | -------- 41 | ![Donation QR](https://raw.githubusercontent.com/skywind3000/kcp/master/donation.png) 42 | 43 | Call for donation to help improve performance and quality, scan QR code of alipay to donate. 44 | 45 | 46 | -------------------------------------------------------------------------------- /images/Pixellib_anti_aliasing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/images/Pixellib_anti_aliasing.png -------------------------------------------------------------------------------- /images/Pixellib_geometry.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/images/Pixellib_geometry.png -------------------------------------------------------------------------------- /images/Pixellib_image_drawing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/images/Pixellib_image_drawing.png -------------------------------------------------------------------------------- /images/Pixellib_image_transform.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/images/Pixellib_image_transform.png -------------------------------------------------------------------------------- /images/Pixellib_image_warp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/images/Pixellib_image_warp.png -------------------------------------------------------------------------------- /images/Pixellib_quality.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/images/Pixellib_quality.png -------------------------------------------------------------------------------- /pixellib/ibitmap.c: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * 3 | * ibitmap.c - the basic definition of the bitmap 4 | * 5 | * IBITMAP is designed under the desire that it can exactly describe 6 | * one basic bitmap, which is considered as simple and pure. 7 | * 8 | * there are five basic bitmap operating interfaces: 9 | * 10 | * create - create a new bitmap and return the struct address 11 | * release - free the bitmap 12 | * blit - copy the speciafied rectangle from one bitmap to another 13 | * setmask - set the color key for transparent blit (IBLIT_MASK on) 14 | * fill - fill a rectange in the bitmap 15 | * 16 | * the history of this file: 17 | * Feb. 7 2003 skywind created including create/release/blit 18 | * Dec. 15 2004 skywind add filling 19 | * 20 | * aim to keep it simply and stupid, this file will only provide the 21 | * most basic bitmap operation interfaces. pixel format declearation, 22 | * color components modification must not be included in it. 23 | * 24 | * aim to platform independence, all of the sources are writen in ansi 25 | * c but you can replace the default blitter by ibitmap_funcset() to 26 | * optimized the benchmark of ibitmap_blit in the speciafied platform 27 | * 28 | **********************************************************************/ 29 | 30 | #include "ibitmap.h" 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | 38 | /********************************************************************** 39 | * MEMORY ALLOCATOR FUNCTIONS 40 | **********************************************************************/ 41 | void*(*icmalloc)(size_t size) = malloc; 42 | void (*icfree)(void *ptr) = free; 43 | 44 | 45 | /********************************************************************** 46 | * BASIC BITMAP FUNCTIONS 47 | **********************************************************************/ 48 | 49 | /* 50 | * ibitmap_create - create bitmap and return the pointer to struct IBITMAP 51 | * width - bitmap width 52 | * height - bitmap height 53 | * bpp - bitmap color depth (8, 16, 24, 32) 54 | */ 55 | struct IBITMAP *ibitmap_create(int w, int h, int bpp) 56 | { 57 | struct IBITMAP *bmp; 58 | unsigned char*line; 59 | int pixelbyte = (bpp + 7) >> 3; 60 | int i; 61 | 62 | /* check for invalid parametes */ 63 | assert(bpp >= 8 && bpp <=32 && w > 0 && h > 0); 64 | 65 | /* allocate memory for the IBITMAP struct */ 66 | bmp = (struct IBITMAP*)icmalloc(sizeof(struct IBITMAP)); 67 | if (bmp == NULL) return NULL; 68 | 69 | /* setup bmp struct */ 70 | bmp->w = w; 71 | bmp->h= h; 72 | bmp->bpp = bpp; 73 | bmp->pitch = (((long)w * pixelbyte + 7) >> 3) << 3; 74 | bmp->code = 0; 75 | 76 | /* allocate memory for pixel data */ 77 | bmp->pixel = (char*)icmalloc(bmp->pitch * h); 78 | 79 | if (bmp->pixel == NULL) { 80 | icfree(bmp); 81 | return NULL; 82 | } 83 | 84 | bmp->mode = 0; 85 | bmp->mask = 0; 86 | bmp->extra = NULL; 87 | 88 | /* caculate the offset of each scanline */ 89 | bmp->line = (void**)icmalloc(sizeof(void*) * h); 90 | if (bmp->line == NULL) { 91 | icfree(bmp->pixel); 92 | icfree(bmp); 93 | return NULL; 94 | } 95 | 96 | line = (unsigned char*)bmp->pixel; 97 | for (i = 0; i < h; i++, line += bmp->pitch) 98 | bmp->line[i] = line; 99 | 100 | return bmp; 101 | } 102 | 103 | /* 104 | * ibitmap_release - release bitmap 105 | * bmp - pointer to the IBITMAP struct 106 | */ 107 | void ibitmap_release(struct IBITMAP *bmp) 108 | { 109 | assert(bmp); 110 | if (bmp->pixel) icfree(bmp->pixel); 111 | bmp->pixel = NULL; 112 | if (bmp->line) icfree(bmp->line); 113 | bmp->line = NULL; 114 | bmp->w = 0; 115 | bmp->h = 0; 116 | bmp->pitch = 0; 117 | bmp->bpp = 0; 118 | icfree(bmp); 119 | } 120 | 121 | 122 | /* 123 | * ibitmap_clip - clip the rectangle from the src clip and dst clip then 124 | * caculate a new rectangle which is shared between dst and src cliprect: 125 | * clipdst - dest clip array (left, top, right, bottom) 126 | * clipsrc - source clip array (left, top, right, bottom) 127 | * (x, y) - dest position 128 | * rectsrc - source rect 129 | * mode - check IBLIT_HFLIP or IBLIT_VFLIP 130 | * return zero for successful, return non-zero if there is no shared part 131 | */ 132 | int ibitmap_clip(const int *clipdst, const int *clipsrc, int *x, int *y, 133 | int *rectsrc, int mode) 134 | { 135 | int dcl = clipdst[0]; /* dest clip: left */ 136 | int dct = clipdst[1]; /* dest clip: top */ 137 | int dcr = clipdst[2]; /* dest clip: right */ 138 | int dcb = clipdst[3]; /* dest clip: bottom */ 139 | int scl = clipsrc[0]; /* source clip: left */ 140 | int sct = clipsrc[1]; /* source clip: top */ 141 | int scr = clipsrc[2]; /* source clip: right */ 142 | int scb = clipsrc[3]; /* source clip: bottom */ 143 | int dx = *x; /* dest x position */ 144 | int dy = *y; /* dest y position */ 145 | int sl = rectsrc[0]; /* source rectangle: left */ 146 | int st = rectsrc[1]; /* source rectangle: top */ 147 | int sr = rectsrc[2]; /* source rectangle: right */ 148 | int sb = rectsrc[3]; /* source rectangle: bottom */ 149 | int hflip, vflip; 150 | int w, h, d; 151 | 152 | hflip = (mode & IBLIT_HFLIP)? 1 : 0; 153 | vflip = (mode & IBLIT_VFLIP)? 1 : 0; 154 | 155 | if (dcr <= dcl || dcb <= dct || scr <= scl || scb <= sct) 156 | return -1; 157 | 158 | if (sr <= scl || sb <= sct || sl >= scr || st >= scb) 159 | return -2; 160 | 161 | /* check dest clip: left */ 162 | if (dx < dcl) { 163 | d = dcl - dx; 164 | dx = dcl; 165 | if (!hflip) sl += d; 166 | else sr -= d; 167 | } 168 | 169 | /* check dest clip: top */ 170 | if (dy < dct) { 171 | d = dct - dy; 172 | dy = dct; 173 | if (!vflip) st += d; 174 | else sb -= d; 175 | } 176 | 177 | w = sr - sl; 178 | h = sb - st; 179 | 180 | if (w < 0 || h < 0) 181 | return -3; 182 | 183 | /* check dest clip: right */ 184 | if (dx + w > dcr) { 185 | d = dx + w - dcr; 186 | if (!hflip) sr -= d; 187 | else sl += d; 188 | } 189 | 190 | /* check dest clip: bottom */ 191 | if (dy + h > dcb) { 192 | d = dy + h - dcb; 193 | if (!vflip) sb -= d; 194 | else st += d; 195 | } 196 | 197 | if (sl >= sr || st >= sb) 198 | return -4; 199 | 200 | /* check source clip: left */ 201 | if (sl < scl) { 202 | d = scl - sl; 203 | sl = scl; 204 | if (!hflip) dx += d; 205 | } 206 | 207 | /* check source clip: top */ 208 | if (st < sct) { 209 | d = sct - st; 210 | st = sct; 211 | if (!vflip) dy += d; 212 | } 213 | 214 | if (sl >= sr || st >= sb) 215 | return -5; 216 | 217 | /* check source clip: right */ 218 | if (sr > scr) { 219 | d = sr - scr; 220 | sr = scr; 221 | if (hflip) dx += d; 222 | } 223 | 224 | /* check source clip: bottom */ 225 | if (sb > scb) { 226 | d = sb - scb; 227 | sb = scb; 228 | if (vflip) dy += d; 229 | } 230 | 231 | if (sl >= sr || st >= sb) 232 | return -6; 233 | 234 | *x = dx; 235 | *y = dy; 236 | 237 | rectsrc[0] = sl; 238 | rectsrc[1] = st; 239 | rectsrc[2] = sr; 240 | rectsrc[3] = sb; 241 | 242 | return 0; 243 | } 244 | 245 | 246 | /********************************************************************** 247 | * BLITTER DEFINITION 248 | **********************************************************************/ 249 | int ibitmap_blitnc(char *dst, long pitch1, const char *src, long pitch2, 250 | int w, int h, int pixsize, long linesize); 251 | int ibitmap_blitmc(char *dst, long pitch1, const char *src, long pitch2, 252 | int w, int h, int pixsize, long linesize, unsigned long mask); 253 | int ibitmap_blitfc(char *dst, long pitch1, const char *src, long pitch2, 254 | int w, int h, int pixsize, long linesize, unsigned long mask, int flag); 255 | 256 | 257 | /* set blitters interface to default blitters (c version) */ 258 | ibitmap_blitter_norm ibitmap_blitn = ibitmap_blitnc; 259 | ibitmap_blitter_mask ibitmap_blitm = ibitmap_blitmc; 260 | ibitmap_blitter_flip ibitmap_blitf = ibitmap_blitfc; 261 | 262 | 263 | 264 | /********************************************************************** 265 | * BLITTER INTERFACE - CORE OPERATION 266 | **********************************************************************/ 267 | 268 | /* 269 | * ibitmap_blit - blit from source bitmap to dest bitmap 270 | * returns zero for successful, others for error 271 | * dst - dest bitmap to draw on 272 | * x, y - target position of dest bitmap to draw on 273 | * src - source bitmap 274 | * sx, sy - source rectangle position in source bitmap 275 | * w, h - source rectangle width and height in source bitmap 276 | * mode - blit flag bits (IBLIT_CLIP, IBLIT_MASK) 277 | */ 278 | int ibitmap_blit(struct IBITMAP *dst, int x, int y, 279 | const struct IBITMAP *src, int sx, int sy, int w, int h, int mode) 280 | { 281 | long pitch1, pitch2; 282 | long linesize, d1, d2; 283 | int pixsize, r; 284 | char *pixel1; 285 | char *pixel2; 286 | 287 | /* check whether parametes is error */ 288 | assert(src && dst); 289 | assert(src->bpp == dst->bpp); 290 | 291 | /* check whether need to clip rectangle */ 292 | if (mode & IBLIT_CLIP) { 293 | int clipdst[4], clipsrc[4], rect[4]; 294 | clipdst[0] = 0; 295 | clipdst[1] = 0; 296 | clipdst[2] = (int)dst->w; 297 | clipdst[3] = (int)dst->h; 298 | clipsrc[0] = 0; 299 | clipsrc[1] = 0; 300 | clipsrc[2] = (int)src->w; 301 | clipsrc[3] = (int)src->h; 302 | rect[0] = sx; 303 | rect[1] = sy; 304 | rect[2] = sx + (int)w; 305 | rect[3] = sy + (int)h; 306 | r = ibitmap_clip(clipdst, clipsrc, &x, &y, rect, mode); 307 | if (r != 0) return 0; 308 | sx = rect[0]; 309 | sy = rect[1]; 310 | w = rect[2] - rect[0]; 311 | h = rect[3] - rect[1]; 312 | } 313 | 314 | /* get the size of one pixel */ 315 | pixsize = (src->bpp + 7) >> 3; 316 | pitch1 = dst->pitch; 317 | pitch2 = src->pitch; 318 | 319 | /* choose linear offset */ 320 | switch (pixsize) { 321 | case 1: 322 | linesize = w; 323 | d1 = x; 324 | d2 = sx; 325 | break; 326 | case 2: 327 | linesize = (w << 1); 328 | d1 = (x << 1); 329 | d2 = (sx << 1); 330 | break; 331 | case 3: 332 | linesize = (w << 1) + w; 333 | d1 = (x << 1) + x; 334 | d2 = (sx << 1) + sx; 335 | break; 336 | case 4: 337 | linesize = (w << 2); 338 | d1 = (x << 2); 339 | d2 = (sx << 2); 340 | break; 341 | default: 342 | linesize = w * pixsize; 343 | d1 = x * pixsize; 344 | d2 = sx * pixsize; 345 | break; 346 | } 347 | 348 | /* get the first scanlines of two bitmaps */ 349 | pixel1 = (char*)dst->line[y] + d1; 350 | pixel2 = (char*)src->line[sy] + d2; 351 | 352 | /* detect whether blit with flip */ 353 | if ((mode & (IBLIT_VFLIP | IBLIT_HFLIP)) != 0) { 354 | if (mode & IBLIT_VFLIP) { 355 | pixel2 = (char*)src->line[sy + h - 1] + d2; 356 | } 357 | r = ibitmap_blitf(pixel1, pitch1, pixel2, pitch2, w, h, 358 | pixsize, linesize, src->mask, mode); 359 | if (r) ibitmap_blitfc(pixel1, pitch1, pixel2, pitch2, w, h, 360 | pixsize, linesize, src->mask, mode); 361 | return 0; 362 | } 363 | 364 | /* check to use the normal blitter or the transparent blitter */ 365 | if ((mode & IBLIT_MASK) == 0) { 366 | r = ibitmap_blitn(pixel1, pitch1, pixel2, pitch2, w, h, 367 | pixsize, linesize); 368 | if (r) ibitmap_blitnc(pixel1, pitch1, pixel2, pitch2, w, h, 369 | pixsize, linesize); 370 | } else { 371 | r = ibitmap_blitm(pixel1, pitch1, pixel2, pitch2, w, h, 372 | pixsize, linesize, src->mask); 373 | if (r) ibitmap_blitmc(pixel1, pitch1, pixel2, pitch2, w, h, 374 | pixsize, linesize, src->mask); 375 | } 376 | 377 | return 0; 378 | } 379 | 380 | 381 | /********************************************************************** 382 | * ibitmap_blitnc - default blitter for normal blit (no transparent) 383 | **********************************************************************/ 384 | int ibitmap_blitnc(char *dst, long pitch1, const char *src, long pitch2, 385 | int w, int h, int pixelbyte, long linesize) 386 | { 387 | char *ss = (char*)src; 388 | char *sd = (char*)dst; 389 | 390 | /* avoid never use warnings */ 391 | if (pixelbyte == 1) linesize = w; 392 | 393 | /* copy each line */ 394 | for (; h; h--) 395 | { 396 | memcpy(sd, ss, linesize); 397 | sd += pitch1; 398 | ss += pitch2; 399 | } 400 | 401 | return 0; 402 | } 403 | 404 | 405 | /********************************************************************** 406 | * ibitmap_blitmc - default blitter for transparent blit 407 | **********************************************************************/ 408 | int ibitmap_blitmc(char *dst, long pitch1, const char *src, long pitch2, 409 | int w, int h, int pixelbyte, long linesize, unsigned long mask) 410 | { 411 | static unsigned long endian = 0x11223344; 412 | unsigned char *p1, *p2; 413 | unsigned long key24, c; 414 | unsigned char key08; 415 | unsigned short key16; 416 | unsigned int imask, k; 417 | long inc1, inc2, i; 418 | long longsize, isize; 419 | 420 | /* caculate the inc offset of two array */ 421 | inc1 = pitch1 - linesize; 422 | inc2 = pitch2 - linesize; 423 | 424 | longsize = sizeof(long); 425 | isize = sizeof(int); 426 | 427 | /* copying pixel for all color depth */ 428 | switch (pixelbyte) 429 | { 430 | /* for 8 bits colors depth */ 431 | case 1: 432 | key08 = (unsigned char)mask; 433 | for (; h; h--) { /* copy each scanline */ 434 | for (i = w; i; i--) { /* copy each pixel */ 435 | if (*(unsigned char*)src != key08) *dst = *src; 436 | src++; 437 | dst++; 438 | } 439 | dst += inc1; 440 | src += inc2; 441 | } 442 | break; 443 | 444 | /* for 15/16 bits colors depth */ 445 | case 2: 446 | key16 = (unsigned short)mask; 447 | for (; h; h--) { /* copy each scanline */ 448 | for (i = w; i; i--) { /* copy each pixel */ 449 | if (*(unsigned short*)src != key16) 450 | *(unsigned short*)dst = *(unsigned short*)src; 451 | src += 2; 452 | dst += 2; 453 | } 454 | dst += inc1; 455 | src += inc2; 456 | } 457 | break; 458 | 459 | /* for 24 bits colors depth */ 460 | case 3: 461 | if (((unsigned char*)&endian)[0] != 0x44) key24 = mask; 462 | else key24 = ((mask & 0xFFFF) << 8) | ((mask >> 16) & 0xFF); 463 | p1 = (unsigned char*)dst; 464 | p2 = (unsigned char*)src; 465 | 466 | /* 32/16 BIT: detect word-size in runtime instead of using */ 467 | /* macros, in order to be compiled in any unknown platform */ 468 | if (longsize == 4) { /* 32/16 BIT PLATFORM */ 469 | for (; h; h--) { /* copy each scanline */ 470 | for (i = w; i; i--) { /* copy each pixel */ 471 | c = (((unsigned long)(*(unsigned short*)p2)) << 8); 472 | if ((c | p2[2]) != key24) { 473 | p1[0] = p2[0]; 474 | p1[1] = p2[1]; 475 | p1[2] = p2[2]; 476 | } 477 | p1 += 3; 478 | p2 += 3; 479 | } 480 | p1 += inc1; 481 | p2 += inc2; 482 | } 483 | } 484 | else if (isize == 4) { /* 64 BIT PLATFORM */ 485 | imask = (unsigned int)(key24 & 0xffffffff); 486 | for (; h; h--) { /* copy each scanline */ 487 | for (i = w; i; i--) { /* copy each pixel */ 488 | k = (((unsigned int)(*(unsigned short*)p2)) << 8); 489 | if ((k | p2[2]) != imask) { 490 | p1[0] = p2[0]; 491 | p1[1] = p2[1]; 492 | p1[2] = p2[2]; 493 | } 494 | p1 += 3; 495 | p2 += 3; 496 | } 497 | p1 += inc1; 498 | p2 += inc2; 499 | } 500 | } 501 | break; 502 | 503 | /* for 32 bits colors depth */ 504 | case 4: 505 | /* 32/16 BIT: detect word-size in runtime instead of using */ 506 | /* macros, in order to be compiled in any unknown platform */ 507 | if (longsize == 4) { /* 32/16 BIT PLATFORM */ 508 | for (; h; h--) { /* copy each scanline */ 509 | for (i = w; i; i--) { /* copy each pixel */ 510 | if (*(unsigned long*)src != mask) 511 | *(unsigned long*)dst = *(unsigned long*)src; 512 | src += 4; 513 | dst += 4; 514 | } 515 | dst += inc1; 516 | src += inc2; 517 | } 518 | } 519 | else if (isize == 4) { /* 64 BIT PLATFORM */ 520 | imask = (unsigned int)(mask & 0xffffffff); 521 | for (; h; h--) { /* copy each scanline */ 522 | for (i = w; i; i--) { /* copy each pixel */ 523 | if (*(unsigned int*)src != imask) 524 | *(unsigned int*)dst = *(unsigned int*)src; 525 | src += 4; 526 | dst += 4; 527 | } 528 | dst += inc1; 529 | src += inc2; 530 | } 531 | } 532 | break; 533 | } 534 | 535 | return 0; 536 | } 537 | 538 | 539 | /********************************************************************** 540 | * ibitmap_blitfc - default blitter for flip blit 541 | **********************************************************************/ 542 | int ibitmap_blitfc(char *dst, long pitch1, const char *src, long pitch2, 543 | int w, int h, int pixsize, long linesize, unsigned long mask, int flag) 544 | { 545 | static unsigned long endian = 0x11223344; 546 | unsigned char *p1, *p2; 547 | unsigned long key24, c; 548 | unsigned char key08; 549 | unsigned short key16; 550 | unsigned int imask, k; 551 | long inc1, inc2, i; 552 | long longsize, isize; 553 | 554 | /* flip vertical without mask */ 555 | if ((flag & (IBLIT_MASK | IBLIT_HFLIP)) == 0) { 556 | for (; h; h--) { 557 | memcpy(dst, src, linesize); 558 | dst += pitch1; 559 | src -= pitch2; 560 | } 561 | return 0; 562 | } 563 | 564 | /* flip vertical with mask */ 565 | if ((flag & IBLIT_MASK) != 0 && (flag & IBLIT_HFLIP) == 0) { 566 | for (; h; h--) { 567 | ibitmap_blitmc(dst, pitch1, src, pitch2, w, 1, pixsize, 568 | linesize, mask); 569 | dst += pitch1; 570 | src -= pitch2; 571 | } 572 | return 0; 573 | } 574 | 575 | /* flip horizon */ 576 | src += linesize - pixsize; 577 | inc1 = pitch1 - linesize; 578 | 579 | longsize = sizeof(long); 580 | isize = sizeof(int); 581 | 582 | /* horizon & vertical or horizon only */ 583 | if (flag & IBLIT_VFLIP) inc2 = - (pitch2 - linesize); 584 | else inc2 = pitch2 + linesize; 585 | 586 | /* copying pixel for all color depth */ 587 | switch (pixsize) 588 | { 589 | /* flip in 8 bits colors depth */ 590 | case 1: 591 | key08 = (unsigned char)mask; 592 | for (; h; h--) { 593 | if (flag & IBLIT_MASK) { 594 | for (i = w; i; i--) { /* copy each pixel with mask */ 595 | if (*(unsigned char*)src != key08) *dst = *src; 596 | dst++; 597 | src--; 598 | } 599 | } else { 600 | for (i = w; i; i--) { /* copy pixels without mask */ 601 | *dst = *src; 602 | dst++; 603 | src--; 604 | } 605 | } 606 | dst += inc1; 607 | src += inc2; 608 | } 609 | break; 610 | 611 | /* flip in 15/16 bits colors depth */ 612 | case 2: 613 | key16 = (unsigned short)mask; 614 | for (; h; h--) { 615 | if (flag & IBLIT_MASK) { 616 | for (i = w; i; i--) { /* copy each pixel with mask */ 617 | if (*(unsigned short*)src != key16) 618 | *(unsigned short*)dst = *(unsigned short*)src; 619 | dst += 2; 620 | src -= 2; 621 | } 622 | } else { 623 | for (i = w; i; i--) { /* copy pixels without mask */ 624 | *(unsigned short*)dst = *(unsigned short*)src; 625 | dst += 2; 626 | src -= 2; 627 | } 628 | } 629 | dst += inc1; 630 | src += inc2; 631 | } 632 | break; 633 | 634 | /* flip in 24 bits colors depth */ 635 | case 3: 636 | if (((unsigned char*)&endian)[0] != 0x44) key24 = mask; 637 | else key24 = ((mask & 0xFFFF) << 8) | ((mask >> 16) & 0xFF); 638 | p1 = (unsigned char*)dst; 639 | p2 = (unsigned char*)src; 640 | for (; h; h--) { /* copy each scanline */ 641 | if (flag & IBLIT_MASK) { 642 | if (longsize == 4) { /* 32/16 BIT PLATFORM */ 643 | for (i = w; i; i--) { /* copy each pixel with mask */ 644 | c = (((unsigned long)(*(unsigned short*)p2)) << 8); 645 | if ((c | p2[2]) != key24) { 646 | p1[0] = p2[0]; 647 | p1[1] = p2[1]; 648 | p1[2] = p2[2]; 649 | } 650 | p1 += 3; 651 | p2 -= 3; 652 | } 653 | } 654 | else if (isize == 4) { /* 64 BIT PLATFORM */ 655 | imask = (unsigned int)(key24 & 0xffffffff); 656 | for (i = w; i; i--) { /* copy each pixel with mask */ 657 | k = (((unsigned int)(*(unsigned short*)p2)) << 8); 658 | if ((k | p2[2]) != imask) { 659 | p1[0] = p2[0]; 660 | p1[1] = p2[1]; 661 | p1[2] = p2[2]; 662 | } 663 | p1 += 3; 664 | p2 -= 3; 665 | } 666 | } 667 | } else { /* copy pixels without mask */ 668 | for (i = w; i; i--) { 669 | p1[0] = p2[0]; 670 | p1[1] = p2[1]; 671 | p1[2] = p2[2]; 672 | p1 += 3; 673 | p2 -= 3; 674 | } 675 | } 676 | p1 += inc1; 677 | p2 += inc2; 678 | } 679 | break; 680 | 681 | /* flip in 32 bits colors depth */ 682 | case 4: 683 | for (; h; h--) { 684 | if (longsize == 4) { /* 32/16 BIT PLATFORM */ 685 | if (flag & IBLIT_MASK) { 686 | for (i = w; i; i--) { /* copy each pixel with mask */ 687 | if (*(unsigned long*)src != mask) 688 | *(unsigned long*)dst = *(unsigned long*)src; 689 | dst += 4; 690 | src -= 4; 691 | } 692 | } else { 693 | for (i = w; i; i--) { /* copy pixels without mask */ 694 | *(unsigned long*)dst = *(unsigned long*)src; 695 | dst += 4; 696 | src -= 4; 697 | } 698 | } 699 | } 700 | else if (isize == 4) { /* 64 BIT PLATFORM */ 701 | imask = (unsigned int)(mask & 0xffffffff); 702 | if (flag & IBLIT_MASK) { 703 | for (i = w; i; i--) { /* copy each pixel with mask */ 704 | if (*(unsigned int*)src != imask) 705 | *(unsigned int*)dst = *(unsigned int*)src; 706 | dst += 4; 707 | src -= 4; 708 | } 709 | } else { 710 | for (i = w; i; i--) { /* copy pixels without mask */ 711 | *(unsigned int*)dst = *(unsigned int*)src; 712 | dst += 4; 713 | src -= 4; 714 | } 715 | } 716 | } 717 | dst += inc1; 718 | src += inc2; 719 | } 720 | break; 721 | } 722 | 723 | return 0; 724 | } 725 | 726 | 727 | 728 | /* 729 | * ibitmap_setmask - change mask(colorkey) of the bitmap 730 | * when blit with IBLIT_MASK, this value can be used as the key color to 731 | * transparent. you can change bmp->mask directly without calling it. 732 | */ 733 | int ibitmap_setmask(struct IBITMAP *bmp, unsigned long mask) 734 | { 735 | bmp->mask = mask; 736 | return 0; 737 | } 738 | 739 | 740 | /********************************************************************** 741 | * FILLER DEFINITION 742 | **********************************************************************/ 743 | int ibitmap_fillc(char *dst, long pitch, int w, int h, int pixsize, 744 | unsigned long c); 745 | 746 | /* set filler interface to default filler (c version) */ 747 | ibitmap_filler ibitmap_filling = ibitmap_fillc; 748 | 749 | 750 | /* ibitmap_fill - fill the rectangle with given color 751 | * returns zero for successful, others for error 752 | * dst - dest bitmap to draw on 753 | * dx, dy - target position of dest bitmap to draw on 754 | * w, h - width and height of the rectangle to be filled 755 | * col - indicate the color to fill the rectangle 756 | */ 757 | int ibitmap_fill(struct IBITMAP *dst, int dx, int dy, int w, int h, 758 | unsigned long col, int noclip) 759 | { 760 | int pixsize, r; 761 | long delta; 762 | char *pixel; 763 | 764 | assert(dst); 765 | if (noclip == 0) { 766 | if (dx >= (long)dst->w || dx + w <= 0 || w < 0) return 0; 767 | if (dy >= (long)dst->h || dy + h <= 0 || h < 0) return 0; 768 | if (dx < 0) w += dx, dx = 0; 769 | if (dy < 0) h += dy, dy = 0; 770 | if (dx + w >= (long)dst->w) w = (long)dst->w - dx; 771 | if (dy + h >= (long)dst->h) h = (long)dst->h - dy; 772 | } 773 | 774 | /* get pixel size */ 775 | pixsize = (dst->bpp + 7) >> 3; 776 | 777 | /* choose linear offset */ 778 | switch (pixsize) { 779 | case 1: delta = dx; break; 780 | case 2: delta = (dx << 1); break; 781 | case 3: delta = (dx << 1) + dx; break; 782 | case 4: delta = (dx << 2); break; 783 | default: delta = dx * pixsize; break; 784 | } 785 | 786 | /* get the first scanlines of the bitmap */ 787 | pixel = (char*)dst->line[dy] + delta; 788 | 789 | r = ibitmap_filling(pixel, dst->pitch, w, h, pixsize, col); 790 | if (r) ibitmap_fillc(pixel, dst->pitch, w, h, pixsize, col); 791 | 792 | return 0; 793 | } 794 | 795 | 796 | /********************************************************************** 797 | * ibitmap_blitfc - default blitter for flip blit 798 | **********************************************************************/ 799 | int ibitmap_fillc(char *dst, long pitch, int w, int h, int pixsize, 800 | unsigned long col) 801 | { 802 | static unsigned long endian = 0x11223344; 803 | unsigned short col16; 804 | unsigned char col8, c1, c2, c3; 805 | unsigned long *p32; 806 | unsigned int k, *k32; 807 | long longsize, isize; 808 | long inc, i; 809 | 810 | longsize = sizeof(long); 811 | isize = sizeof(int); 812 | 813 | switch (pixsize) 814 | { 815 | /* fill for 8 bits color depth */ 816 | case 1: 817 | col8 = (unsigned char)(col & 0xff); 818 | for (; h; h--) { 819 | memset(dst, col8, w); 820 | dst += pitch; 821 | } 822 | break; 823 | 824 | /* fill for 15/16 bits color depth */ 825 | case 2: 826 | col16 = (unsigned short)(col & 0xffff); 827 | col = (col << 16) | (col & 0xffff); 828 | if (longsize == 4) { /* 32/16 BIT PLATFORM */ 829 | for (; h; h--) { 830 | p32 = (unsigned long*)dst; 831 | for (i = w >> 1; i; i--) *p32++ = col; 832 | if (w & 1) *(unsigned short*)p32 = col16; 833 | dst += pitch; 834 | } 835 | } 836 | else if (isize == 4) { /* 64 BIT PLATFORM */ 837 | k = (unsigned int)(col & 0xffffffff); 838 | for (; h; h--) { 839 | k32 = (unsigned int*)dst; 840 | for (i = w >> 1; i; i--) *k32++ = k; 841 | if (w & 1) *(unsigned short*)k32 = col16; 842 | dst += pitch; 843 | } 844 | } 845 | break; 846 | 847 | /* fill for 24 bits color depth */ 848 | case 3: 849 | inc = pitch - ((w << 1) + w); 850 | if (((unsigned char*)&endian)[0] != 0x44) { 851 | c1 = (unsigned char)((col >> 16) & 0xff); 852 | c2 = (unsigned char)((col >> 8) & 0xff); 853 | c3 = (unsigned char)(col & 0xff); 854 | } else { 855 | c1 = (unsigned char)(col & 0xff); 856 | c2 = (unsigned char)((col >> 8) & 0xff); 857 | c3 = (unsigned char)((col >> 16) & 0xff); 858 | } 859 | for (; h; h--) { 860 | for (i = w; i; i--) { 861 | *dst++ = c1; 862 | *dst++ = c2; 863 | *dst++ = c3; 864 | } 865 | dst += inc; 866 | } 867 | break; 868 | 869 | /* fill for 32 bits color depth */ 870 | case 4: 871 | if (longsize == 4) { /* 32/16 BIT PLATFORM */ 872 | for (; h; h--) { 873 | p32 = (unsigned long*)dst; 874 | for (i = w; i; i--) *p32++ = col; 875 | dst += pitch; 876 | } 877 | } 878 | else if (isize == 4) { /* 64 BIT PLATFORM */ 879 | k = (unsigned int)(col & 0xffffffff); 880 | for (; h; h--) { 881 | k32 = (unsigned int*)dst; 882 | for (i = w; i; i--) *k32++ = k; 883 | dst += pitch; 884 | } 885 | } 886 | break; 887 | } 888 | 889 | return 0; 890 | } 891 | 892 | 893 | /* ibitmap_stretch - copies a bitmap from a source rectangle into a 894 | * destination rectangle, stretching or compressing the bitmap to fit 895 | * the dimensions of the destination rectangle 896 | * returns zero for successful, others for invalid rectangle 897 | * dst - dest bitmap to draw on 898 | * dx, dy - target rectangle position of dest bitmap to draw on 899 | * dw, dh - target rectangle width and height in dest bitmap 900 | * src - source bitmap 901 | * sx, sy - source rectangle position in source bitmap 902 | * sw, sh - source rectangle width and height in source bitmap 903 | * mode - flags of IBLIT_MASK, IBLIT_HFLIP, IBLIT_VFLIP... 904 | * it uses bresenham like algorithm instead of fixed point or indexing 905 | * to avoid integer size overflow and memory allocation, just use it 906 | * when you don't have a stretch function. 907 | */ 908 | int ibitmap_stretch(struct IBITMAP *dst, int dx, int dy, int dw, int dh, 909 | const struct IBITMAP *src, int sx, int sy, int sw, int sh, int mode) 910 | { 911 | int dstwidth, dstheight, dstwidth2, dstheight2, srcwidth2, srcheight2; 912 | int werr, herr, incx, incy, i, j, nbytes; 913 | static unsigned long endian = 0x11223344; 914 | unsigned long mask, key24; 915 | long longsize, isize; 916 | 917 | /* check whether parametes is error */ 918 | assert(src && dst); 919 | assert(src->bpp == dst->bpp); 920 | 921 | if (src->bpp != dst->bpp) 922 | return -10; 923 | 924 | if (dw == sw && dh == sh) { 925 | mode |= IBLIT_CLIP; 926 | return ibitmap_blit(dst, dx, dy, src, sx, sy, sw, sh, mode); 927 | } 928 | 929 | if (dx < 0 || dx + dw > (int)dst->w || dy < 0 || dy + dh > (int)dst->h || 930 | sx < 0 || sx + sw > (int)src->w || sy < 0 || sy + sh > (int)src->h || 931 | sh <= 0 || sw <= 0 || dh <= 0 || dw <= 0) 932 | return -20; 933 | 934 | dstwidth = dw; 935 | dstheight = dh; 936 | dstwidth2 = dw * 2; 937 | dstheight2 = dh * 2; 938 | srcwidth2 = sw * 2; 939 | srcheight2 = sh * 2; 940 | 941 | if (mode & IBLIT_VFLIP) sy = sy + sh - 1, incy = -1; 942 | else incy = 1; 943 | 944 | herr = srcheight2 - dstheight2; 945 | nbytes = (src->bpp + 7) / 8; 946 | 947 | isize = sizeof(int); 948 | longsize = sizeof(long); 949 | mask = (unsigned long)src->mask; 950 | 951 | for (j = 0; j < dstheight; j++) { 952 | const unsigned char *srcrow = (const unsigned char*)src->line[sy]; 953 | unsigned char *dstrow = (unsigned char*)dst->line[dy]; 954 | const unsigned char *srcpix = srcrow + nbytes * sx; 955 | unsigned char *dstpix = dstrow + nbytes * dx; 956 | incx = nbytes; 957 | if (mode & IBLIT_HFLIP) { 958 | srcpix += (sw - 1) * nbytes; 959 | incx = -nbytes; 960 | } 961 | werr = srcwidth2 - dstwidth2; 962 | 963 | switch (nbytes) 964 | { 965 | case 1: 966 | { 967 | unsigned char mask8; 968 | if ((mode & IBLIT_MASK) == 0) { 969 | for (i = dstwidth; i > 0; i--) { 970 | *dstpix++ = *srcpix; 971 | while (werr >= 0) { 972 | srcpix += incx, werr -= dstwidth2; 973 | } 974 | werr += srcwidth2; 975 | } 976 | } else { 977 | mask8 = (unsigned char)(src->mask & 0xff); 978 | for (i = dstwidth; i > 0; i--) { 979 | if (*srcpix != mask8) *dstpix = *srcpix; 980 | dstpix++; 981 | while (werr >= 0) { 982 | srcpix += incx, werr -= dstwidth2; 983 | } 984 | werr += srcwidth2; 985 | } 986 | } 987 | } 988 | break; 989 | 990 | case 2: 991 | { 992 | unsigned short mask16; 993 | if ((mode & IBLIT_MASK) == 0) { 994 | for (i = dstwidth; i > 0; i--) { 995 | *((unsigned short*)dstpix) = 996 | *((unsigned short*)srcpix); 997 | dstpix += 2; 998 | while (werr >= 0) { 999 | srcpix += incx, werr -= dstwidth2; 1000 | } 1001 | werr += srcwidth2; 1002 | } 1003 | } else { 1004 | mask16 = (unsigned short)(src->mask & 0xffff); 1005 | for (i = dstwidth; i > 0; i--) { 1006 | if (*((unsigned short*)srcpix) != mask16) 1007 | *((unsigned short*)dstpix) = 1008 | *((unsigned short*)srcpix); 1009 | dstpix += 2; 1010 | while (werr >= 0) { 1011 | srcpix += incx, werr -= dstwidth2; 1012 | } 1013 | werr += srcwidth2; 1014 | } 1015 | } 1016 | } 1017 | break; 1018 | 1019 | case 3: 1020 | if (((unsigned char*)&endian)[0] != 0x44) key24 = mask; 1021 | else key24 = ((mask & 0xFFFF) << 8) | ((mask >> 16) & 0xFF); 1022 | if ((mode & IBLIT_MASK) == 0) { 1023 | for (i = dstwidth; i > 0; i--) { 1024 | dstpix[0] = srcpix[0]; 1025 | dstpix[1] = srcpix[1]; 1026 | dstpix[2] = srcpix[2]; 1027 | dstpix += 3; 1028 | while (werr >= 0) { 1029 | srcpix += incx, werr -= dstwidth2; 1030 | } 1031 | werr += srcwidth2; 1032 | } 1033 | } 1034 | else if (longsize == 4) { 1035 | unsigned long longmask, k; 1036 | longmask = key24 & 0xffffff; 1037 | for (i = dstwidth; i > 0; i--) { 1038 | k = (((unsigned long)(*(unsigned short*)srcpix)) << 8); 1039 | if ((k | srcpix[2]) != longmask) { 1040 | dstpix[0] = srcpix[0]; 1041 | dstpix[1] = srcpix[1]; 1042 | dstpix[2] = srcpix[2]; 1043 | } 1044 | dstpix += 3; 1045 | while (werr >= 0) { 1046 | srcpix += incx, werr -= dstwidth2; 1047 | } 1048 | werr += srcwidth2; 1049 | } 1050 | } 1051 | else if (isize == 4) { 1052 | unsigned int imask, k; 1053 | imask = key24 & 0xffffff; 1054 | for (i = dstwidth; i > 0; i--) { 1055 | k = (((unsigned int)(*(unsigned short*)srcpix)) << 8); 1056 | if ((k | srcpix[2]) != imask) { 1057 | dstpix[0] = srcpix[0]; 1058 | dstpix[1] = srcpix[1]; 1059 | dstpix[2] = srcpix[2]; 1060 | } 1061 | dstpix += 3; 1062 | while (werr >= 0) { 1063 | srcpix += incx, werr -= dstwidth2; 1064 | } 1065 | werr += srcwidth2; 1066 | } 1067 | } 1068 | break; 1069 | 1070 | case 4: 1071 | if (longsize == 4) { 1072 | unsigned long masklong; 1073 | if ((mode & IBLIT_MASK) == 0) { 1074 | for (i = dstwidth; i > 0; i--) { 1075 | *((unsigned long*)dstpix) = 1076 | *((unsigned long*)srcpix); 1077 | dstpix += 4; 1078 | while (werr >= 0) { 1079 | srcpix += incx, werr -= dstwidth2; 1080 | } 1081 | werr += srcwidth2; 1082 | } 1083 | } else { 1084 | masklong = (unsigned long)(src->mask); 1085 | for (i = dstwidth; i > 0; i--) { 1086 | if (*((unsigned long*)srcpix) != masklong) 1087 | *((unsigned long*)dstpix) = 1088 | *((unsigned long*)srcpix); 1089 | dstpix += 4; 1090 | while (werr >= 0) { 1091 | srcpix += incx, werr -= dstwidth2; 1092 | } 1093 | werr += srcwidth2; 1094 | } 1095 | } 1096 | } 1097 | else if (isize == 4) { 1098 | unsigned int maskint; 1099 | if ((mode & IBLIT_MASK) == 0) { 1100 | for (i = dstwidth; i > 0; i--) { 1101 | *((unsigned int*)dstpix) = *((unsigned int*)srcpix); 1102 | dstpix += 4; 1103 | while (werr >= 0) { 1104 | srcpix += incx, werr -= dstwidth2; 1105 | } 1106 | werr += srcwidth2; 1107 | } 1108 | } else { 1109 | maskint = (unsigned int)(src->mask); 1110 | for (i = dstwidth; i > 0; i--) { 1111 | if (*((unsigned int*)srcpix) != maskint) 1112 | *((unsigned int*)dstpix) = 1113 | *((unsigned int*)srcpix); 1114 | dstpix += 4; 1115 | while (werr >= 0) { 1116 | srcpix += incx, werr -= dstwidth2; 1117 | } 1118 | werr += srcwidth2; 1119 | } 1120 | } 1121 | } 1122 | else { 1123 | assert(0); 1124 | } 1125 | break; 1126 | } 1127 | 1128 | while (herr >= 0) { 1129 | sy += incy, herr -= dstheight2; 1130 | } 1131 | 1132 | herr += srcheight2; 1133 | dy++; 1134 | } 1135 | 1136 | return 0; 1137 | } 1138 | 1139 | 1140 | 1141 | /* 1142 | * ibitmap_funcset - set basic bitmap functions, returns zero for successful 1143 | * mode - function index, there are two blitters, (0/1 normal/transparent) 1144 | * proc - extra function pointer, set it to null to use default method 1145 | * there are two blitters, normal blitter and transparent blitter, which 1146 | * ibitmap_blit will call to complete blit operation. see ibitmapm.c 1147 | */ 1148 | int ibitmap_funcset(int functionid, const void *proc) 1149 | { 1150 | typedef void*(*icmalloc_t)(size_t); 1151 | typedef void (*icfree_t)(void*ptr); 1152 | 1153 | switch (functionid) 1154 | { 1155 | case IBITMAP_BLITER_NORM: 1156 | ibitmap_blitn = (proc == NULL)? ibitmap_blitnc : 1157 | (ibitmap_blitter_norm)proc; 1158 | break; 1159 | case IBITMAP_BLITER_MASK: 1160 | ibitmap_blitm = (proc == NULL)? ibitmap_blitmc : 1161 | (ibitmap_blitter_mask)proc; 1162 | break; 1163 | case IBITMAP_BLITER_FLIP: 1164 | ibitmap_blitf = (proc == NULL)? ibitmap_blitfc : 1165 | (ibitmap_blitter_flip)proc; 1166 | break; 1167 | case IBITMAP_FILLER: 1168 | ibitmap_filling = (proc == NULL)? ibitmap_fillc : 1169 | (ibitmap_filler)proc; 1170 | break; 1171 | case IBITMAP_MALLOC: 1172 | icmalloc = (proc == NULL)? malloc : (icmalloc_t)proc; 1173 | break; 1174 | case IBITMAP_FREE: 1175 | icfree = (proc == NULL)? free : (icfree_t)proc; 1176 | break; 1177 | default: 1178 | assert(0); 1179 | break; 1180 | } 1181 | return 0; 1182 | } 1183 | 1184 | 1185 | /* 1186 | * ibitmap_funcget - get the blitter function pointer, returns the address 1187 | * of the blitter function, and returns NULL for error. for more information 1188 | * please see the comment of ibitmap_funcset. 1189 | */ 1190 | void *ibitmap_funcget(int functionid, int version) 1191 | { 1192 | void *proc = NULL; 1193 | switch (functionid) 1194 | { 1195 | case IBITMAP_BLITER_NORM: 1196 | proc = (version)? (void*)ibitmap_blitnc : (void*)ibitmap_blitn; 1197 | break; 1198 | case IBITMAP_BLITER_MASK: 1199 | proc = (version)? (void*)ibitmap_blitmc : (void*)ibitmap_blitm; 1200 | break; 1201 | case IBITMAP_BLITER_FLIP: 1202 | proc = (version)? (void*)ibitmap_blitfc : (void*)ibitmap_blitf; 1203 | break; 1204 | case IBITMAP_FILLER: 1205 | proc = (version)? (void*)ibitmap_fillc : (void*)ibitmap_filling; 1206 | break; 1207 | } 1208 | return proc; 1209 | } 1210 | 1211 | 1212 | -------------------------------------------------------------------------------- /pixellib/ibitmap.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * 3 | * ibitmap.h - the basic definition of the bitmap 4 | * 5 | * IBITMAP is designed under the desire that it can exactly describe 6 | * one basic bitmap, which is considered as simple and pure. 7 | * 8 | * there are five basic bitmap operating interfaces: 9 | * 10 | * create - create a new bitmap and return the struct address 11 | * release - free the bitmap 12 | * blit - copy the speciafied rectangle from one bitmap to another 13 | * setmask - set the color key for transparent blit (IBLIT_MASK on) 14 | * fill - fill a rectange in the bitmap 15 | * 16 | * the history of this file: 17 | * Feb. 7 2003 skywind created including create/release/blit 18 | * Dec. 15 2004 skywind add filling 19 | * 20 | * aim to keep it simply and stupid, this file will only provide the 21 | * most basic bitmap operation interfaces. pixel format declearation, 22 | * color components modification must not be included in it. 23 | * 24 | * aim to platform independence, all of the sources are writen in ansi 25 | * c but you can replace the default blitter by ibitmap_funcset() to 26 | * optimized the benchmark of ibitmap_blit in the speciafied platform 27 | * 28 | **********************************************************************/ 29 | 30 | #ifndef __IBITMAP_H__ 31 | #define __IBITMAP_H__ 32 | 33 | 34 | /********************************************************************** 35 | * IBITMAP DECLEARATION 36 | **********************************************************************/ 37 | 38 | struct IBITMAP 39 | { 40 | unsigned long w; /* width of the bitmap */ 41 | unsigned long h; /* height of the bitmap */ 42 | unsigned long bpp; /* color depth of bitmap */ 43 | unsigned long pitch; /* pitch of the bitmap */ 44 | unsigned long mask; /* bitmap bit flags */ 45 | unsigned long mode; /* additional mode data */ 46 | unsigned long code; /* bitmap class code */ 47 | void *pixel; /* pixels data in bitmap */ 48 | void *extra; /* extra data structure */ 49 | void **line; /* pointer to each line in bitmap */ 50 | }; 51 | 52 | 53 | 54 | /********************************************************************** 55 | * Bitmap Global Interface 56 | **********************************************************************/ 57 | #ifndef IBLIT_CLIP 58 | #define IBLIT_CLIP 1 /* blit mode: enable clip */ 59 | #endif 60 | 61 | #ifndef IBLIT_MASK 62 | #define IBLIT_MASK 2 /* blit mode: enable transparent blit */ 63 | #endif 64 | 65 | #ifndef IBLIT_HFLIP 66 | #define IBLIT_HFLIP 4 /* flip horizon */ 67 | #endif 68 | 69 | #ifndef IBLIT_VFLIP 70 | #define IBLIT_VFLIP 8 /* flip vertical */ 71 | #endif 72 | 73 | 74 | #ifdef __cplusplus 75 | extern "C" { 76 | #endif 77 | 78 | 79 | 80 | /********************************************************************** 81 | * Bitmap Function Definition 82 | **********************************************************************/ 83 | 84 | /* 85 | * ibitmap_create - create bitmap and return the pointer to struct IBITMAP 86 | * width - bitmap width 87 | * height - bitmap height 88 | * bpp - bitmap color depth (8, 16, 24, 32) 89 | */ 90 | struct IBITMAP *ibitmap_create(int width, int height, int bpp); 91 | 92 | 93 | /* 94 | * ibitmap_release - release bitmap 95 | * bmp - pointer to the IBITMAP struct 96 | */ 97 | void ibitmap_release(struct IBITMAP *bmp); 98 | 99 | 100 | /* 101 | * ibitmap_clip - clip the rectangle from the src clip and dst clip then 102 | * caculate a new rectangle which is shared between dst and src cliprect: 103 | * clipdst - dest clip array (left, top, right, bottom) 104 | * clipsrc - source clip array (left, top, right, bottom) 105 | * (x, y) - dest position 106 | * rectsrc - source rect 107 | * mode - check IBLIT_HFLIP or IBLIT_VFLIP 108 | * return zero for successful, return non-zero if there is no shared part 109 | */ 110 | int ibitmap_clip(const int *clipdst, const int *clipsrc, int *x, int *y, 111 | int *rectsrc, int mode); 112 | 113 | 114 | /* 115 | * ibitmap_blit - blit from source bitmap to dest bitmap 116 | * returns zero for successful, others for error 117 | * dst - dest bitmap to draw on 118 | * x, y - target position of dest bitmap to draw on 119 | * src - source bitmap 120 | * sx, sy - source rectangle position in source bitmap 121 | * w, h - source rectangle width and height in source bitmap 122 | * mode - flags of IBLIT_CLIP, IBLIT_MASK, IBLIT_HFLIP, IBLIT_VFLIP... 123 | */ 124 | int ibitmap_blit(struct IBITMAP *dst, int x, int y, 125 | const struct IBITMAP *src, int sx, int sy, int w, int h, int mode); 126 | 127 | 128 | /* 129 | * ibitmap_setmask - change mask(colorkey) of the bitmap 130 | * when blit with IBLIT_MASK, this value can be used as the key color to 131 | * transparent. you can change bmp->mask directly without calling it. 132 | */ 133 | int ibitmap_setmask(struct IBITMAP *bmp, unsigned long mask); 134 | 135 | 136 | /* ibitmap_fill - fill the rectangle with given color 137 | * returns zero for successful, others for error 138 | * dst - dest bitmap to draw on 139 | * dx, dy - target position of dest bitmap to draw on 140 | * w, h - width and height of the rectangle to be filled 141 | * col - indicate the color to fill the rectangle 142 | */ 143 | int ibitmap_fill(struct IBITMAP *dst, int dx, int dy, int w, int h, 144 | unsigned long col, int noclip); 145 | 146 | 147 | /* ibitmap_stretch - copies a bitmap from a source rectangle into a 148 | * destination rectangle, stretching or compressing the bitmap to fit 149 | * the dimensions of the destination rectangle 150 | * returns zero for successful, others for invalid rectangle 151 | * dst - dest bitmap to draw on 152 | * dx, dy - target rectangle position of dest bitmap to draw on 153 | * dw, dh - target rectangle width and height in dest bitmap 154 | * src - source bitmap 155 | * sx, sy - source rectangle position in source bitmap 156 | * sw, sh - source rectangle width and height in source bitmap 157 | * mode - flags of IBLIT_MASK, IBLIT_HFLIP, IBLIT_VFLIP... 158 | * it uses bresenham like algorithm instead of fixed point or indexing 159 | * to avoid integer size overflow and memory allocation, just use it 160 | * when you don't have a stretch function. 161 | */ 162 | int ibitmap_stretch(struct IBITMAP *dst, int dx, int dy, int dw, int dh, 163 | const struct IBITMAP *src, int sx, int sy, int sw, int sh, int mode); 164 | 165 | 166 | /********************************************************************** 167 | * Bitmap Basic Interface 168 | **********************************************************************/ 169 | typedef int (*ibitmap_blitter_norm)(char *, long, const char *, long, 170 | int, int, int, long); 171 | typedef int (*ibitmap_blitter_mask)(char *, long, const char *, long, 172 | int, int, int, long, unsigned long); 173 | 174 | typedef int (*ibitmap_blitter_flip)(char *, long, const char *, long, 175 | int, int, int, long, unsigned long, int); 176 | 177 | typedef int (*ibitmap_filler)(char *, long, int, int, int, unsigned long); 178 | 179 | 180 | #define IBITMAP_BLITER_NORM 0 181 | #define IBITMAP_BLITER_MASK 1 182 | #define IBITMAP_BLITER_FLIP 2 183 | 184 | #define IBITMAP_FILLER 3 185 | 186 | #define IBITMAP_MALLOC 4 187 | #define IBITMAP_FREE 5 188 | 189 | 190 | 191 | /* 192 | * ibitmap_funcset - set basic bitmap functions, returns zero for successful 193 | * mode - function index, there are two blitters, (0/1 normal/transparent) 194 | * proc - extra function pointer, set it to null to use default method: 195 | * int imyblitter0(char *dst, long pitch1, const char *src, long pitch2, 196 | * int w, int h, int pixelbyte, long linesize); 197 | * int imyblitter1(char *dst, long pitch1, const char *src, long pitch2 198 | * int w, int h, int pixelbyte, unsigned long mask, long linesize); 199 | * there are two blitters, normal blitter and transparent blitter, which 200 | * ibitmap_blit() will call to complete blit operation. 201 | */ 202 | int ibitmap_funcset(int functionid, const void *proc); 203 | 204 | 205 | /* 206 | * ibitmap_funcget - get the blitter function pointer, returns the address 207 | * of the blitter function, and returns NULL for error. for more information 208 | * please see the comment of ibitmap_funcset. 209 | */ 210 | void *ibitmap_funcget(int functionid, int version); 211 | 212 | 213 | #ifdef __cplusplus 214 | } 215 | #endif 216 | 217 | 218 | #endif 219 | 220 | 221 | 222 | -------------------------------------------------------------------------------- /pixellib/iblit386.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // iblit386.h - bitmap blitters implemention in i386 4 | // 5 | // - bypasse on-chip, write directly into combining buffer 6 | // - software prefetch instruction 7 | // - improvement: speed up 200% - 250% vs tradition blitters 8 | // - compile it with gcc, msvc, borlandc, watcomc, ... 9 | // 10 | // for more information about cache-control instructions please see: 11 | // The IA-32 Intel Architecture Software Developer's Manual 12 | // Volume 3: System Programming Guide 13 | // with the URL below: 14 | // http://developer.intel.com/design/pentium4/manuals/253668.htm 15 | // Using Block Prefetch for Optimized Memory Performance, Mike Wall 16 | // 17 | // history of this file: 18 | // - Feb.15 2004 skywind create this file with iblit_386, iblit_mmx 19 | // - Feb.20 2004 skywind add most i386 assembler globals 20 | // - Jun.17 2004 skywind implement normal blitter with sse 21 | // - May.05 2005 skywind implement mask blitter with mmx & sse 22 | // - Aug.02 2005 skywind improve blitters with cache-control tech. 23 | // - Dec.11 2006 skywind rewrite cpu detection method 24 | // - Dec.27 2006 skywind rewrite mask blitters 25 | // - Jan.28 2007 skywind reform this file with new comment 26 | // - Sep.09 2010 skywind add 64bits & mmx macros 27 | // - Oct.03 2010 skywind amd64 supported 28 | // 29 | //===================================================================== 30 | 31 | #ifndef __IBLIT386_H__ 32 | #define __IBLIT386_H__ 33 | 34 | #include 35 | 36 | 37 | //--------------------------------------------------------------------- 38 | // platform detection 39 | //--------------------------------------------------------------------- 40 | #if (defined(_WIN32) && !defined(WIN32)) 41 | #define WIN32 _WIN32 42 | #elif (defined(WIN32) && !defined(_WIN32)) 43 | #define _WIN32 WIN32 44 | #endif 45 | 46 | #if (defined(_WIN32) && !defined(_MSC_VER) && !defined(_WIN64)) 47 | #ifndef __i386__ 48 | #define __i386__ 49 | #endif 50 | #elif defined(_MSC_VER) 51 | #if (defined(_M_IX86) && !defined(__i386__)) 52 | #define __i386__ 53 | #endif 54 | #endif 55 | 56 | #ifndef __i386__ 57 | #if (defined(__386__) || defined(__I386__) || _M_IX86) 58 | #define __i386__ 59 | #endif 60 | #endif 61 | 62 | #if (defined(__i386__) && !defined(__I386__)) 63 | #define __I386__ 64 | #endif 65 | 66 | #if (defined(__x86_64__) && !defined(__x86_64)) 67 | #define __x86_64 68 | #endif 69 | 70 | #if (defined(__x86_64) && !defined(__x86_64__)) 71 | #define __x86_64__ 72 | #endif 73 | 74 | #if (defined(_M_AMD64)) && (!defined(__amd64__)) 75 | #define __amd64__ 76 | #endif 77 | 78 | #if (defined(__amd64) && !defined(__amd64__)) 79 | #define __amd64__ 80 | #endif 81 | 82 | #if (defined(__amd64__) && !defined(__amd64)) 83 | #define __amd64 84 | #endif 85 | 86 | #if (defined(__i386__) || defined(__amd64__)) && (!defined(__x86__)) 87 | #if !(defined(_MSC_VER) && defined(__amd64__)) 88 | #define __x86__ // MSVC doesn't support inline assembly in x64 89 | #endif 90 | #endif 91 | 92 | //===================================================================== 93 | // i386 archtech support 94 | //===================================================================== 95 | #ifdef __x86__ 96 | 97 | 98 | #ifndef ASMCODE 99 | #define ASMCODE 100 | //--------------------------------------------------------------------- 101 | // basic inline asm operation code generation 102 | //--------------------------------------------------------------------- 103 | #ifdef __GNUC__ 104 | #define ASMCODE1(a) ".byte "#a"\n" 105 | #define ASMCODE2(a, b) ".byte "#a", "#b"\n" 106 | #define ASMCODE3(a, b, c) ".byte "#a", "#b", "#c"\n" 107 | #define ASMCODE4(a, b, c, d) ".byte "#a", "#b", "#c", "#d"\n" 108 | #define ASMCODE5(a, b, c, d, e) ".byte "#a", "#b", "#c", "#d", "#e"\n" 109 | #define ASMCODEW(n) ".short "#n"\n" 110 | #define ASMCODED(n) ".long "#n"\n" 111 | #define ASMALIGN(n) ".align "#n", 0x90\n" 112 | #define __ALIGNC__ ASMALIGN(8) 113 | #define __INLINEGNU__ 114 | #ifndef __MACH__ 115 | #define ASM_BEGIN 116 | #define ASM_ENDUP 117 | #ifdef __i386__ 118 | #define ASM_REGS "esi", "edi", "eax", "ebx", "ecx", "edx" 119 | #else 120 | #define ASM_REGS "rsi", "rdi", "rax", "rbx", "rcx", "rdx" 121 | #endif 122 | #else 123 | #ifdef __i386__ 124 | #define ASM_BEGIN " pushl %%ebx\n" 125 | #define ASM_ENDUP " popl %%ebx\n" 126 | #define ASM_REGS "esi", "edi", "eax", "ecx", "edx" 127 | #else 128 | #define ASM_BEGIN " push %%rbx\n" 129 | #define ASM_ENDUP " pop %%rbx\n" 130 | #define ASM_REGS "rsi", "rdi", "rax", "rcx", "rdx" 131 | #endif 132 | #endif 133 | 134 | #elif defined(_MSC_VER) 135 | #define ASMCODE1(a) _asm _emit (a) 136 | #define ASMCODE2(a, b) ASMCODE1(a) ASMCODE1(b) 137 | #define ASMCODE3(a, b, c) ASMCODE2(a, b) ASMCODE1(c) 138 | #define ASMCODE4(a, b, c, d) ASMCODE3(a, b, c) ASMCODE1(d) 139 | #define ASMCODE5(a, b, c, d, e) ASMCODE4(a, b, c, d) ASMCODE1(e) 140 | #define ASMCODEW(n) ASMCODE2(((n) AND 0xff), ((n) / 0x100)) 141 | #define ASMCODED(n) ASMCODEW(n) ASMCODEW((n) / 0x10000) 142 | #define ASMALIGN(n) ALIGN n 143 | #define __ALIGNC__ ASMALIGN(8) 144 | #define __INLINEMSC__ 145 | #define ASM_BEGIN 146 | #define ASM_ENDUP 147 | 148 | #elif (defined(__BORLANDC__) || defined(__WATCOMC__)) 149 | #define ASMCODE1(a) DB a; 150 | #define ASMCODE2(a, b) DB a, b; 151 | #define ASMCODE3(a, b, c) DB a, b, c; 152 | #define ASMCODE4(a, b, c, d) DB a, b, c, d; 153 | #define ASMCODE5(a, b, c, d, e) DB a, b, c, d, e; 154 | #define ASMCODEW(n) DW n; 155 | #define ASMCODED(n) DD n; 156 | #define ASMALIGN(n) ALIGN n 157 | #pragma warn -8002 158 | #pragma warn -8004 159 | #pragma warn -8008 160 | #pragma warn -8012 161 | #pragma warn -8027 162 | #pragma warn -8057 163 | #pragma warn -8066 164 | #define __ALIGNC__ ASMALIGN(4) 165 | #define __INLINEMSC__ 166 | //#ifdef __WATCOMC__ 167 | #undef __ALIGNC__ 168 | #define __ALIGNC__ 169 | //#endif 170 | #define ASM_BEGIN 171 | #define ASM_ENDUP 172 | #endif 173 | #endif 174 | 175 | 176 | #ifndef ASM_MMPREFETCH 177 | #define ASM_MMPREFETCH 178 | //--------------------------------------------------------------------- 179 | // cache instructions operation code generation - SSE only 180 | //--------------------------------------------------------------------- 181 | #define mm_prefetch_esi ASMCODE3(0x0f, 0x18, 0x06) 182 | #define mm_prefetch_edi ASMCODE3(0x0f, 0x18, 0x07) 183 | #define mm_sfence ASMCODE3(0x0f, 0xae, 0xf8) 184 | #endif 185 | 186 | 187 | //--------------------------------------------------------------------- 188 | // transform instructions operation code generation - SSE only 189 | //--------------------------------------------------------------------- 190 | #define mm_maskmovq(MMA, MMB) ASMCODE3(0x0f, 0xf7, 0xc0 | ((MMA)<<3)|(MMB) ) 191 | #define mm_maskmovq_0_2 ASMCODE3(0x0f, 0xf7, 0xC2) 192 | #define mm_maskmovq_1_3 ASMCODE3(0x0f, 0xf7, 0xCB) 193 | 194 | 195 | #ifndef ASM_MMPREFETCHX 196 | #define ASM_MMPREFETCHX 197 | //--------------------------------------------------------------------- 198 | // cache instructions extended operation code generation - SSE only 199 | //--------------------------------------------------------------------- 200 | #define mm_prefetch_esi_n(n) ASMCODE3(0x0f, 0x18, 0x86) ASMCODED(n) 201 | #define mm_prefetch_edi_n(n) ASMCODE3(0x0f, 0x18, 0x87) ASMCODED(n) 202 | #define mm_prefetch_esi_8cx_n(n) ASMCODE4(0x0f,0x18,0x84,0xce) ASMCODED(n) 203 | #define mm_prefetch_esi_8dx ASMCODE4(0x0f, 0x18, 0x04, 0xd6) 204 | #define mm_prefetch_edi_8dx ASMCODE4(0x0f, 0x18, 0x04, 0xd7) 205 | #ifdef __WATCOMC__ 206 | #undef mm_prefetch_esi_n 207 | #undef mm_prefetch_edi_n 208 | #undef mm_prefetch_esi_8cx_n 209 | #define mm_prefetch_esi_n(n) DD 0x86180f90, n 210 | #define mm_prefetch_edi_n(n) DD 0x86180f90, n 211 | #define mm_prefetch_esi_8cx_n(n) DD 0xCE84180f, n 212 | #endif 213 | #endif 214 | 215 | //--------------------------------------------------------------------- 216 | // data instructions operation code generation - SSE only 217 | //--------------------------------------------------------------------- 218 | #define mm_movntq_edi_0_m0 ASMCODE3(0x0f, 0xe7, 0x07) 219 | #define mm_movntq_edi_8_m1 ASMCODE4(0x0f, 0xe7, 0x4f, 0x08) 220 | #define mm_movntq_edi_16_m2 ASMCODE4(0x0f, 0xe7, 0x57, 0x10) 221 | #define mm_movntq_edi_24_m3 ASMCODE4(0x0f, 0xe7, 0x5f, 0x18) 222 | #define mm_movntq_edi_32_m4 ASMCODE4(0x0f, 0xe7, 0x67, 0x20) 223 | #define mm_movntq_edi_40_m5 ASMCODE4(0x0f, 0xe7, 0x6f, 0x28) 224 | #define mm_movntq_edi_48_m6 ASMCODE4(0x0f, 0xe7, 0x77, 0x30) 225 | #define mm_movntq_edi_56_m7 ASMCODE4(0x0f, 0xe7, 0x7f, 0x38) 226 | 227 | 228 | //--------------------------------------------------------------------- 229 | // data instructions operation code generation - SSE only 230 | //--------------------------------------------------------------------- 231 | #define mm_movntq_edi_8cx_0_m0 ASMCODE4(0x0f, 0xe7, 0x04, 0xcf) 232 | #define mm_movntq_edi_8cx_8_m1 ASMCODE5(0x0f, 0xe7, 0x4c, 0xcf, 0x08) 233 | #define mm_movntq_edi_8cx_16_m2 ASMCODE5(0x0f, 0xe7, 0x54, 0xcf, 0x10) 234 | #define mm_movntq_edi_8cx_24_m3 ASMCODE5(0x0f, 0xe7, 0x5c, 0xcf, 0x18) 235 | #define mm_movntq_edi_8cx_32_m4 ASMCODE5(0x0f, 0xe7, 0x64, 0xcf, 0x20) 236 | #define mm_movntq_edi_8cx_40_m5 ASMCODE5(0x0f, 0xe7, 0x6c, 0xcf, 0x28) 237 | #define mm_movntq_edi_8cx_48_m6 ASMCODE5(0x0f, 0xe7, 0x74, 0xcf, 0x30) 238 | #define mm_movntq_edi_8cx_56_m7 ASMCODE5(0x0f, 0xe7, 0x7c, 0xcf, 0x38) 239 | 240 | 241 | #define _MMX_FEATURE_BIT 0x00800000 242 | #define _SSE_FEATURE_BIT 0x02000000 243 | #define _SSE2_FEATURE_BIT 0x04000000 244 | #define _3DNOW_FEATURE_BIT 0x80000000 245 | 246 | #ifdef __cplusplus 247 | extern "C" { 248 | #endif 249 | 250 | //--------------------------------------------------------------------- 251 | // X86 FEATURE DEFINITION 252 | //--------------------------------------------------------------------- 253 | #define X86_FEATURE_FPU (0*32+ 0) /* Onboard FPU */ 254 | #define X86_FEATURE_VME (0*32+ 1) /* Virtual Mode Extensions */ 255 | #define X86_FEATURE_DE (0*32+ 2) /* Debugging Extensions */ 256 | #define X86_FEATURE_TSC (0*32+ 4) /* Time Stamp Counter */ 257 | #define X86_FEATURE_MSR (0*32+ 5) /* Model-Specific Registers */ 258 | #define X86_FEATURE_PAE (0*32+ 6) /* Physical Address Extensions */ 259 | #define X86_FEATURE_MCE (0*32+ 7) /* Machine Check Architecture */ 260 | #define X86_FEATURE_CX8 (0*32+ 8) /* CMPXCHG8 instruction */ 261 | #define X86_FEATURE_MCA (0*32+14) /* Machine Check Architecture */ 262 | #define X86_FEATURE_CMOV (0*32+15) /* CMOV (FCMOVCC/FCOMI too if FPU) */ 263 | #define X86_FEATURE_PAT (0*32+16) /* Page Attribute Table */ 264 | #define X86_FEATURE_PSE36 (0*32+17) /* 36-bit PSEs */ 265 | #define X86_FEATURE_CLFLSH (0*32+19) /* Supports the CLFLUSH instruction */ 266 | #define X86_FEATURE_MMX (0*32+23) /* Multimedia Extensions */ 267 | #define X86_FEATURE_XMM (0*32+25) /* Streaming SIMD Extensions */ 268 | #define X86_FEATURE_XMM2 (0*32+26) /* Streaming SIMD Extensions-2 */ 269 | #define X86_FEATURE_SELFSNOOP (0*32+27) /* CPU self snoop */ 270 | #define X86_FEATURE_HT (0*32+28) /* Hyper-Threading */ 271 | #define X86_FEATURE_ACC (0*32+29) /* Automatic clock control */ 272 | #define X86_FEATURE_IA64 (0*32+30) /* IA-64 processor */ 273 | 274 | #define X86_FEATURE_MP (1*32+19) /* MP Capable. */ 275 | #define X86_FEATURE_NX (1*32+20) /* Execute Disable */ 276 | #define X86_FEATURE_MMXEXT (1*32+22) /* AMD MMX extensions */ 277 | #define X86_FEATURE_LM (1*32+29) /* Long Mode (x86-64) */ 278 | #define X86_FEATURE_3DNOWEXT (1*32+30) /* AMD 3DNow! extensions */ 279 | #define X86_FEATURE_3DNOW (1*32+31) /* 3DNow! */ 280 | 281 | #define X86_FEATURE_CXMMX (3*32+ 0) /* Cyrix MMX extensions */ 282 | #define X86_FEATURE_K6_MTRR (3*32+ 1) /* AMD K6 nonstandard MTRRs */ 283 | #define X86_FEATURE_CYRIX_ARR (3*32+ 2) /* Cyrix ARRs (= MTRRs) */ 284 | #define X86_FEATURE_CENTAUR_MCR (3*32+ 3) /* Centaur MCRs (= MTRRs) */ 285 | #define X86_FEATURE_K8 (3*32+ 4) /* Opteron, Athlon64 */ 286 | #define X86_FEATURE_K7 (3*32+ 5) /* Athlon */ 287 | #define X86_FEATURE_P3 (3*32+ 6) /* P3 */ 288 | #define X86_FEATURE_P4 (3*32+ 7) /* P4 */ 289 | #define X86_FEATURE_EST (4*32+ 7) /* Enhanced SpeedStep */ 290 | #define X86_FEATURE_MWAIT (4*32+ 3) /* Monitor/Mwait support */ 291 | 292 | #define X86_VENDOR_INTEL 0 293 | #define X86_VENDOR_CYRIX 1 294 | #define X86_VENDOR_AMD 2 295 | #define X86_VENDOR_UMC 3 296 | #define X86_VENDOR_NEXGEN 4 297 | #define X86_VENDOR_CENTAUR 5 298 | #define X86_VENDOR_RISE 6 299 | #define X86_VENDOR_TRANSMETA 7 300 | #define X86_VENDOR_NSC 8 301 | #define X86_VENDOR_NUM 9 302 | #define X86_VENDOR_SIS 10 303 | #define X86_VENDOR_UNKNOWN 0xff 304 | 305 | 306 | //--------------------------------------------------------------------- 307 | // cpu global information 308 | //--------------------------------------------------------------------- 309 | extern unsigned int _cpu_feature[]; 310 | extern unsigned int _cpu_cachesize; 311 | extern int _cpu_level; 312 | extern int _cpu_device; 313 | extern int _cpu_vendor; 314 | extern char _cpu_vendor_name[]; 315 | extern int _cpu_cache_l1i; 316 | extern int _cpu_cache_l1d; 317 | extern int _cpu_cache_l2; 318 | 319 | #define _TEST_BIT(p, x) (((unsigned int*)(p))[(x) >> 5] & (1 << ((x) & 31))) 320 | #define X86_FEATURE(x) _TEST_BIT(_cpu_feature, x) 321 | 322 | #ifndef IMASK32 323 | #define IMASK32 unsigned long 324 | #endif 325 | 326 | #ifndef ISRCPTR 327 | #define ISRCPTR const char * 328 | #endif 329 | 330 | #ifdef __amd64__ 331 | typedef unsigned int IDWORD; 332 | typedef unsigned long IQWORD; 333 | #else 334 | typedef unsigned long IDWORD; 335 | #if defined(_MSC_VER) || defined(__BORLANDC__) 336 | typedef unsigned __int64 IQWORD; 337 | #else 338 | typedef unsigned long long IQWORD; 339 | #endif 340 | #endif 341 | 342 | #ifndef __IULONG_DEFINED 343 | #define __IULONG_DEFINED 344 | typedef ptrdiff_t ilong; 345 | typedef size_t iulong; 346 | #endif 347 | 348 | void _x86_cpuid(int op, int *eax, int *ebx, int *ecx, int *edx); 349 | void _x86_detect(void); 350 | 351 | void _x86_choose_blitter(void); 352 | 353 | int iblit_386(char*, long, const char*, long, int, int, int, long); 354 | int iblit_mmx(char*, long, const char*, long, int, int, int, long); 355 | int iblit_sse(char*, long, const char*, long, int, int, int, long); 356 | int iblit_mix(char*, long, const char*, long, int, int, int, long); 357 | 358 | int iblit_mask_mmx(char*, long, ISRCPTR, long, int, int, int, long, IMASK32); 359 | int iblit_mask_sse(char*, long, ISRCPTR, long, int, int, int, long, IMASK32); 360 | int iblit_mask_mix(char*, long, ISRCPTR, long, int, int, int, long, IMASK32); 361 | 362 | 363 | #ifdef __cplusplus 364 | } 365 | #endif 366 | 367 | 368 | 369 | //===================================================================== 370 | // MMX INLINE INSTRUCTIONS 371 | //===================================================================== 372 | #if defined(__GNUC__) 373 | #define immx_op(op) \ 374 | __asm__ __volatile__ (#op "" : : : "memory") 375 | #define immx_op_r_r(op, regd, regs) \ 376 | __asm__ __volatile__ (#op " %%" #regs ", %%" #regd "" : : : "memory") 377 | #define immx_op_r_i(op, regd, imm) \ 378 | __asm__ __volatile__ (#op " %0, %%" #regd : : "i"(imm) : "memory") 379 | #define immx_op_r_m(op, regd, mem) \ 380 | __asm__ __volatile__ (#op " %0, %%" #regd : : "m"(*(mem)) : "memory") 381 | #define immx_op_m_r(op, mem, regs) \ 382 | __asm__ __volatile__ (#op " %%" #regs ", %0" : "=X"(*(mem)) : : "memory") 383 | #define immx_op_r_m32(op, regd, mem32) \ 384 | immx_op_r_m(op, regd, mem32) 385 | #define immx_op_m32_r(op, mem32, regs) \ 386 | immx_op_m_r(op, mem32, regs) 387 | #define immx_op_r_v(op, regd, vars) \ 388 | immx_op_r_m(op, regd, (&(vars))) 389 | #define immx_op_v_r(op, vard, regs) \ 390 | immx_op_m_r(op, (&(vard)), regs) 391 | typedef unsigned long long immx_uint64; 392 | typedef unsigned int immx_uint32; 393 | typedef long long immx_int64; 394 | typedef int immx_int32; 395 | #define immx_const_uint64(__imm__) (__imm__ ## ULL) 396 | #define immx_const_int64(__imm__) (__imm__ ## LL) 397 | #elif defined(_MSC_VER) || defined(__BORLANDC__) 398 | #define immx_op(op) \ 399 | _asm { op } 400 | #define immx_op_r_r(op, regd, regs) \ 401 | _asm { op regd, regs } 402 | #define immx_op_r_i(op, regd, imm) \ 403 | _asm { op regd, imm } 404 | #define immx_op_r_m(op, regd, mem) \ 405 | { register __int64 var = *(__int64*)(mem); _asm { op regd, var } } 406 | #define immx_op_m_r(op, mem, regs) \ 407 | { register __int64 var; _asm { op var, regs }; *(__int64*)(mem) = var; } 408 | #define immx_op_r_m32(op, regd, mem32) \ 409 | { register int var = *(int*)(mem32); _asm { op regd, var } } 410 | #define immx_op_m32_r(op, mem32, regs) \ 411 | { register int var; _asm { op var, regs }; *(int*)(mem32) = var; } 412 | #define immx_op_r_v(op, regd, vars) \ 413 | _asm { op regd, vars } 414 | #define immx_op_v_r(op, vard, regs) \ 415 | _asm { op vard, regs } 416 | typedef unsigned __int64 immx_uint64; 417 | typedef unsigned int immx_uint32; 418 | typedef __int64 immx_int64; 419 | typedef int immx_int32; 420 | #define immx_const_uint64(__imm__) (__imm__ ## UI64) 421 | #define immx_const_int64(__imm__) (__imm__ ## I64) 422 | #endif 423 | 424 | 425 | 426 | //--------------------------------------------------------------------- 427 | // MMX Instruction Tracing 428 | //--------------------------------------------------------------------- 429 | #ifdef immx_op 430 | 431 | typedef union { 432 | immx_uint64 uq; 433 | immx_int64 q; 434 | immx_uint32 ud[2]; 435 | immx_int32 d[2]; 436 | unsigned short uw[4]; 437 | short w[4]; 438 | unsigned char ub[8]; 439 | char b[8]; 440 | float s[2]; 441 | } immx_t; 442 | 443 | #define immx_op_trace(op) { \ 444 | printf(#op "\n"); \ 445 | immx_op(op); \ 446 | } 447 | 448 | #define immx_op_m_m(op, memd, mems) { \ 449 | immx_op_r_m(movq, mm0, memd); \ 450 | immx_op_r_m(op, mm0, mems); \ 451 | immx_op_m_r(movq, memd, mm0); \ 452 | } 453 | 454 | #define immx_op_m32_m32(op, memd, mems) { \ 455 | immx_op_r_m32(movd, mm0, memd); \ 456 | immx_op_r_m32(movd, mm1, mems); \ 457 | immx_op_r_r(op, mm0, mm1); \ 458 | immx_op_m_r(movd, memd, mm0); \ 459 | } 460 | 461 | #define immx_op_trace_r_r(op, regd, regs) { \ 462 | immx_t mmx_trace; \ 463 | immx_op_m_r(movq, &mmx_trace, regd); \ 464 | printf(#op "_r_r(" #regd "=0x%08x%08x, ", \ 465 | mmx_trace.d[1], mmx_trace.d[0]); \ 466 | immx_op_m_r(movq, &mmx_trace, regs); \ 467 | printf(#regs "=0x%08x%08x) => ", \ 468 | mmx_trace.d[1], mmx_trace.d[0]); \ 469 | immx_op_r_r(op, regd, regs); \ 470 | immx_op_m_r(movq, &mmx_trace, regd); \ 471 | printf(#regd "=0x%08x%08x\n", \ 472 | mmx_trace.d[1], mmx_trace.d[0]); \ 473 | } 474 | 475 | #define immx_op_trace_r_i(op, regd, imm) { \ 476 | immx_t mmx_trace; \ 477 | immx_op_m_r(movq, &mmx_trace, regd); \ 478 | printf(#op "_r_i(" #regd "=0x%08x%08x, ", \ 479 | mmx_trace.d[1], mmx_trace.d[0]); \ 480 | mmx_trace.uq = (imm); \ 481 | printf(#imm "=0x%08x%08x) => ", \ 482 | mmx_trace.d[1], mmx_trace.d[0]); \ 483 | immx_op_r_i(op, regd, imm); \ 484 | immx_op_m_r(movq, &mmx_trace, regd); \ 485 | printf(#regd "=0x%08x%08x\n", \ 486 | mmx_trace.d[1], mmx_trace.d[0]); \ 487 | } 488 | 489 | #define immx_op_trace_r_m(op, regd, mem) { \ 490 | immx_t mmx_trace; \ 491 | immx_op_m_r(movq, &mmx_trace, regd); \ 492 | printf(#op "_r_m(" #regd "=0x%08x%08x, ", \ 493 | mmx_trace.d[1], mmx_trace.d[0]); \ 494 | mmx_trace.uq = *(immx_int64*)(mem); \ 495 | printf(#mem "=0x%08x%08x) => ", \ 496 | mmx_trace.d[1], mmx_trace.d[0]); \ 497 | immx_op_r_m(op, regd, mem); \ 498 | immx_op_m_r(movq, &mmx_trace, regd); \ 499 | printf(#regd "=0x%08x%08x\n", \ 500 | mmx_trace.d[1], mmx_trace.d[0]); \ 501 | } 502 | 503 | #define immx_op_trace_m_r(op, mem, regs) { \ 504 | immx_t mmx_trace; \ 505 | mmx_trace.uq = *(immx_int64*)(mem); \ 506 | printf(#op "_m_r(" #mem "=0x%08x%08x, ", \ 507 | mmx_trace.d[1], mmx_trace.d[0]); \ 508 | immx_op_m_r(movq, &mmx_trace, regs); \ 509 | printf(#regs "=0x%08x%08x) => ", \ 510 | mmx_trace.d[1], mmx_trace.d[0]); \ 511 | immx_op_m_r(op, mem, regs); \ 512 | mmx_trace.uq = *(immx_int64*)(mem); \ 513 | printf(#mem "=0x%08x%08x\n", \ 514 | mmx_trace.d[1], mmx_trace.d[0]); \ 515 | } 516 | 517 | #define immx_op_trace_r_m32(op, regd, mem) { \ 518 | immx_t mmx_trace; \ 519 | immx_op_m_r(movq, &mmx_trace, regd); \ 520 | printf(#op "_r_m32(" #regd "=0x%08x%08x, ", \ 521 | mmx_trace.d[1], mmx_trace.d[0]); \ 522 | mmx_trace.d[0] = *(immx_int32*)(mem); \ 523 | mmx_trace.d[1] = 0; \ 524 | printf(#mem "=0x%08x%08x) => ", \ 525 | mmx_trace.d[1], mmx_trace.d[0]); \ 526 | immx_op_r_m32(op, regd, mem); \ 527 | immx_op_m_r(movq, &mmx_trace, regd); \ 528 | printf(#regd "=0x%08x%08x\n", \ 529 | mmx_trace.d[1], mmx_trace.d[0]); \ 530 | } 531 | 532 | #define immx_op_trace_m32_r(op, mem, regs) { \ 533 | immx_t mmx_trace; \ 534 | mmx_trace.d[0] = *(immx_int32*)(mem); \ 535 | mmx_trace.d[1] = 0; \ 536 | printf(#op "_m32_r(" #mem "=0x%08x%08x, ", \ 537 | mmx_trace.d[1], mmx_trace.d[0]); \ 538 | immx_op_m_r(movq, &mmx_trace, regs); \ 539 | printf(#regs "=0x%08x%08x) => ", \ 540 | mmx_trace.d[1], mmx_trace.d[0]); \ 541 | immx_op_m32_r(op, mem, regs); \ 542 | mmx_trace.d[0] = *(immx_int32*)(mem); \ 543 | mmx_trace.d[1] = 0; \ 544 | printf(#mem "=0x%08x%08x\n", \ 545 | mmx_trace.d[1], mmx_trace.d[0]); \ 546 | } 547 | 548 | #define immx_op_trace_m_m(op, memd, mems) { \ 549 | immx_t mmx_trace1, mmx_trace2; \ 550 | immx_op_r_m(movq, mm0, memd); \ 551 | immx_op_r_m(movq, mm1, mems); \ 552 | immx_op_m_r(movq, &mmx_trace1, mm0); \ 553 | immx_op_m_r(movq, &mmx_trace2, mm1); \ 554 | printf(#op "_m_m(" #memd "=0x%08x%08x, ", \ 555 | mmx_trace1.d[1], mmx_trace1.d[0]); \ 556 | printf(#mems "=0x%08x%08x) => ", \ 557 | mmx_trace2.d[1], mmx_trace2.d[0]); \ 558 | immx_op_m_m(op, memd, mems); \ 559 | immx_op_r_m(movq, mm0, memd); \ 560 | immx_op_m_r(movq, &mmx_trace1, mm0); \ 561 | printf(#memd "=0x%08x%08x\n", \ 562 | mmx_trace1.d[1], mmx_trace1.d[0]); \ 563 | } 564 | 565 | #define immx_op_trace_m32_m32(op, memd, mems) { \ 566 | immx_t mmx_trace1, mmx_trace2; \ 567 | immx_op_r_m32(movd, mm0, memd); \ 568 | immx_op_r_m32(movd, mm1, mems); \ 569 | immx_op_m_r(movq, immx_addr(mmx_trace1), mm0); \ 570 | immx_op_m_r(movq, immx_addr(mmx_trace2), mm1); \ 571 | printf(#op "_m_m(" #memd "=0x%08x, ", mmx_trace1.d[0]); \ 572 | printf(#mems "=0x%08x) => ", mmx_trace2.d[0]); \ 573 | immx_op_m_m(op, memd, mems); \ 574 | immx_op_r_m32(movd, mm0, memd); \ 575 | immx_op_m_r(movq, immx_addr(mmx_trace1), mm0); \ 576 | printf(#memd "=0x%08x\n", mmx_trace1.d[0]); \ 577 | } 578 | 579 | #define immx_op_trace_r_v(op, regd, vars) { \ 580 | immx_t mmx_trace; \ 581 | immx_op_m_r(movq, &mmx_trace, regd); \ 582 | printf(#op "_r_v(" #regd "=0x%08x%08x, ", \ 583 | mmx_trace.d[1], mmx_trace.d[0]); \ 584 | mmx_trace.uq = (immx_int64)(vars); \ 585 | printf(#vars "=0x%08x%08x) => ", \ 586 | mmx_trace.d[1], mmx_trace.d[0]); \ 587 | immx_op_r_v(op, regd, vars); \ 588 | immx_op_m_r(movq, &mmx_trace, regd); \ 589 | printf(#regd "=0x%08x%08x\n", \ 590 | mmx_trace.d[1], mmx_trace.d[0]); \ 591 | } 592 | 593 | #define immx_op_trace_v_r(op, vard, regs) { \ 594 | immx_t mmx_trace; \ 595 | mmx_trace.uq = (immx_int64)(vard); \ 596 | printf(#op "_v_r(" #vard "=0x%08x%08x, ", \ 597 | mmx_trace.d[1], mmx_trace.d[0]); \ 598 | immx_op_m_r(movq, &mmx_trace, regs); \ 599 | printf(#regs "=0x%08x%08x) => ", \ 600 | mmx_trace.d[1], mmx_trace.d[0]); \ 601 | immx_op_v_r(op, vard, regs); \ 602 | mmx_trace.uq = (immx_int64)(vard); \ 603 | printf(#vard "=0x%08x%08x\n", \ 604 | mmx_trace.d[1], mmx_trace.d[0]); \ 605 | } 606 | 607 | #define immx_trace_print_reg(regs) { \ 608 | immx_t mmx_trace; \ 609 | immx_op_m_r(movq, immx_addr(mmx_trace), regs); \ 610 | printf(#regs "=0x%08x%08x\n", \ 611 | mmx_trace.d[1], mmx_trace.d[0]); \ 612 | } 613 | 614 | #endif 615 | 616 | 617 | #ifndef IMMX_TRACE 618 | #define immx_inst(op) immx_op(op) 619 | #define immx_inst_r_r(op, regd, regs) immx_op_r_r(op, regd, regs) 620 | #define immx_inst_r_i(op, regd, imm) immx_op_r_i(op, regd, imm) 621 | #define immx_inst_r_m(op, regd, mem) immx_op_r_m(op, regd, mem) 622 | #define immx_inst_m_r(op, mem, regs) immx_op_m_r(op, mem, regs) 623 | #define immx_inst_r_m32(op, regd, mem) immx_op_r_m32(op, regd, mem) 624 | #define immx_inst_m32_r(op, mem, regs) immx_op_m32_r(op, mem, regs) 625 | #define immx_inst_r_v(op, regd, vars) immx_op_r_v(op, regd, vars) 626 | #define immx_inst_v_r(op, vard, regs) immx_op_v_r(op, vard, regs) 627 | #define immx_inst_m_m(op, memd, mems) immx_op_m_m(op, memd, mems) 628 | #define immx_inst_m32_m32(op, m1, m2) immx_op_m32_m32(op, m1, m2) 629 | #define immx_trace_reg(reg) 630 | #else 631 | #define immx_inst(op) immx_op_trace(op) 632 | #define immx_inst_r_r(op, regd, regs) immx_op_trace_r_r(op, regd, regs) 633 | #define immx_inst_r_i(op, regd, imm) immx_op_trace_r_i(op, regd, imm) 634 | #define immx_inst_r_m(op, regd, mem) immx_op_trace_r_m(op, regd, mem) 635 | #define immx_inst_m_r(op, mem, regs) immx_op_trace_m_r(op, mem, regs) 636 | #define immx_inst_r_m32(op, regd, mem) immx_op_trace_r_m32(op, regd, mem) 637 | #define immx_inst_m32_r(op, mem, regs) immx_op_trace_m32_r(op, mem, regs) 638 | #define immx_inst_r_v(op, regd, vars) immx_op_trace_r_v(op, regd, vars) 639 | #define immx_inst_v_r(op, vard, regs) immx_op_trace_v_r(op, vard, regs) 640 | #define immx_inst_m_m(op, memd, mems) immx_op_trace_m_m(op, memd, mems) 641 | #define immx_inst_m32_m32(op, m1, m2) immx_op_trace_m32_m32(op, m1, m2) 642 | #define immx_trace_reg(reg) immx_trace_print_reg(reg) 643 | #endif 644 | 645 | 646 | //--------------------------------------------------------------------- 647 | // MMX instructions (generated by python) 648 | //--------------------------------------------------------------------- 649 | #define movq_r_r(regd, regs) immx_inst_r_r(movq, regd, regs) 650 | #define movq_r_m(regd, mem) immx_inst_r_m(movq, regd, mem) 651 | #define movq_m_r(mem, regs) immx_inst_m_r(movq, mem, regs) 652 | #define movq_m_m(memd, mems) immx_inst_m_m(movq, memd, mems) 653 | #define movq_r_v(regd, vars) immx_inst_r_v(movq, regd, vars) 654 | #define movq_v_r(vard, regs) immx_inst_v_r(movq, vard, regs) 655 | 656 | #define movd_r_r(regd, regs) immx_inst_r_r(movd, regd, regs) 657 | #define movd_r_m(regd, mem) immx_inst_r_m32(movd, regd, mem) 658 | #define movd_m_r(mem, regs) immx_inst_m32_r(movd, mem, regs) 659 | #define movd_m_m(memd, mems) immx_inst_m_m(movd, memd, mems) 660 | #define movd_r_v(regd, vars) immx_inst_r_v(movd, regd, vars) 661 | #define movd_v_r(vard, regs) immx_inst_v_r(movd, vard, regs) 662 | 663 | #define paddd_r_m(regd, mem) immx_inst_r_m(paddd, regd, mem) 664 | #define paddd_r_r(regd, regs) immx_inst_r_r(paddd, regd, regs) 665 | #define paddd_r_v(regd, vars) immx_inst_r_v(paddd, regd, vars) 666 | #define paddw_r_m(regd, mem) immx_inst_r_m(paddw, regd, mem) 667 | #define paddw_r_r(regd, regs) immx_inst_r_r(paddw, regd, regs) 668 | #define paddw_r_v(regd, vars) immx_inst_r_v(paddw, regd, vars) 669 | #define paddb_r_m(regd, mem) immx_inst_r_m(paddb, regd, mem) 670 | #define paddb_r_r(regd, regs) immx_inst_r_r(paddb, regd, regs) 671 | #define paddb_r_v(regd, vars) immx_inst_r_v(paddb, regd, vars) 672 | 673 | #define paddsw_r_m(regd, mem) immx_inst_r_m(paddsw, regd, mem) 674 | #define paddsw_r_r(regd, regs) immx_inst_r_r(paddsw, regd, regs) 675 | #define paddsw_r_v(regd, vars) immx_inst_r_v(paddsw, regd, vars) 676 | #define paddsb_r_m(regd, mem) immx_inst_r_m(paddsb, regd, mem) 677 | #define paddsb_r_r(regd, regs) immx_inst_r_r(paddsb, regd, regs) 678 | #define paddsb_r_v(regd, vars) immx_inst_r_v(paddsb, regd, vars) 679 | 680 | #define paddusw_r_m(regd, mem) immx_inst_r_m(paddusw, regd, mem) 681 | #define paddusw_r_r(regd, regs) immx_inst_r_r(paddusw, regd, regs) 682 | #define paddusw_r_v(regd, vars) immx_inst_r_v(paddusw, regd, vars) 683 | #define paddusb_r_m(regd, mem) immx_inst_r_m(paddusb, regd, mem) 684 | #define paddusb_r_r(regd, regs) immx_inst_r_r(paddusb, regd, regs) 685 | #define paddusb_r_v(regd, vars) immx_inst_r_v(paddusb, regd, vars) 686 | 687 | #define psubd_r_m(regd, mem) immx_inst_r_m(psubd, regd, mem) 688 | #define psubd_r_r(regd, regs) immx_inst_r_r(psubd, regd, regs) 689 | #define psubd_r_v(regd, vars) immx_inst_r_v(psubd, regd, vars) 690 | #define psubw_r_m(regd, mem) immx_inst_r_m(psubw, regd, mem) 691 | #define psubw_r_r(regd, regs) immx_inst_r_r(psubw, regd, regs) 692 | #define psubw_r_v(regd, vars) immx_inst_r_v(psubw, regd, vars) 693 | #define psubb_r_m(regd, mem) immx_inst_r_m(psubb, regd, mem) 694 | #define psubb_r_r(regd, regs) immx_inst_r_r(psubb, regd, regs) 695 | #define psubb_r_v(regd, vars) immx_inst_r_v(psubb, regd, vars) 696 | 697 | #define psubsw_r_m(regd, mem) immx_inst_r_m(psubsw, regd, mem) 698 | #define psubsw_r_r(regd, regs) immx_inst_r_r(psubsw, regd, regs) 699 | #define psubsw_r_v(regd, vars) immx_inst_r_v(psubsw, regd, vars) 700 | #define psubsb_r_m(regd, mem) immx_inst_r_m(psubsb, regd, mem) 701 | #define psubsb_r_r(regd, regs) immx_inst_r_r(psubsb, regd, regs) 702 | #define psubsb_r_v(regd, vars) immx_inst_r_v(psubsb, regd, vars) 703 | 704 | #define psubusw_r_m(regd, mem) immx_inst_r_m(psubusw, regd, mem) 705 | #define psubusw_r_r(regd, regs) immx_inst_r_r(psubusw, regd, regs) 706 | #define psubusw_r_v(regd, vars) immx_inst_r_v(psubusw, regd, vars) 707 | #define psubusb_r_m(regd, mem) immx_inst_r_m(psubusb, regd, mem) 708 | #define psubusb_r_r(regd, regs) immx_inst_r_r(psubusb, regd, regs) 709 | #define psubusb_r_v(regd, vars) immx_inst_r_v(psubusb, regd, vars) 710 | 711 | #define pmullw_r_m(regd, mem) immx_inst_r_m(pmullw, regd, mem) 712 | #define pmullw_r_r(regd, regs) immx_inst_r_r(pmullw, regd, regs) 713 | #define pmullw_r_v(regd, vars) immx_inst_r_v(pmullw, regd, vars) 714 | 715 | #define pmulhw_r_m(regd, mem) immx_inst_r_m(pmulhw, regd, mem) 716 | #define pmulhw_r_r(regd, regs) immx_inst_r_r(pmulhw, regd, regs) 717 | #define pmulhw_r_v(regd, vars) immx_inst_r_v(pmulhw, regd, vars) 718 | 719 | #define pmaddwd_r_m(regd, mem) immx_inst_r_m(pmaddwd, regd, mem) 720 | #define pmaddwd_r_r(regd, regs) immx_inst_r_r(pmaddwd, regd, regs) 721 | #define pmaddwd_r_v(regd, vars) immx_inst_r_v(pmaddwd, regd, vars) 722 | 723 | #define pand_r_m(regd, mem) immx_inst_r_m(pand, regd, mem) 724 | #define pand_r_r(regd, regs) immx_inst_r_r(pand, regd, regs) 725 | #define pand_r_v(regd, vars) immx_inst_r_v(pand, regd, vars) 726 | 727 | #define pandn_r_m(regd, mem) immx_inst_r_m(pandn, regd, mem) 728 | #define pandn_r_r(regd, regs) immx_inst_r_r(pandn, regd, regs) 729 | #define pandn_r_v(regd, vars) immx_inst_r_v(pandn, regd, vars) 730 | 731 | #define por_r_m(regd, mem) immx_inst_r_m(por, regd, mem) 732 | #define por_r_r(regd, regs) immx_inst_r_r(por, regd, regs) 733 | #define por_r_v(regd, vars) immx_inst_r_v(por, regd, vars) 734 | 735 | #define pxor_r_m(regd, mem) immx_inst_r_m(pxor, regd, mem) 736 | #define pxor_r_r(regd, regs) immx_inst_r_r(pxor, regd, regs) 737 | #define pxor_r_v(regd, vars) immx_inst_r_v(pxor, regd, vars) 738 | 739 | #define pcmpeqd_r_m(regd, mem) immx_inst_r_m(pcmpeqd, regd, mem) 740 | #define pcmpeqd_r_r(regd, regs) immx_inst_r_r(pcmpeqd, regd, regs) 741 | #define pcmpeqd_r_v(regd, vars) immx_inst_r_v(pcmpeqd, regd, vars) 742 | #define pcmpeqw_r_m(regd, mem) immx_inst_r_m(pcmpeqw, regd, mem) 743 | #define pcmpeqw_r_r(regd, regs) immx_inst_r_r(pcmpeqw, regd, regs) 744 | #define pcmpeqw_r_v(regd, vars) immx_inst_r_v(pcmpeqw, regd, vars) 745 | #define pcmpeqb_r_m(regd, mem) immx_inst_r_m(pcmpeqb, regd, mem) 746 | #define pcmpeqb_r_r(regd, regs) immx_inst_r_r(pcmpeqb, regd, regs) 747 | #define pcmpeqb_r_v(regd, vars) immx_inst_r_v(pcmpeqb, regd, vars) 748 | 749 | #define pcmpgtd_r_m(regd, mem) immx_inst_r_m(pcmpgtd, regd, mem) 750 | #define pcmpgtd_r_r(regd, regs) immx_inst_r_r(pcmpgtd, regd, regs) 751 | #define pcmpgtd_r_v(regd, vars) immx_inst_r_v(pcmpgtd, regd, vars) 752 | #define pcmpgtw_r_m(regd, mem) immx_inst_r_m(pcmpgtw, regd, mem) 753 | #define pcmpgtw_r_r(regd, regs) immx_inst_r_r(pcmpgtw, regd, regs) 754 | #define pcmpgtw_r_v(regd, vars) immx_inst_r_v(pcmpgtw, regd, vars) 755 | #define pcmpgtb_r_m(regd, mem) immx_inst_r_m(pcmpgtb, regd, mem) 756 | #define pcmpgtb_r_r(regd, regs) immx_inst_r_r(pcmpgtb, regd, regs) 757 | #define pcmpgtb_r_v(regd, vars) immx_inst_r_v(pcmpgtb, regd, vars) 758 | 759 | #define psllq_r_i(regd, imm) immx_inst_r_i(psllq, regd, imm) 760 | #define psllq_r_m(regd, mem) immx_inst_r_m(psllq, regd, mem) 761 | #define psllq_r_r(regd, regs) immx_inst_r_r(psllq, regd, regs) 762 | #define psllq_r_v(regd, vars) immx_inst_r_v(psllq, regd, vars) 763 | #define pslld_r_i(regd, imm) immx_inst_r_i(pslld, regd, imm) 764 | #define pslld_r_m(regd, mem) immx_inst_r_m(pslld, regd, mem) 765 | #define pslld_r_r(regd, regs) immx_inst_r_r(pslld, regd, regs) 766 | #define pslld_r_v(regd, vars) immx_inst_r_v(pslld, regd, vars) 767 | #define psllw_r_i(regd, imm) immx_inst_r_i(psllw, regd, imm) 768 | #define psllw_r_m(regd, mem) immx_inst_r_m(psllw, regd, mem) 769 | #define psllw_r_r(regd, regs) immx_inst_r_r(psllw, regd, regs) 770 | #define psllw_r_v(regd, vars) immx_inst_r_v(psllw, regd, vars) 771 | 772 | #define psrlq_r_i(regd, imm) immx_inst_r_i(psrlq, regd, imm) 773 | #define psrlq_r_m(regd, mem) immx_inst_r_m(psrlq, regd, mem) 774 | #define psrlq_r_r(regd, regs) immx_inst_r_r(psrlq, regd, regs) 775 | #define psrlq_r_v(regd, vars) immx_inst_r_v(psrlq, regd, vars) 776 | #define psrld_r_i(regd, imm) immx_inst_r_i(psrld, regd, imm) 777 | #define psrld_r_m(regd, mem) immx_inst_r_m(psrld, regd, mem) 778 | #define psrld_r_r(regd, regs) immx_inst_r_r(psrld, regd, regs) 779 | #define psrld_r_v(regd, vars) immx_inst_r_v(psrld, regd, vars) 780 | #define psrlw_r_i(regd, imm) immx_inst_r_i(psrlw, regd, imm) 781 | #define psrlw_r_m(regd, mem) immx_inst_r_m(psrlw, regd, mem) 782 | #define psrlw_r_r(regd, regs) immx_inst_r_r(psrlw, regd, regs) 783 | #define psrlw_r_v(regd, vars) immx_inst_r_v(psrlw, regd, vars) 784 | 785 | #define psrad_r_i(regd, imm) immx_inst_r_i(psrad, regd, imm) 786 | #define psrad_r_m(regd, mem) immx_inst_r_m(psrad, regd, mem) 787 | #define psrad_r_r(regd, regs) immx_inst_r_r(psrad, regd, regs) 788 | #define psrad_r_v(regd, vars) immx_inst_r_v(psrad, regd, vars) 789 | #define psraw_r_i(regd, imm) immx_inst_r_i(psraw, regd, imm) 790 | #define psraw_r_m(regd, mem) immx_inst_r_m(psraw, regd, mem) 791 | #define psraw_r_r(regd, regs) immx_inst_r_r(psraw, regd, regs) 792 | #define psraw_r_v(regd, vars) immx_inst_r_v(psraw, regd, vars) 793 | 794 | #define packssdw_r_m(regd, mem) immx_inst_r_m(packssdw, regd, mem) 795 | #define packssdw_r_r(regd, regs) immx_inst_r_r(packssdw, regd, regs) 796 | #define packssdw_r_v(regd, vars) immx_inst_r_v(packssdw, regd, vars) 797 | #define packsswb_r_m(regd, mem) immx_inst_r_m(packsswb, regd, mem) 798 | #define packsswb_r_r(regd, regs) immx_inst_r_r(packsswb, regd, regs) 799 | #define packsswb_r_v(regd, vars) immx_inst_r_v(packsswb, regd, vars) 800 | 801 | #define packuswb_r_m(regd, mem) immx_inst_r_m(packuswb, regd, mem) 802 | #define packuswb_r_r(regd, regs) immx_inst_r_r(packuswb, regd, regs) 803 | #define packuswb_r_v(regd, vars) immx_inst_r_v(packuswb, regd, vars) 804 | 805 | #define punpckldq_r_m(regd, mem) immx_inst_r_m(punpckldq, regd, mem) 806 | #define punpckldq_r_r(regd, regs) immx_inst_r_r(punpckldq, regd, regs) 807 | #define punpckldq_r_v(regd, vars) immx_inst_r_v(punpckldq, regd, vars) 808 | #define punpcklwd_r_m(regd, mem) immx_inst_r_m(punpcklwd, regd, mem) 809 | #define punpcklwd_r_r(regd, regs) immx_inst_r_r(punpcklwd, regd, regs) 810 | #define punpcklwd_r_v(regd, vars) immx_inst_r_v(punpcklwd, regd, vars) 811 | #define punpcklbw_r_m(regd, mem) immx_inst_r_m(punpcklbw, regd, mem) 812 | #define punpcklbw_r_r(regd, regs) immx_inst_r_r(punpcklbw, regd, regs) 813 | #define punpcklbw_r_v(regd, vars) immx_inst_r_v(punpcklbw, regd, vars) 814 | 815 | #define punpckhdq_r_m(regd, mem) immx_inst_r_m(punpckhdq, regd, mem) 816 | #define punpckhdq_r_r(regd, regs) immx_inst_r_r(punpckhdq, regd, regs) 817 | #define punpckhdq_r_v(regd, vars) immx_inst_r_v(punpckhdq, regd, vars) 818 | #define punpckhwd_r_m(regd, mem) immx_inst_r_m(punpckhwd, regd, mem) 819 | #define punpckhwd_r_r(regd, regs) immx_inst_r_r(punpckhwd, regd, regs) 820 | #define punpckhwd_r_v(regd, vars) immx_inst_r_v(punpckhwd, regd, vars) 821 | #define punpckhbw_r_m(regd, mem) immx_inst_r_m(punpckhbw, regd, mem) 822 | #define punpckhbw_r_r(regd, regs) immx_inst_r_r(punpckhbw, regd, regs) 823 | #define punpckhbw_r_v(regd, vars) immx_inst_r_v(punpckhbw, regd, vars) 824 | 825 | #define immx_emms() immx_inst(emms) 826 | 827 | 828 | #if (defined(__i386__) || defined(__amd64__) || defined(_M_IA64)) 829 | #if defined(immx_inst) && defined(__x86__) 830 | #define ASMMMX_ENABLE 831 | #define __asmmmx__ 832 | #endif 833 | #endif 834 | 835 | #endif 836 | 837 | #endif 838 | 839 | 840 | -------------------------------------------------------------------------------- /pixellib/ibmcols.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/pixellib/ibmcols.c -------------------------------------------------------------------------------- /pixellib/ibmcols.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/pixellib/ibmcols.h -------------------------------------------------------------------------------- /pixellib/ibmdata.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/pixellib/ibmdata.c -------------------------------------------------------------------------------- /pixellib/ibmdata.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/pixellib/ibmdata.h -------------------------------------------------------------------------------- /pixellib/ibmfont.c: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // ibmfont.c - builtin font operation 4 | // 5 | // NOTE: 6 | // for more information, please see the readme file 7 | // 8 | //===================================================================== 9 | #include "ibmfont.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | 19 | 20 | // builtin font 21 | static const unsigned char _ifont_asc16[4096] = { 22 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,126,129,165,129,129,189,153,129,129,126, 23 | 0,0,0,0,0,0,126,255,219,255,255,195,231,255,255,126,0,0,0,0,0,0,0,0,108,254, 24 | 254,254,254,124,56,16,0,0,0,0,0,0,0,0,16,56,124,254,124,56,16,0,0,0,0,0,0, 25 | 0,0,24,60,60,231,231,231,24,24,60,0,0,0,0,0,0,0,24,60,126,255,255,126,24, 26 | 24,60,0,0,0,0,0,0,0,0,0,0,24,60,60,24,0,0,0,0,0,0,255,255,255,255,255,255, 27 | 231,195,195,231,255,255,255,255,255,255,0,0,0,0,0,60,102,66,66,102,60,0,0, 28 | 0,0,0,255,255,255,255,255,195,153,189,189,153,195,255,255,255,255,255,0,0, 29 | 30,14,26,50,120,204,204,204,204,120,0,0,0,0,0,0,60,102,102,102,102,60,24, 30 | 126,24,24,0,0,0,0,0,0,63,51,63,48,48,48,48,112,240,224,0,0,0,0,0,0,127,99, 31 | 127,99,99,99,99,103,231,230,192,0,0,0,0,0,0,24,24,219,60,231,60,219,24,24, 32 | 0,0,0,0,0,128,192,224,240,248,254,248,240,224,192,128,0,0,0,0,0,2,6,14,30, 33 | 62,254,62,30,14,6,2,0,0,0,0,0,0,24,60,126,24,24,24,126,60,24,0,0,0,0,0,0, 34 | 0,102,102,102,102,102,102,102,0,102,102,0,0,0,0,0,0,127,219,219,219,123,27, 35 | 27,27,27,27,0,0,0,0,0,124,198,96,56,108,198,198,108,56,12,198,124,0,0,0,0, 36 | 0,0,0,0,0,0,0,254,254,254,254,0,0,0,0,0,0,24,60,126,24,24,24,126,60,24,126, 37 | 0,0,0,0,0,0,24,60,126,24,24,24,24,24,24,24,0,0,0,0,0,0,24,24,24,24,24,24, 38 | 24,126,60,24,0,0,0,0,0,0,0,0,0,24,12,254,12,24,0,0,0,0,0,0,0,0,0,0,0,48,96, 39 | 254,96,48,0,0,0,0,0,0,0,0,0,0,0,0,192,192,192,254,0,0,0,0,0,0,0,0,0,0,0,40, 40 | 108,254,108,40,0,0,0,0,0,0,0,0,0,0,16,56,56,124,124,254,254,0,0,0,0,0,0,0, 41 | 0,0,254,254,124,124,56,56,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 42 | 0,24,60,60,60,24,24,24,0,24,24,0,0,0,0,0,102,102,102,36,0,0,0,0,0,0,0,0,0, 43 | 0,0,0,0,0,108,108,254,108,108,108,254,108,108,0,0,0,0,24,24,124,198,194,192, 44 | 124,6,6,134,198,124,24,24,0,0,0,0,0,0,194,198,12,24,48,96,198,134,0,0,0,0, 45 | 0,0,56,108,108,56,118,220,204,204,204,118,0,0,0,0,0,48,48,48,96,0,0,0,0,0, 46 | 0,0,0,0,0,0,0,0,12,24,48,48,48,48,48,48,24,12,0,0,0,0,0,0,48,24,12,12,12, 47 | 12,12,12,24,48,0,0,0,0,0,0,0,0,0,102,60,255,60,102,0,0,0,0,0,0,0,0,0,0,0, 48 | 24,24,126,24,24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,24,24,48,0,0,0,0,0,0,0,0, 49 | 0,0,254,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,24,0,0,0,0,0,0,0,0,2,6,12, 50 | 24,48,96,192,128,0,0,0,0,0,0,56,108,198,198,214,214,198,198,108,56,0,0,0, 51 | 0,0,0,24,56,120,24,24,24,24,24,24,126,0,0,0,0,0,0,124,198,6,12,24,48,96,192, 52 | 198,254,0,0,0,0,0,0,124,198,6,6,60,6,6,6,198,124,0,0,0,0,0,0,12,28,60,108, 53 | 204,254,12,12,12,30,0,0,0,0,0,0,254,192,192,192,252,6,6,6,198,124,0,0,0,0, 54 | 0,0,56,96,192,192,252,198,198,198,198,124,0,0,0,0,0,0,254,198,6,6,12,24,48, 55 | 48,48,48,0,0,0,0,0,0,124,198,198,198,124,198,198,198,198,124,0,0,0,0,0,0, 56 | 124,198,198,198,126,6,6,6,12,120,0,0,0,0,0,0,0,0,24,24,0,0,0,24,24,0,0,0, 57 | 0,0,0,0,0,0,24,24,0,0,0,24,24,48,0,0,0,0,0,0,0,6,12,24,48,96,48,24,12,6,0, 58 | 0,0,0,0,0,0,0,0,126,0,0,126,0,0,0,0,0,0,0,0,0,0,96,48,24,12,6,12,24,48,96, 59 | 0,0,0,0,0,0,124,198,198,12,24,24,24,0,24,24,0,0,0,0,0,0,0,124,198,198,222, 60 | 222,222,220,192,124,0,0,0,0,0,0,16,56,108,198,198,254,198,198,198,198,0,0, 61 | 0,0,0,0,252,102,102,102,124,102,102,102,102,252,0,0,0,0,0,0,60,102,194,192, 62 | 192,192,192,194,102,60,0,0,0,0,0,0,248,108,102,102,102,102,102,102,108,248, 63 | 0,0,0,0,0,0,254,102,98,104,120,104,96,98,102,254,0,0,0,0,0,0,254,102,98,104, 64 | 120,104,96,96,96,240,0,0,0,0,0,0,60,102,194,192,192,222,198,198,102,58,0, 65 | 0,0,0,0,0,198,198,198,198,254,198,198,198,198,198,0,0,0,0,0,0,60,24,24,24, 66 | 24,24,24,24,24,60,0,0,0,0,0,0,30,12,12,12,12,12,204,204,204,120,0,0,0,0,0, 67 | 0,230,102,102,108,120,120,108,102,102,230,0,0,0,0,0,0,240,96,96,96,96,96, 68 | 96,98,102,254,0,0,0,0,0,0,198,238,254,254,214,198,198,198,198,198,0,0,0,0, 69 | 0,0,198,230,246,254,222,206,198,198,198,198,0,0,0,0,0,0,124,198,198,198,198, 70 | 198,198,198,198,124,0,0,0,0,0,0,252,102,102,102,124,96,96,96,96,240,0,0,0, 71 | 0,0,0,124,198,198,198,198,198,198,214,222,124,12,14,0,0,0,0,252,102,102,102, 72 | 124,108,102,102,102,230,0,0,0,0,0,0,124,198,198,96,56,12,6,198,198,124,0, 73 | 0,0,0,0,0,126,126,90,24,24,24,24,24,24,60,0,0,0,0,0,0,198,198,198,198,198, 74 | 198,198,198,198,124,0,0,0,0,0,0,198,198,198,198,198,198,198,108,56,16,0,0, 75 | 0,0,0,0,198,198,198,198,214,214,214,254,238,108,0,0,0,0,0,0,198,198,108,124, 76 | 56,56,124,108,198,198,0,0,0,0,0,0,102,102,102,102,60,24,24,24,24,60,0,0,0, 77 | 0,0,0,254,198,134,12,24,48,96,194,198,254,0,0,0,0,0,0,60,48,48,48,48,48,48, 78 | 48,48,60,0,0,0,0,0,0,0,128,192,224,112,56,28,14,6,2,0,0,0,0,0,0,60,12,12, 79 | 12,12,12,12,12,12,60,0,0,0,0,16,56,108,198,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 80 | 0,0,0,0,0,0,0,0,0,0,255,0,0,48,48,24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 81 | 120,12,124,204,204,204,118,0,0,0,0,0,0,224,96,96,120,108,102,102,102,102, 82 | 124,0,0,0,0,0,0,0,0,0,124,198,192,192,192,198,124,0,0,0,0,0,0,28,12,12,60, 83 | 108,204,204,204,204,118,0,0,0,0,0,0,0,0,0,124,198,254,192,192,198,124,0,0, 84 | 0,0,0,0,56,108,100,96,240,96,96,96,96,240,0,0,0,0,0,0,0,0,0,118,204,204,204, 85 | 204,204,124,12,204,120,0,0,0,224,96,96,108,118,102,102,102,102,230,0,0,0, 86 | 0,0,0,24,24,0,56,24,24,24,24,24,60,0,0,0,0,0,0,6,6,0,14,6,6,6,6,6,6,102,102, 87 | 60,0,0,0,224,96,96,102,108,120,120,108,102,230,0,0,0,0,0,0,56,24,24,24,24, 88 | 24,24,24,24,60,0,0,0,0,0,0,0,0,0,236,254,214,214,214,214,198,0,0,0,0,0,0, 89 | 0,0,0,220,102,102,102,102,102,102,0,0,0,0,0,0,0,0,0,124,198,198,198,198,198, 90 | 124,0,0,0,0,0,0,0,0,0,220,102,102,102,102,102,124,96,96,240,0,0,0,0,0,0,118, 91 | 204,204,204,204,204,124,12,12,30,0,0,0,0,0,0,220,118,102,96,96,96,240,0,0, 92 | 0,0,0,0,0,0,0,124,198,96,56,12,198,124,0,0,0,0,0,0,16,48,48,252,48,48,48, 93 | 48,54,28,0,0,0,0,0,0,0,0,0,204,204,204,204,204,204,118,0,0,0,0,0,0,0,0,0, 94 | 102,102,102,102,102,60,24,0,0,0,0,0,0,0,0,0,198,198,214,214,214,254,108,0, 95 | 0,0,0,0,0,0,0,0,198,108,56,56,56,108,198,0,0,0,0,0,0,0,0,0,198,198,198,198, 96 | 198,198,126,6,12,248,0,0,0,0,0,0,254,204,24,48,96,198,254,0,0,0,0,0,0,14, 97 | 24,24,24,112,24,24,24,24,14,0,0,0,0,0,0,24,24,24,24,0,24,24,24,24,24,0,0, 98 | 0,0,0,0,112,24,24,24,14,24,24,24,24,112,0,0,0,0,0,0,118,220,0,0,0,0,0,0,0, 99 | 0,0,0,0,0,0,0,0,0,16,56,108,198,198,198,254,0,0,0,0,0,0,0,60,102,194,192, 100 | 192,192,194,102,60,12,6,124,0,0,0,0,204,0,0,204,204,204,204,204,204,118,0, 101 | 0,0,0,0,12,24,48,0,124,198,254,192,192,198,124,0,0,0,0,0,16,56,108,0,120, 102 | 12,124,204,204,204,118,0,0,0,0,0,0,204,0,0,120,12,124,204,204,204,118,0,0, 103 | 0,0,0,96,48,24,0,120,12,124,204,204,204,118,0,0,0,0,0,56,108,56,0,120,12, 104 | 124,204,204,204,118,0,0,0,0,0,0,0,0,60,102,96,96,102,60,12,6,60,0,0,0,0,16, 105 | 56,108,0,124,198,254,192,192,198,124,0,0,0,0,0,0,198,0,0,124,198,254,192, 106 | 192,198,124,0,0,0,0,0,96,48,24,0,124,198,254,192,192,198,124,0,0,0,0,0,0, 107 | 102,0,0,56,24,24,24,24,24,60,0,0,0,0,0,24,60,102,0,56,24,24,24,24,24,60,0, 108 | 0,0,0,0,96,48,24,0,56,24,24,24,24,24,60,0,0,0,0,0,198,0,16,56,108,198,198, 109 | 254,198,198,198,0,0,0,0,56,108,56,0,56,108,198,198,254,198,198,198,0,0,0, 110 | 0,24,48,96,0,254,102,96,124,96,96,102,254,0,0,0,0,0,0,0,0,0,204,118,54,126, 111 | 216,216,110,0,0,0,0,0,0,62,108,204,204,254,204,204,204,204,206,0,0,0,0,0, 112 | 16,56,108,0,124,198,198,198,198,198,124,0,0,0,0,0,0,198,0,0,124,198,198,198, 113 | 198,198,124,0,0,0,0,0,96,48,24,0,124,198,198,198,198,198,124,0,0,0,0,0,48, 114 | 120,204,0,204,204,204,204,204,204,118,0,0,0,0,0,96,48,24,0,204,204,204,204, 115 | 204,204,118,0,0,0,0,0,0,198,0,0,198,198,198,198,198,198,126,6,12,120,0,0, 116 | 198,0,124,198,198,198,198,198,198,198,124,0,0,0,0,0,198,0,198,198,198,198, 117 | 198,198,198,198,124,0,0,0,0,0,24,24,60,102,96,96,96,102,60,24,24,0,0,0,0, 118 | 0,56,108,100,96,240,96,96,96,96,230,252,0,0,0,0,0,0,102,102,60,24,126,24, 119 | 126,24,24,24,0,0,0,0,0,248,204,204,248,196,204,222,204,204,204,198,0,0,0, 120 | 0,0,14,27,24,24,24,126,24,24,24,24,24,216,112,0,0,0,24,48,96,0,120,12,124, 121 | 204,204,204,118,0,0,0,0,0,12,24,48,0,56,24,24,24,24,24,60,0,0,0,0,0,24,48, 122 | 96,0,124,198,198,198,198,198,124,0,0,0,0,0,24,48,96,0,204,204,204,204,204, 123 | 204,118,0,0,0,0,0,0,118,220,0,220,102,102,102,102,102,102,0,0,0,0,118,220, 124 | 0,198,230,246,254,222,206,198,198,198,0,0,0,0,0,60,108,108,62,0,126,0,0,0, 125 | 0,0,0,0,0,0,0,56,108,108,56,0,124,0,0,0,0,0,0,0,0,0,0,0,48,48,0,48,48,96, 126 | 192,198,198,124,0,0,0,0,0,0,0,0,0,0,254,192,192,192,192,0,0,0,0,0,0,0,0,0, 127 | 0,0,254,6,6,6,6,0,0,0,0,0,0,192,192,194,198,204,24,48,96,220,134,12,24,62, 128 | 0,0,0,192,192,194,198,204,24,48,102,206,158,62,6,6,0,0,0,0,24,24,0,24,24, 129 | 24,60,60,60,24,0,0,0,0,0,0,0,0,0,54,108,216,108,54,0,0,0,0,0,0,0,0,0,0,0, 130 | 216,108,54,108,216,0,0,0,0,0,0,17,68,17,68,17,68,17,68,17,68,17,68,17,68, 131 | 17,68,85,170,85,170,85,170,85,170,85,170,85,170,85,170,85,170,221,119,221, 132 | 119,221,119,221,119,221,119,221,119,221,119,221,119,24,24,24,24,24,24,24, 133 | 24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,248,24,24,24,24,24,24,24, 134 | 24,24,24,24,24,24,248,24,248,24,24,24,24,24,24,24,24,54,54,54,54,54,54,54, 135 | 246,54,54,54,54,54,54,54,54,0,0,0,0,0,0,0,254,54,54,54,54,54,54,54,54,0,0, 136 | 0,0,0,248,24,248,24,24,24,24,24,24,24,24,54,54,54,54,54,246,6,246,54,54,54, 137 | 54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,0,0,0,0,0, 138 | 254,6,246,54,54,54,54,54,54,54,54,54,54,54,54,54,246,6,254,0,0,0,0,0,0,0, 139 | 0,54,54,54,54,54,54,54,254,0,0,0,0,0,0,0,0,24,24,24,24,24,248,24,248,0,0, 140 | 0,0,0,0,0,0,0,0,0,0,0,0,0,248,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24, 141 | 31,0,0,0,0,0,0,0,0,24,24,24,24,24,24,24,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 142 | 255,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,31,24,24,24,24,24,24,24, 143 | 24,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,24,24,24,24,24,24,24,255,24,24,24,24, 144 | 24,24,24,24,24,24,24,24,24,31,24,31,24,24,24,24,24,24,24,24,54,54,54,54,54, 145 | 54,54,55,54,54,54,54,54,54,54,54,54,54,54,54,54,55,48,63,0,0,0,0,0,0,0,0, 146 | 0,0,0,0,0,63,48,55,54,54,54,54,54,54,54,54,54,54,54,54,54,247,0,255,0,0,0, 147 | 0,0,0,0,0,0,0,0,0,0,255,0,247,54,54,54,54,54,54,54,54,54,54,54,54,54,55,48, 148 | 55,54,54,54,54,54,54,54,54,0,0,0,0,0,255,0,255,0,0,0,0,0,0,0,0,54,54,54,54, 149 | 54,247,0,247,54,54,54,54,54,54,54,54,24,24,24,24,24,255,0,255,0,0,0,0,0,0, 150 | 0,0,54,54,54,54,54,54,54,255,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,255,24,24,24, 151 | 24,24,24,24,24,0,0,0,0,0,0,0,255,54,54,54,54,54,54,54,54,54,54,54,54,54,54, 152 | 54,63,0,0,0,0,0,0,0,0,24,24,24,24,24,31,24,31,0,0,0,0,0,0,0,0,0,0,0,0,0,31, 153 | 24,31,24,24,24,24,24,24,24,24,0,0,0,0,0,0,0,63,54,54,54,54,54,54,54,54,54, 154 | 54,54,54,54,54,54,255,54,54,54,54,54,54,54,54,24,24,24,24,24,255,24,255,24, 155 | 24,24,24,24,24,24,24,24,24,24,24,24,24,24,248,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 156 | 0,31,24,24,24,24,24,24,24,24,255,255,255,255,255,255,255,255,255,255,255, 157 | 255,255,255,255,255,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,240, 158 | 240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,15,15,15,15,15, 159 | 15,15,15,15,15,15,15,15,15,15,15,255,255,255,255,255,255,255,0,0,0,0,0,0, 160 | 0,0,0,0,0,0,0,0,118,220,216,216,216,220,118,0,0,0,0,0,0,120,204,204,204,216, 161 | 204,198,198,198,204,0,0,0,0,0,0,254,198,198,192,192,192,192,192,192,192,0, 162 | 0,0,0,0,0,0,0,254,108,108,108,108,108,108,108,0,0,0,0,0,0,0,254,198,96,48, 163 | 24,48,96,198,254,0,0,0,0,0,0,0,0,0,126,216,216,216,216,216,112,0,0,0,0,0, 164 | 0,0,0,102,102,102,102,102,124,96,96,192,0,0,0,0,0,0,0,118,220,24,24,24,24, 165 | 24,24,0,0,0,0,0,0,0,126,24,60,102,102,102,60,24,126,0,0,0,0,0,0,0,56,108, 166 | 198,198,254,198,198,108,56,0,0,0,0,0,0,56,108,198,198,198,108,108,108,108, 167 | 238,0,0,0,0,0,0,30,48,24,12,62,102,102,102,102,60,0,0,0,0,0,0,0,0,0,126,219, 168 | 219,219,126,0,0,0,0,0,0,0,0,0,3,6,126,219,219,243,126,96,192,0,0,0,0,0,0, 169 | 28,48,96,96,124,96,96,96,48,28,0,0,0,0,0,0,0,124,198,198,198,198,198,198, 170 | 198,198,0,0,0,0,0,0,0,0,254,0,0,254,0,0,254,0,0,0,0,0,0,0,0,0,24,24,126,24, 171 | 24,0,0,255,0,0,0,0,0,0,0,48,24,12,6,12,24,48,0,126,0,0,0,0,0,0,0,12,24,48, 172 | 96,48,24,12,0,126,0,0,0,0,0,0,14,27,27,24,24,24,24,24,24,24,24,24,24,24,24, 173 | 24,24,24,24,24,24,24,216,216,216,112,0,0,0,0,0,0,0,0,24,24,0,126,0,24,24, 174 | 0,0,0,0,0,0,0,0,0,0,118,220,0,118,220,0,0,0,0,0,0,0,56,108,108,56,0,0,0,0, 175 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,0,0,0, 176 | 0,0,0,0,0,15,12,12,12,12,12,236,108,108,60,28,0,0,0,0,0,216,108,108,108,108, 177 | 108,0,0,0,0,0,0,0,0,0,0,112,216,48,96,200,248,0,0,0,0,0,0,0,0,0,0,0,0,0,124, 178 | 124,124,124,124,124,124,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 179 | }; 180 | 181 | 182 | static IGLYPHFONT ibuiltin_font = { 183 | 8, 16, _ifont_asc16 184 | }; 185 | 186 | 187 | void ibitmap_draw_text(IBITMAP *dst, int x, int y, const char *string, 188 | const IRECT *clip, IUINT32 color, IUINT32 back, int additive) 189 | { 190 | ibitmap_draw_ascii(dst, &ibuiltin_font, x, y, string, clip, color, back, 191 | additive); 192 | } 193 | 194 | 195 | #ifdef _MSC_VER 196 | #pragma warning(disable:4996) 197 | #endif 198 | 199 | void ibitmap_printf(IBITMAP *dst, int x, int y, const IRECT *clip, 200 | IUINT32 color, IUINT32 back, int additive, const char *fmt, ...) 201 | { 202 | char buffer[4096]; 203 | va_list argptr; 204 | va_start(argptr, fmt); 205 | vsprintf(buffer, fmt, argptr); 206 | va_end(argptr); 207 | ibitmap_draw_text(dst, x, y, buffer, clip, color, back, additive); 208 | } 209 | 210 | -------------------------------------------------------------------------------- /pixellib/ibmfont.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // ibmfont.h - builtin font operation 4 | // 5 | // NOTE: 6 | // for more information, please see the readme file 7 | // 8 | //===================================================================== 9 | #ifndef __IBMFONT_H__ 10 | #define __IBMFONT_H__ 11 | 12 | #include "ibmcols.h" 13 | 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | 20 | void ibitmap_draw_text(IBITMAP *dst, int x, int y, const char *string, 21 | const IRECT *clip, IUINT32 color, IUINT32 back, int additive); 22 | 23 | void ibitmap_printf(IBITMAP *dst, int x, int y, const IRECT *clip, 24 | IUINT32 color, IUINT32 back, int additive, const char *fmt, ...); 25 | 26 | 27 | #ifdef __cplusplus 28 | } 29 | #endif 30 | 31 | #endif 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /pixellib/ibmsse2.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/pixellib/ibmsse2.c -------------------------------------------------------------------------------- /pixellib/ibmsse2.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // ibmsse2.h - sse2 & mmx optimize 4 | // 5 | // NOTE: 6 | // for more information, please see the readme file 7 | // 8 | //===================================================================== 9 | 10 | #ifndef __IBMSSE2_H__ 11 | #define __IBMSSE2_H__ 12 | 13 | #include "ibmbits.h" 14 | 15 | 16 | 17 | //--------------------------------------------------------------------- 18 | // platform detection 19 | //--------------------------------------------------------------------- 20 | #if (defined(_WIN32) && !defined(WIN32)) 21 | #define WIN32 _WIN32 22 | #elif (defined(WIN32) && !defined(_WIN32)) 23 | #define _WIN32 WIN32 24 | #endif 25 | 26 | #if (defined(_WIN32) && !defined(_MSC_VER) && !defined(_WIN64)) 27 | #ifndef __i386__ 28 | #define __i386__ 29 | #endif 30 | #elif defined(_MSC_VER) 31 | #if (defined(_M_IX86) && !defined(__i386__)) 32 | #define __i386__ 33 | #endif 34 | #endif 35 | 36 | #ifndef __i386__ 37 | #if (defined(__386__) || defined(__I386__) || _M_IX86) 38 | #define __i386__ 39 | #endif 40 | #endif 41 | 42 | #if (defined(__i386__) && !defined(__I386__)) 43 | #define __I386__ 44 | #endif 45 | 46 | #if (defined(__x86_64__) && !defined(__x86_64)) 47 | #define __x86_64 48 | #endif 49 | 50 | #if (defined(__x86_64) && !defined(__x86_64__)) 51 | #define __x86_64__ 52 | #endif 53 | 54 | #if (defined(_M_AMD64)) && (!defined(__amd64__)) 55 | #define __amd64__ 56 | #endif 57 | 58 | #if (defined(__amd64) && !defined(__amd64__)) 59 | #define __amd64__ 60 | #endif 61 | 62 | #if (defined(__amd64__) && !defined(__amd64)) 63 | #define __amd64 64 | #endif 65 | 66 | #if (defined(__i386__) || defined(__amd64__)) && (!defined(__x86__)) 67 | #if !(defined(_MSC_VER) && defined(__amd64__)) 68 | #define __x86__ // MSVC doesn't support inline assembly in x64 69 | #endif 70 | #endif 71 | 72 | //===================================================================== 73 | // i386 archtech support 74 | //===================================================================== 75 | #ifdef __x86__ 76 | 77 | 78 | #ifndef ASMCODE 79 | #define ASMCODE 80 | //--------------------------------------------------------------------- 81 | // basic inline asm operation code generation 82 | //--------------------------------------------------------------------- 83 | #ifdef __GNUC__ 84 | #define ASMCODE1(a) ".byte "#a"\n" 85 | #define ASMCODE2(a, b) ".byte "#a", "#b"\n" 86 | #define ASMCODE3(a, b, c) ".byte "#a", "#b", "#c"\n" 87 | #define ASMCODE4(a, b, c, d) ".byte "#a", "#b", "#c", "#d"\n" 88 | #define ASMCODE5(a, b, c, d, e) ".byte "#a", "#b", "#c", "#d", "#e"\n" 89 | #define ASMCODEW(n) ".short "#n"\n" 90 | #define ASMCODED(n) ".long "#n"\n" 91 | #define ASMALIGN(n) ".align "#n", 0x90\n" 92 | #define __ALIGNC__ ASMALIGN(8) 93 | #define __INLINEGNU__ 94 | #ifndef __MACH__ 95 | #define ASM_BEGIN 96 | #define ASM_ENDUP 97 | #ifdef __i386__ 98 | #define ASM_REGS "esi", "edi", "eax", "ebx", "ecx", "edx" 99 | #else 100 | #define ASM_REGS "rsi", "rdi", "rax", "rbx", "rcx", "rdx" 101 | #endif 102 | #else 103 | #ifdef __i386__ 104 | #define ASM_BEGIN " pushl %%ebx\n" 105 | #define ASM_ENDUP " popl %%ebx\n" 106 | #define ASM_REGS "esi", "edi", "eax", "ecx", "edx" 107 | #else 108 | #define ASM_BEGIN " push %%rbx\n" 109 | #define ASM_ENDUP " pop %%rbx\n" 110 | #define ASM_REGS "rsi", "rdi", "rax", "rcx", "rdx" 111 | #endif 112 | #endif 113 | 114 | #elif defined(_MSC_VER) 115 | #define ASMCODE1(a) _asm _emit (a) 116 | #define ASMCODE2(a, b) ASMCODE1(a) ASMCODE1(b) 117 | #define ASMCODE3(a, b, c) ASMCODE2(a, b) ASMCODE1(c) 118 | #define ASMCODE4(a, b, c, d) ASMCODE3(a, b, c) ASMCODE1(d) 119 | #define ASMCODE5(a, b, c, d, e) ASMCODE4(a, b, c, d) ASMCODE1(e) 120 | #define ASMCODEW(n) ASMCODE2(((n) AND 0xff), ((n) / 0x100)) 121 | #define ASMCODED(n) ASMCODEW(n) ASMCODEW((n) / 0x10000) 122 | #define ASMALIGN(n) ALIGN n 123 | #define __ALIGNC__ ASMALIGN(8) 124 | #define __INLINEMSC__ 125 | #define ASM_BEGIN 126 | #define ASM_ENDUP 127 | 128 | #elif (defined(__BORLANDC__) || defined(__WATCOMC__)) 129 | #define ASMCODE1(a) DB a; 130 | #define ASMCODE2(a, b) DB a, b; 131 | #define ASMCODE3(a, b, c) DB a, b, c; 132 | #define ASMCODE4(a, b, c, d) DB a, b, c, d; 133 | #define ASMCODE5(a, b, c, d, e) DB a, b, c, d, e; 134 | #define ASMCODEW(n) DW n; 135 | #define ASMCODED(n) DD n; 136 | #define ASMALIGN(n) ALIGN n 137 | #pragma warn -8002 138 | #pragma warn -8004 139 | #pragma warn -8008 140 | #pragma warn -8012 141 | #pragma warn -8027 142 | #pragma warn -8057 143 | #pragma warn -8066 144 | #define __ALIGNC__ ASMALIGN(4) 145 | #define __INLINEMSC__ 146 | //#ifdef __WATCOMC__ 147 | #undef __ALIGNC__ 148 | #define __ALIGNC__ 149 | //#endif 150 | #define ASM_BEGIN 151 | #define ASM_ENDUP 152 | #endif 153 | #endif 154 | 155 | #endif 156 | 157 | //--------------------------------------------------------------------- 158 | // PLATFORM DETECT 159 | //--------------------------------------------------------------------- 160 | #if defined(__GNUC__) 161 | #if defined(__MMX__) 162 | #define __ARCH_MMX__ 163 | #endif 164 | #if defined(__SSE__) 165 | #define __ARCH_SSE__ 166 | #endif 167 | #if defined(__SSE2__) 168 | #define __ARCH_SSE2__ 169 | #endif 170 | #elif defined(_MSC_VER) && defined(__x86__) 171 | #if !(defined(WIN64) || defined(_WIN64) || defined(__x86_64)) 172 | #if _MSC_VER >= 1200 173 | #define __ARCH_MMX__ 174 | #elif _MSC_VER >= 1300 175 | #define __ARCH_SSE__ 176 | #elif _MSC_VER >= 1400 177 | #define __ARCH_SSE2__ 178 | #endif 179 | #endif 180 | #endif 181 | 182 | #ifndef __IULONG_DEFINED 183 | #define __IULONG_DEFINED 184 | typedef ptrdiff_t ilong; 185 | typedef size_t iulong; 186 | #endif 187 | 188 | #ifndef __IINT64_DEFINED 189 | #define __IINT64_DEFINED 190 | #if defined(_MSC_VER) || defined(__BORLANDC__) 191 | typedef __int64 IINT64; 192 | #else 193 | typedef long long IINT64; 194 | #endif 195 | #endif 196 | 197 | #ifndef __IUINT64_DEFINED 198 | #define __IUINT64_DEFINED 199 | #if defined(_MSC_VER) || defined(__BORLANDC__) 200 | typedef unsigned __int64 IUINT64; 201 | #else 202 | typedef unsigned long long IUINT64; 203 | #endif 204 | #endif 205 | 206 | //--------------------------------------------------------------------- 207 | // pixel load and store 208 | //--------------------------------------------------------------------- 209 | 210 | 211 | 212 | //--------------------------------------------------------------------- 213 | // INTERFACES 214 | //--------------------------------------------------------------------- 215 | #ifdef __cplusplus 216 | extern "C" { 217 | #endif 218 | 219 | int pixellib_mmx_init(void); 220 | 221 | int pixellib_xmm_init(void); 222 | 223 | #ifdef __cplusplus 224 | } 225 | #endif 226 | 227 | 228 | 229 | #endif 230 | 231 | 232 | -------------------------------------------------------------------------------- /pixellib/ibmwink.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/pixellib/ibmwink.c -------------------------------------------------------------------------------- /pixellib/ibmwink.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/pixellib/ibmwink.h -------------------------------------------------------------------------------- /pixellib/ikitwin.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/pixellib/ikitwin.c -------------------------------------------------------------------------------- /pixellib/ikitwin.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/pixellib/ikitwin.h -------------------------------------------------------------------------------- /pixellib/ipicture.c: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // ipicture.c - general picture file operation 4 | // 5 | // FEATURES: 6 | // * I/O stream support 7 | // * save and load tga/bmp/gif 8 | // 9 | // NOTE: 10 | // require ibitmap.h, ibmbits.h, ibmcols.h 11 | // for more information, please see the readme file 12 | // 13 | //===================================================================== 14 | 15 | #include "ibmbits.h" 16 | #include "ibmcols.h" 17 | #include "ipicture.h" 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | 25 | 26 | //===================================================================== 27 | // 28 | // PICTURE DATA INTERFACE 29 | // 30 | // IMDIO - Media Data Input/Output Interface 31 | // PIXELS - Pixel Operation for Bitmaps 32 | // FIXUP - Pixel Format Fixing Up Interface 33 | // 34 | //===================================================================== 35 | 36 | //--------------------------------------------------------------------- 37 | // Media Data Input/Output Interface 38 | //--------------------------------------------------------------------- 39 | int is_getc(IMDIO *stream) 40 | { 41 | int ch; 42 | if (stream->_ungetc >= 0) { 43 | ch = (int)stream->_ungetc; 44 | stream->_ungetc = -1; 45 | } else { 46 | ch = (stream->getc)(stream); 47 | if (ch >= 0) stream->_cnt++; 48 | } 49 | return ch; 50 | } 51 | 52 | int is_putc(IMDIO *stream, int c) 53 | { 54 | int ch; 55 | ch = (stream->putc)(stream, c); 56 | if (ch >= 0) stream->_cnt++; 57 | return ch; 58 | } 59 | 60 | int is_ungetc(IMDIO *stream, int c) 61 | { 62 | if (stream->_ungetc >= 0) return -1; 63 | stream->_ungetc = (long)c; 64 | return c; 65 | } 66 | 67 | long is_reader(IMDIO *stream, void *buffer, long size) 68 | { 69 | unsigned char *lptr = (unsigned char*)buffer; 70 | long total = 0; 71 | int ch; 72 | 73 | for (ch = 0; total < size; total++) { 74 | ch = is_getc(stream); 75 | if (ch < 0) break; 76 | *lptr++ = (unsigned char)ch; 77 | } 78 | if (total == 0) return -1; 79 | return total; 80 | } 81 | 82 | long is_writer(IMDIO *stream, const void *buffer, long size) 83 | { 84 | unsigned char *lptr = (unsigned char*)buffer; 85 | long total = 0; 86 | int ch; 87 | 88 | for (ch = 0; total < size; total++) { 89 | ch = *lptr++; 90 | ch = is_putc(stream, ch); 91 | if (ch < 0) break; 92 | } 93 | if (total == 0) return -1; 94 | return total; 95 | } 96 | 97 | int is_igetw(IMDIO *stream) 98 | { 99 | int c1, c2; 100 | if ((c1 = is_getc(stream)) < 0) return -1; 101 | if ((c2 = is_getc(stream)) < 0) return -1; 102 | return c1 | (c2 << 8); 103 | } 104 | 105 | int is_iputw(IMDIO *stream, int w) 106 | { 107 | int c1 = (w & 0xFF), c2 = ((w >> 8) & 0xFF); 108 | if (is_putc(stream, c1) < 0) return -1; 109 | if (is_putc(stream, c2) < 0) return -1; 110 | return w; 111 | } 112 | 113 | long is_igetl(IMDIO *stream) 114 | { 115 | long c1, c2, c3, c4; 116 | if ((c1 = (long)is_getc(stream)) < 0) return -1; 117 | if ((c2 = (long)is_getc(stream)) < 0) return -1; 118 | if ((c3 = (long)is_getc(stream)) < 0) return -1; 119 | if ((c4 = (long)is_getc(stream)) < 0) return -1; 120 | return (c1 | (c2 << 8) | (c3 << 16) | (c4 << 24)); 121 | } 122 | 123 | long is_iputl(IMDIO *stream, long l) 124 | { 125 | long c1, c2, c3, c4; 126 | c1 = (l & 0x000000FF) >> 0; 127 | c2 = (l & 0x0000FF00) >> 8; 128 | c3 = (l & 0x00FF0000) >> 16; 129 | c4 = (l & 0xFF000000) >> 24; 130 | if (is_putc(stream, c1) < 0) return -1; 131 | if (is_putc(stream, c2) < 0) return -1; 132 | if (is_putc(stream, c3) < 0) return -1; 133 | if (is_putc(stream, c4) < 0) return -1; 134 | return l; 135 | } 136 | 137 | int is_mgetw(IMDIO *stream) 138 | { 139 | int c1, c2; 140 | if ((c1 = is_getc(stream)) < 0) return -1; 141 | if ((c2 = is_getc(stream)) < 0) return -1; 142 | return (c1 << 8) | c2; 143 | } 144 | 145 | int is_mputw(IMDIO *stream, int w) 146 | { 147 | int c1 = (w >> 8) & 0xFF, c2 = (w & 0xFF); 148 | if (is_putc(stream, c1) < 0) return -1; 149 | if (is_putc(stream, c2) < 0) return -1; 150 | return w; 151 | } 152 | 153 | long is_mgetl(IMDIO *stream) 154 | { 155 | long c1, c2, c3, c4; 156 | if ((c1 = (long)is_getc(stream)) < 0) return -1; 157 | if ((c2 = (long)is_getc(stream)) < 0) return -1; 158 | if ((c3 = (long)is_getc(stream)) < 0) return -1; 159 | if ((c4 = (long)is_getc(stream)) < 0) return -1; 160 | return ((c1 << 24) | (c2 << 16) | (c3 << 8) | c4); 161 | } 162 | 163 | long is_mputl(IMDIO *stream, long l) 164 | { 165 | long c1, c2, c3, c4; 166 | c1 = (l & 0xFF000000) >> 24; 167 | c2 = (l & 0x00FF0000) >> 16; 168 | c3 = (l & 0x0000FF00) >> 8; 169 | c4 = (l & 0x000000FF); 170 | if (is_putc(stream, c1) < 0) return -1; 171 | if (is_putc(stream, c2) < 0) return -1; 172 | if (is_putc(stream, c3) < 0) return -1; 173 | if (is_putc(stream, c4) < 0) return -1; 174 | return l; 175 | } 176 | 177 | long is_getbits(IMDIO *stream, int count, int litend) 178 | { 179 | long data, bitc, bitd, mask, c, i; 180 | bitc = stream->_bitc; 181 | bitd = stream->_bitd; 182 | for (data = 0, i = 0; count > 0; ) { 183 | if (bitc == 0) { 184 | bitd = is_getc(stream); 185 | bitc = 8; 186 | if (bitd < 0) { 187 | bitd = 0; 188 | bitc = 0; 189 | data = -1; 190 | break; 191 | } 192 | } 193 | c = (count >= bitc) ? bitc : count; 194 | if (litend == 0) { 195 | data <<= c; 196 | data |= (bitd >> (8 - c)) & 0xff; 197 | bitd = (bitd << c) & 0xff; 198 | } else { 199 | mask = (1L << c) - 1; 200 | data |= (bitd & mask) << i; 201 | bitd >>= c; 202 | i += c; 203 | } 204 | count -= c; 205 | bitc -= c; 206 | } 207 | stream->_bitc = bitc; 208 | stream->_bitd = bitd; 209 | return data; 210 | } 211 | 212 | long is_putbits(IMDIO *stream, long data, int count, int litend) 213 | { 214 | long bitc, bitd, mask, c; 215 | bitc = stream->_bitc; 216 | bitd = stream->_bitd; 217 | for (; count > 0; ) { 218 | c = 8 - bitc; 219 | if (count < c) c = count; 220 | if (litend == 0) { 221 | mask = (data >> (count - c)) & 0xff; 222 | bitd |= (mask << (8 - c)) >> bitc; 223 | } else { 224 | mask = ((1L << c) - 1) & data; 225 | data >>= c; 226 | bitd |= mask << bitc; 227 | } 228 | bitc += c; 229 | count -= c; 230 | if (bitc >= 8) { 231 | if (is_putc(stream, bitd & 0xff) < 0) { 232 | return -1; 233 | } 234 | bitc = 0; 235 | bitd = 0; 236 | } 237 | } 238 | stream->_bitc = bitc; 239 | stream->_bitd = bitd; 240 | return 0; 241 | } 242 | 243 | void is_flushbits(IMDIO *stream, int isflushwrite, int litendian) 244 | { 245 | if (isflushwrite) { 246 | if (stream->_bitc != 0) { 247 | is_putbits(stream, 0, 8 - stream->_bitc, litendian); 248 | } 249 | } 250 | stream->_bitc = 0; 251 | stream->_bitd = 0; 252 | } 253 | 254 | long is_igetbits(IMDIO *stream, int count) 255 | { 256 | return is_getbits(stream, count, 1); 257 | } 258 | 259 | long is_mgetbits(IMDIO *stream, int count) 260 | { 261 | return is_getbits(stream, count, 0); 262 | } 263 | 264 | long is_iputbits(IMDIO *stream, long data, int count) 265 | { 266 | return is_putbits(stream, data, count, 1); 267 | } 268 | 269 | long is_mputbits(IMDIO *stream, long data, int count) 270 | { 271 | return is_putbits(stream, data, count, 0); 272 | } 273 | 274 | void is_iflushbits(IMDIO *stream, int isflushwrite) 275 | { 276 | is_flushbits(stream, isflushwrite, 1); 277 | } 278 | 279 | void is_mflushbits(IMDIO *stream, int isflushwrite) 280 | { 281 | is_flushbits(stream, isflushwrite, 0); 282 | } 283 | 284 | void is_seekcur(IMDIO *stream, long skip) 285 | { 286 | for (; skip > 0; skip--) is_getc(stream); 287 | } 288 | 289 | 290 | //--------------------------------------------------------------------- 291 | // IBITMAP PIXEL OPERATION 292 | //--------------------------------------------------------------------- 293 | #define _is_bmline(bmp, y) ((unsigned char*)((bmp)->line[y])) 294 | 295 | static inline IUINT32 _is_get3b(const void *p) 296 | { 297 | return _ipixel_fetch_24(p, 0); 298 | } 299 | 300 | static inline IUINT32 _is_put3b(void *p, IUINT32 c) 301 | { 302 | _ipixel_store_24(p, 0, c); 303 | return c; 304 | } 305 | 306 | #define _IS_HEADER1() do { \ 307 | if (bmp == NULL) return 0; \ 308 | if (x<0 || y<0 || x>=(int)bmp->w || y>=(int)bmp->h) \ 309 | return 0; \ 310 | } while (0) 311 | 312 | static inline IUINT32 _is_get8(const struct IBITMAP *bmp, int x, int y) 313 | { 314 | _IS_HEADER1(); 315 | return _is_bmline(bmp, y)[x]; 316 | } 317 | 318 | static inline IUINT32 _is_get15(const struct IBITMAP *bmp, int x, int y) 319 | { 320 | _IS_HEADER1(); 321 | return ((IUINT16*)_is_bmline(bmp, y))[x]; 322 | } 323 | 324 | static inline IUINT32 _is_get16(const struct IBITMAP *bmp, int x, int y) 325 | { 326 | _IS_HEADER1(); 327 | return ((IUINT16*)_is_bmline(bmp, y))[x]; 328 | } 329 | 330 | static inline IUINT32 _is_get24(const struct IBITMAP *bmp, int x, int y) 331 | { 332 | _IS_HEADER1(); 333 | return _is_get3b(_is_bmline(bmp, y) + (x) * 3); 334 | } 335 | 336 | static inline IUINT32 _is_get32(const struct IBITMAP *bmp, int x, int y) 337 | { 338 | _IS_HEADER1(); 339 | return ((IUINT32*)_is_bmline(bmp, y))[x]; 340 | } 341 | 342 | static inline IUINT32 _is_put8(struct IBITMAP *bmp, int x, int y, IUINT32 c) 343 | { 344 | _IS_HEADER1(); 345 | _is_bmline(bmp, y)[x] = (unsigned char)(c & 0xFF); 346 | return c; 347 | } 348 | 349 | static inline IUINT32 _is_put15(struct IBITMAP *bmp, int x, int y, IUINT32 c) 350 | { 351 | _IS_HEADER1(); 352 | ((IUINT16*)_is_bmline(bmp, y))[x] = (IUINT16)(c & 0xFFFF); 353 | return c; 354 | } 355 | 356 | static inline IUINT32 _is_put16(struct IBITMAP *bmp, int x, int y, IUINT32 c) 357 | { 358 | _IS_HEADER1(); 359 | ((IUINT16*)_is_bmline(bmp, y))[x] = (IUINT16)(c & 0xFFFF); 360 | return c; 361 | } 362 | 363 | static inline IUINT32 _is_put24(struct IBITMAP *bmp, int x, int y, IUINT32 c) 364 | { 365 | _IS_HEADER1(); 366 | _is_put3b(_is_bmline(bmp, y) + (x) * 3, c); 367 | return c; 368 | } 369 | 370 | static inline IUINT32 _is_put32(struct IBITMAP *bmp, int x, int y, IUINT32 c) 371 | { 372 | _IS_HEADER1(); 373 | ((IUINT32*)_is_bmline(bmp, y))[x] = c; 374 | return c; 375 | } 376 | 377 | static inline IUINT32 _is_getpx(const struct IBITMAP *bmp, int x, int y) 378 | { 379 | _IS_HEADER1(); 380 | if (bmp->bpp == 8) return _is_get8(bmp, x, y); 381 | else if (bmp->bpp == 15) return _is_get15(bmp, x, y); 382 | else if (bmp->bpp == 16) return _is_get16(bmp, x, y); 383 | else if (bmp->bpp == 24) return _is_get24(bmp, x, y); 384 | else if (bmp->bpp == 32) return _is_get32(bmp, x, y); 385 | return 0; 386 | } 387 | 388 | static inline IUINT32 _is_putpx(struct IBITMAP *bmp, int x, int y, IUINT32 c) 389 | { 390 | _IS_HEADER1(); 391 | if (bmp->bpp == 8) return _is_put8(bmp, x, y, c); 392 | else if (bmp->bpp == 15) return _is_put15(bmp, x, y, c); 393 | else if (bmp->bpp == 16) return _is_put16(bmp, x, y, c); 394 | else if (bmp->bpp == 24) return _is_put24(bmp, x, y, c); 395 | else if (bmp->bpp == 32) return _is_put32(bmp, x, y, c); 396 | return 0; 397 | } 398 | 399 | int _ibitmap_guess_pixfmt(const IBITMAP *bmp) 400 | { 401 | int fmt; 402 | fmt = ibitmap_pixfmt_get(bmp); 403 | if (fmt < 0) { 404 | if (bmp->bpp == 8) return IPIX_FMT_C8; 405 | if (bmp->bpp == 15) return IPIX_FMT_X1R5G5B5; 406 | if (bmp->bpp == 16) return IPIX_FMT_R5G6B5; 407 | if (bmp->bpp == 24) return IPIX_FMT_R8G8B8; 408 | if (bmp->bpp == 32) return IPIX_FMT_A8R8G8B8; 409 | } 410 | return fmt; 411 | } 412 | 413 | IUINT32 _im_color_get(int fmt, IUINT32 c, const IRGB *pal) 414 | { 415 | IINT32 r, g, b, a; 416 | if (ipixelfmt[fmt].type == IPIX_FMT_TYPE_INDEX) { 417 | return IRGBA_TO_A8R8G8B8(pal[c].r, pal[c].g, pal[c].b, 255); 418 | } 419 | IRGBA_DISEMBLE(fmt, c, r, g, b, a); 420 | return IRGBA_TO_A8R8G8B8(r, g, b, a); 421 | } 422 | 423 | 424 | #undef _IS_HEADER1 425 | 426 | //--------------------------------------------------------------------- 427 | // local definition 428 | //--------------------------------------------------------------------- 429 | typedef struct IBITMAP ibitmap_t; 430 | long _is_perrno = 0; 431 | 432 | void _is_perrno_set(long v) { _is_perrno = v; } 433 | long _is_perrno_get(void) { return _is_perrno; } 434 | 435 | //--------------------------------------------------------------------- 436 | // stream operation interface 437 | //--------------------------------------------------------------------- 438 | #define IRWCHECK(s, v) do { if ((s)->_code != (v)) return -1; } while(0) 439 | static int iproc_getc_mem(struct IMDIO *stream) 440 | { 441 | IRWCHECK(stream, 0); 442 | if (stream->_pos < stream->_len) 443 | return ((unsigned char*)(stream->data))[stream->_pos++]; 444 | return -1; 445 | } 446 | 447 | static int iproc_putc_mem(struct IMDIO *stream, int c) 448 | { 449 | unsigned char ch = (unsigned char)c; 450 | IRWCHECK(stream, 0); 451 | if (stream->_pos == stream->_len) return -1; 452 | else if (stream->_pos < stream->_len) { 453 | ((unsigned char*)(stream->data))[stream->_pos++] = ch; 454 | } 455 | if (stream->_pos > stream->_len) stream->_len = stream->_pos; 456 | return c; 457 | } 458 | 459 | static int iproc_getc_file(struct IMDIO *stream) 460 | { 461 | IRWCHECK(stream, 1); 462 | return fgetc((FILE*)(stream->data)); 463 | } 464 | 465 | static int iproc_putc_file(struct IMDIO *stream, int c) 466 | { 467 | IRWCHECK(stream, 1); 468 | return fputc(c, (FILE*)(stream->data)); 469 | } 470 | 471 | int is_init_mem(IMDIO *stream, const void *lptr, long size) 472 | { 473 | stream->_code = 0; 474 | stream->_pos = 0; 475 | stream->_len = size; 476 | stream->_bitc = 0; 477 | stream->_bitd = 0; 478 | stream->_ungetc = -1; 479 | stream->data = (void*)lptr; 480 | stream->getc = iproc_getc_mem; 481 | stream->putc = iproc_putc_mem; 482 | return 0; 483 | } 484 | 485 | #ifdef _MSC_VER 486 | #pragma warning(disable:4996) 487 | #endif 488 | 489 | int is_open_file(IMDIO *stream, const char *filename, const char *rw) 490 | { 491 | stream->_code = -1; 492 | stream->data = fopen(filename, rw); 493 | if (stream->data == NULL) return -1; 494 | stream->_code = 1; 495 | stream->_bitc = 0; 496 | stream->_bitd = 0; 497 | stream->_ungetc = -1; 498 | stream->getc = iproc_getc_file; 499 | stream->putc = iproc_putc_file; 500 | return 0; 501 | } 502 | 503 | int is_close_file(IMDIO *stream) 504 | { 505 | IRWCHECK(stream, 1); 506 | fclose((FILE*)(stream->data)); 507 | return 0; 508 | } 509 | 510 | 511 | void *is_read_marked_block(IMDIO *stream, const unsigned char *mark, 512 | int marksize, size_t *nbytes_readed) 513 | { 514 | static const unsigned char dmark[2] = { 0, 0 }; 515 | unsigned char *data; 516 | unsigned char *buffer; 517 | size_t block = 0; 518 | size_t nsize = 0; 519 | int nbuffered = 0; 520 | int index = 0; 521 | 522 | if (stream == NULL) 523 | return NULL; 524 | 525 | buffer = (unsigned char*)malloc(marksize + 10); 526 | 527 | if (buffer == NULL) 528 | return NULL; 529 | 530 | data = (unsigned char*)malloc(256); 531 | block = 256; 532 | 533 | if (data == NULL) { 534 | free(buffer); 535 | return NULL; 536 | } 537 | 538 | if (mark == NULL) mark = dmark; 539 | 540 | while (1) { 541 | int ch; 542 | ch = is_getc(stream); 543 | if (ch < 0) break; 544 | buffer[index] = (unsigned char)ch; 545 | data[nsize++] = (unsigned char)ch; 546 | 547 | if (nsize >= block) { 548 | unsigned char *tmp = (unsigned char*)malloc(block * 2); 549 | if (tmp != NULL) { 550 | memcpy(tmp, data, nsize); 551 | free(data); 552 | data = tmp; 553 | block = block * 2; 554 | } else { 555 | nsize = 0; 556 | } 557 | } 558 | 559 | if (++nbuffered >= marksize && mark && marksize > 0) { 560 | int i, j, k; 561 | for (i = index, j = marksize - 1, k = 0; j >= 0; j--, k++) { 562 | if (buffer[i] != mark[j]) break; 563 | if (--i < 0) i = marksize - 1; 564 | } 565 | if (k == marksize) break; 566 | } 567 | if (++index >= marksize) index = 0; 568 | } 569 | 570 | free(buffer); 571 | 572 | buffer = NULL; 573 | if (nsize > 0) { 574 | buffer = (unsigned char*)malloc(nsize); 575 | } 576 | 577 | if (buffer == NULL || nsize == 0) { 578 | free(data); 579 | if (nbytes_readed) *nbytes_readed = 0; 580 | return NULL; 581 | } 582 | 583 | memcpy(buffer, data, nsize); 584 | if (nbytes_readed) *nbytes_readed = nsize; 585 | free(data); 586 | 587 | return buffer; 588 | } 589 | 590 | 591 | 592 | //===================================================================== 593 | // 594 | // bmp - Windows/OS2 IBITMAP Format 595 | // 596 | // decoding program - idcolor.h 597 | // 598 | //===================================================================== 599 | #define IBI_RGB 0 600 | #define IBI_RLE8 1 601 | #define IBI_RLE4 2 602 | #define IBI_BITFIELDS 3 603 | 604 | #define IOS2INFOHEADERSIZE 12 605 | #define IWININFOHEADERSIZE 40 606 | 607 | 608 | typedef struct _IBITMAPFILEHEADER 609 | { 610 | IUINT32 bfType; 611 | IUINT32 bfSize; 612 | IUINT16 bfReserved1; 613 | IUINT16 bfReserved2; 614 | IUINT32 bfOffBits; 615 | } IBITMAPFILEHEADER; 616 | 617 | 618 | typedef struct _IBITMAPINFOHEADER 619 | { 620 | IUINT32 biWidth; 621 | IUINT32 biHeight; 622 | IUINT16 biBitCount; 623 | IUINT32 biCompression; 624 | } IBITMAPINFOHEADER; 625 | 626 | 627 | //--------------------------------------------------------------------- 628 | // bmp - read_bmfileheader 629 | //--------------------------------------------------------------------- 630 | static int iread_bmfileheader(IMDIO *stream, IBITMAPFILEHEADER *fileheader) 631 | { 632 | fileheader->bfType = is_igetw(stream); 633 | fileheader->bfSize= is_igetl(stream); 634 | fileheader->bfReserved1= is_igetw(stream); 635 | fileheader->bfReserved2= is_igetw(stream); 636 | fileheader->bfOffBits= is_igetl(stream); 637 | 638 | if (fileheader->bfType != 0x4D42) return -1; 639 | 640 | return 0; 641 | } 642 | 643 | //--------------------------------------------------------------------- 644 | // bmp - read_bminfoheader 645 | //--------------------------------------------------------------------- 646 | static int iread_bminfoheader(IMDIO *stream, IBITMAPINFOHEADER *infoheader, 647 | int ihsize) 648 | { 649 | long data[20]; 650 | 651 | if (ihsize == IWININFOHEADERSIZE) { 652 | data[0] = is_igetl(stream); /* IUINT32 biWidth......... */ 653 | data[1] = is_igetl(stream); /* IUINT32 biHeight........ */ 654 | data[2] = is_igetw(stream); /* IUINT16 biPlanes........ */ 655 | data[3] = is_igetw(stream); /* IUINT16 biBitCount...... */ 656 | data[4] = is_igetl(stream); /* IUINT32 biCompression... */ 657 | data[5] = is_igetl(stream); /* IUINT32 biSizeImage..... */ 658 | data[6] = is_igetl(stream); /* IUINT32 biXPelsPerMeters */ 659 | data[7] = is_igetl(stream); /* IUINT32 biYPelsPerMeters */ 660 | data[8] = is_igetl(stream); /* IUINT32 biClrUsed....... */ 661 | data[9] = is_igetl(stream); /* IUINT32 biClrImportant.. */ 662 | 663 | infoheader->biWidth = data[0]; 664 | infoheader->biHeight = data[1]; 665 | infoheader->biBitCount = (IUINT16)data[3]; 666 | infoheader->biCompression = data[4]; 667 | } 668 | else 669 | if (ihsize == IOS2INFOHEADERSIZE) { 670 | data[0] = is_igetw(stream); /* IUINT16 biWidth......... */ 671 | data[1] = is_igetw(stream); /* IUINT16 biHeight........ */ 672 | data[2] = is_igetw(stream); /* IUINT16 biPlanes........ */ 673 | data[3] = is_igetw(stream); /* IUINT16 biBitCount...... */ 674 | 675 | infoheader->biWidth = data[0]; 676 | infoheader->biHeight= data[1]; 677 | infoheader->biBitCount = (IUINT16)data[3]; 678 | infoheader->biCompression = 0; 679 | } 680 | else { 681 | return -1; 682 | } 683 | 684 | return 0; 685 | } 686 | 687 | //--------------------------------------------------------------------- 688 | // bmp - read_bmicolors 689 | //--------------------------------------------------------------------- 690 | static void ibmp_read_bmicolors(int ncols, IRGB *pal, IMDIO *stream, 691 | int win_flag) 692 | { 693 | int i; 694 | for (i = 0; i < ncols; i++) { 695 | pal[i].b = is_getc(stream); 696 | pal[i].g = is_getc(stream); 697 | pal[i].r = is_getc(stream); 698 | if (win_flag) is_getc(stream); 699 | } 700 | } 701 | 702 | //--------------------------------------------------------------------- 703 | // bmp - read_image 704 | //--------------------------------------------------------------------- 705 | static void ibmp_read_image(IMDIO *stream, ibitmap_t *bmp, const 706 | IBITMAPINFOHEADER *infoheader) 707 | { 708 | long line, start, length; 709 | long i, j, k, a, nbytes; 710 | IUINT32 n; 711 | unsigned char b[32]; 712 | IRGB c; 713 | 714 | for (start = 0; start < (long)infoheader->biHeight; start++) { 715 | line = infoheader->biHeight - start - 1; 716 | length = (long)infoheader->biWidth; 717 | 718 | switch (infoheader->biBitCount) { 719 | 720 | case 1: 721 | for (i = 0; i < length; i++) { 722 | j = i % 32; 723 | if (j == 0) { 724 | n = is_mgetl(stream); 725 | for (k = 0; k < 32; k++) { 726 | b[31 - k] = (char)(n & 1); 727 | n = n >> 1; 728 | } 729 | } 730 | _is_put8(bmp, i, line, b[j]); 731 | } 732 | break; 733 | 734 | case 4: 735 | for (i = 0; i < length; i++) { 736 | j = i % 8; 737 | if (j == 0) { 738 | n = is_igetl(stream); 739 | for (k = 0; k < 4; k++) { 740 | b[k * 2 + 1] = (IUINT8)(((n & 0xFF) >> 0) & 0x0F); 741 | b[k * 2 + 0] = (IUINT8)(((n & 0xFF) >> 4) & 0x0F); 742 | n = n >> 8; 743 | } 744 | } 745 | _is_put8(bmp, i, line, b[j]); 746 | } 747 | break; 748 | 749 | case 8: 750 | for (i = 0; i < length; i++) { 751 | _is_put8(bmp, i, line, is_getc(stream)); 752 | } 753 | break; 754 | 755 | case 24: 756 | for (nbytes = 0, i = 0; i < length; i++, nbytes += 3) { 757 | IUINT32 cc; 758 | c.b = is_getc(stream); 759 | c.g = is_getc(stream); 760 | c.r = is_getc(stream); 761 | cc = IRGBA_TO_R8G8B8(c.r, c.g, c.b, 255); 762 | _is_put24(bmp, i, line, cc); 763 | } 764 | nbytes = nbytes % 4; 765 | for (i = nbytes; nbytes != 0 && i < 4; i++) is_getc(stream); 766 | break; 767 | 768 | case 32: 769 | for (i = 0; i < length; i++) { 770 | c.b = is_getc(stream); 771 | c.g = is_getc(stream); 772 | c.r = is_getc(stream); 773 | a = is_getc(stream); 774 | if (bmp->bpp == 32) { 775 | IUINT32 cc = IRGBA_TO_A8R8G8B8(c.r, c.g, c.b, a); 776 | _is_put32(bmp, i, line, cc); 777 | } else { 778 | IUINT32 cc = IRGBA_TO_A8R8G8B8(c.r, c.g, c.b, a); 779 | _is_put24(bmp, i, line, cc); 780 | } 781 | } 782 | break; 783 | } 784 | } 785 | } 786 | 787 | //--------------------------------------------------------------------- 788 | // bmp - read_bitfields_image 789 | //--------------------------------------------------------------------- 790 | static void ibmp_read_bitfields_image(IMDIO *stream, ibitmap_t *bmp, 791 | IBITMAPINFOHEADER *infoheader) 792 | { 793 | long i, j; 794 | long bpp; 795 | int bytes_per_pixel; 796 | int red, grn, blu; 797 | IUINT32 buffer; 798 | 799 | bpp = bmp->bpp; 800 | bytes_per_pixel = (bpp + 7) / 8; 801 | 802 | for (j = (long)infoheader->biHeight - 1; j >= 0; j--) { 803 | for (i = 0; i < (long)infoheader->biWidth; i++) { 804 | 805 | buffer = 0; 806 | if (bytes_per_pixel == 1) buffer = is_getc(stream); 807 | else if (bytes_per_pixel == 2) buffer = is_igetw(stream); 808 | else if (bytes_per_pixel == 3) { 809 | buffer = is_getc(stream); 810 | buffer |= is_getc(stream) << 8; 811 | buffer |= is_getc(stream) << 16; 812 | } 813 | else if (bytes_per_pixel == 4) { 814 | buffer = (IUINT32)is_igetl(stream); 815 | } 816 | 817 | if (bpp == 15) { 818 | red = (buffer >> 10) & 0x1f; 819 | grn = (buffer >> 5) & 0x1f; 820 | blu = (buffer) & 0x1f; 821 | buffer = (red << 10) | 822 | (grn << 5) | 823 | (blu << 0); 824 | } 825 | else if (bpp == 16) { 826 | red = (buffer >> 11) & 0x1f; 827 | grn = (buffer >> 5) & 0x3f; 828 | blu = (buffer) & 0x1f; 829 | buffer = (red << 11) | 830 | (grn << 5) | 831 | (blu << 0); 832 | } 833 | else { 834 | red = (buffer >> 16) & 0xff; 835 | grn = (buffer >> 8) & 0xff; 836 | blu = (buffer) & 0xff; 837 | buffer = (red << 24) | 838 | (grn << 16) | 839 | (blu << 0); 840 | } 841 | 842 | if (bytes_per_pixel == 1) _is_put8(bmp, i, j, buffer); 843 | else if (bytes_per_pixel == 2) _is_put16(bmp, i, j, buffer); 844 | else if (bytes_per_pixel == 3) _is_put24(bmp, i, j, buffer); 845 | else _is_put32(bmp, i, j, buffer); 846 | } 847 | } 848 | } 849 | 850 | //--------------------------------------------------------------------- 851 | // bmp - read_rle_image 852 | //--------------------------------------------------------------------- 853 | static void ibmp_read_rle_image(IMDIO *stream, ibitmap_t *bmp, 854 | IBITMAPINFOHEADER *infoheader) 855 | { 856 | unsigned char count, val, val0; 857 | unsigned char b[8]; 858 | long line, j, k, pos, bpp; 859 | long eolflag, eopicflag; 860 | 861 | line = infoheader->biHeight - 1; 862 | bpp = (infoheader->biCompression == IBI_RLE8)? 8 : 4; 863 | val = 0; 864 | 865 | for (eopicflag = 0; eopicflag == 0; ) { 866 | for (eolflag = 0, pos = 0; eolflag == 0 && eopicflag == 0; ) { 867 | count = is_getc(stream); 868 | val0 = is_getc(stream); 869 | if (count > 0) { 870 | b[1] = val0 & 15; 871 | b[0] = (val0 >> 4) & 15; 872 | for (j = 0; j < count; j++, pos++) { 873 | val = (bpp == 8)? val0 : b[j % 2]; 874 | _is_put8(bmp, pos, line, val); 875 | } 876 | } 877 | else { 878 | if (val == 0) eolflag = 1; 879 | else if (val == 1) eopicflag = 1; 880 | else if (val == 2) { 881 | pos += is_getc(stream); 882 | line -= is_getc(stream); 883 | } else { 884 | for (j = 0; j < val; j++, pos++) { 885 | if (bpp == 8) val = is_getc(stream); 886 | else { 887 | if ((j % 4) == 0) { 888 | val0 = is_igetw(stream); 889 | for (k = 0; k < 2; k++) { 890 | b[2 * k + 1] = val0 & 15; 891 | val0 = val0 >> 4; 892 | b[2 * k] = val0 & 15; 893 | val0 = val0 >> 4; 894 | } 895 | } 896 | val = b[j % 4]; 897 | } 898 | _is_put8(bmp, pos, line, val); 899 | } 900 | if (j % 2 == 1 && bpp == 8) val0 = is_getc(stream); 901 | } 902 | } 903 | if (pos >= (long)infoheader->biWidth) eolflag = 1; 904 | } 905 | if (--line < 0) eopicflag = 1; 906 | } 907 | } 908 | 909 | //--------------------------------------------------------------------- 910 | // bmp - iload_bmp_stream 911 | //--------------------------------------------------------------------- 912 | struct IBITMAP *iload_bmp_stream(IMDIO *stream, IRGB *pal) 913 | { 914 | IBITMAPFILEHEADER fileheader; 915 | IBITMAPINFOHEADER infoheader; 916 | struct IBITMAP *bmp; 917 | long want_palette = 1; 918 | long ncol; 919 | IUINT32 biSize; 920 | int bpp, dest_depth; 921 | IRGB tmppal[256]; 922 | 923 | assert(stream); 924 | 925 | _is_perrno_set(0); 926 | 927 | if (!pal) { 928 | want_palette = 0; 929 | pal = tmppal; 930 | } 931 | 932 | if (iread_bmfileheader(stream, &fileheader) != 0) { 933 | _is_perrno_set(1); 934 | return NULL; 935 | } 936 | 937 | biSize = is_igetl(stream); 938 | 939 | if (iread_bminfoheader(stream, &infoheader, biSize) != 0) { 940 | _is_perrno_set(2); 941 | return NULL; 942 | } 943 | 944 | if (biSize == IWININFOHEADERSIZE) { 945 | ncol = (fileheader.bfOffBits - 54) / 4; 946 | if (infoheader.biCompression != IBI_BITFIELDS) 947 | ibmp_read_bmicolors(ncol, pal, stream, 1); 948 | } 949 | else if (biSize == IOS2INFOHEADERSIZE) { 950 | ncol = (fileheader.bfOffBits - 26) / 3; 951 | if (infoheader.biCompression != IBI_BITFIELDS) 952 | ibmp_read_bmicolors(ncol, pal, stream, 0); 953 | } else { 954 | _is_perrno_set(3); 955 | return NULL; 956 | } 957 | 958 | if (infoheader.biBitCount == 24) bpp = 24; 959 | else if (infoheader.biBitCount == 16) bpp = 16; 960 | else if (infoheader.biBitCount == 32) bpp = 32; 961 | else bpp = 8; 962 | 963 | if (infoheader.biCompression == IBI_BITFIELDS) { 964 | IUINT32 redMask = is_igetl(stream); 965 | IUINT32 grnMask = is_igetl(stream); 966 | IUINT32 bluMask = is_igetl(stream); 967 | (void)grnMask; 968 | if ((bluMask == 0x001f) && (redMask == 0x7C00)) bpp = 15; 969 | else if ((bluMask == 0x001f) && (redMask == 0xF800)) bpp = 16; 970 | else if ((bluMask == 0x0000FF) && (redMask == 0xFF0000)) bpp = 32; 971 | else { 972 | _is_perrno_set(4); 973 | return NULL; 974 | } 975 | } 976 | 977 | bmp = ibitmap_create(infoheader.biWidth, infoheader.biHeight, bpp); 978 | dest_depth = bpp; 979 | 980 | if (!bmp) { 981 | _is_perrno_set(5); 982 | return NULL; 983 | } 984 | 985 | switch (infoheader.biCompression) 986 | { 987 | case IBI_RGB: 988 | ibmp_read_image(stream, bmp, &infoheader); 989 | break; 990 | case IBI_RLE8: 991 | case IBI_RLE4: 992 | ibmp_read_rle_image(stream, bmp, &infoheader); 993 | break; 994 | case IBI_BITFIELDS: 995 | ibmp_read_bitfields_image(stream, bmp, &infoheader); 996 | break; 997 | default: 998 | ibitmap_release(bmp); 999 | bmp = NULL; 1000 | _is_perrno_set(6); 1001 | break; 1002 | } 1003 | 1004 | if (dest_depth != bpp) { 1005 | if ((bpp != 8) && (!want_palette)) pal = NULL; 1006 | } 1007 | 1008 | ibitmap_pixfmt_set(bmp, ibitmap_pixfmt_guess(bmp)); 1009 | 1010 | /* construct a fake palette if 8-bit mode is not involved */ 1011 | if ((bpp != 8) && (dest_depth != 8) && want_palette) { 1012 | //_igenerate_332_palette(pal); 1013 | } 1014 | 1015 | return bmp; 1016 | } 1017 | 1018 | //--------------------------------------------------------------------- 1019 | // bmp - isave_bmp_stream 1020 | //--------------------------------------------------------------------- 1021 | int isave_bmp_stream(IMDIO *stream, struct IBITMAP *bmp, const IRGB *pal) 1022 | { 1023 | IUINT32 c, p; 1024 | long i, j; 1025 | IRGB tmppal[256]; 1026 | int bfSize; 1027 | int biSizeImage; 1028 | int depth; 1029 | int bpp; 1030 | int filler; 1031 | int fmt; 1032 | 1033 | assert(bmp); 1034 | assert(stream); 1035 | 1036 | depth = bmp->bpp; 1037 | bpp = (depth == 8) ? 8 : 24; 1038 | filler = 3 - ((bmp->w * (bpp / 8) - 1) & 3); 1039 | 1040 | if (!pal) { 1041 | memcpy(tmppal, _ipaletted, 256 * sizeof(IRGB)); 1042 | pal = tmppal; 1043 | } 1044 | 1045 | if (bpp == 8) { 1046 | biSizeImage = (bmp->w + filler) * bmp->h; 1047 | bfSize = (54 + 256 * 4 + biSizeImage); 1048 | } else { 1049 | biSizeImage = (bmp->w * 3 + filler) * bmp->h; 1050 | bfSize = 54 + biSizeImage; 1051 | } 1052 | 1053 | _is_perrno_set(0); 1054 | 1055 | /* file_header */ 1056 | is_iputw(stream, 0x4D42); /* bfType ("BM") */ 1057 | is_iputl(stream, bfSize); /* bfSize */ 1058 | is_iputw(stream, 0); /* bfReserved1 */ 1059 | is_iputw(stream, 0); /* bfReserved2 */ 1060 | 1061 | if (bpp == 8) is_iputl(stream, 54 + 256 * 4); 1062 | else is_iputl(stream, 54); 1063 | 1064 | /* info_header */ 1065 | is_iputl(stream, 40); /* biSize */ 1066 | is_iputl(stream, (long)bmp->w); /* biWidth */ 1067 | is_iputl(stream, (long)bmp->h); /* biHeight */ 1068 | is_iputw(stream, 1); /* biPlanes */ 1069 | is_iputw(stream, bpp); /* biBitCount */ 1070 | is_iputl(stream, 0); /* biCompression */ 1071 | is_iputl(stream, biSizeImage); /* biSizeImage */ 1072 | is_iputl(stream, 0xB12); /* (0xB12 = 72 dpi) */ 1073 | is_iputl(stream, 0xB12); /* biYPelsPerMeter */ 1074 | 1075 | if (bpp == 8) { 1076 | is_iputl(stream, 256); /* biClrUsed */ 1077 | is_iputl(stream, 256); /* biClrImportant */ 1078 | for (i = 0; i < 256; i++) { 1079 | is_putc(stream, pal[i].b); 1080 | is_putc(stream, pal[i].g); 1081 | is_putc(stream, pal[i].r); 1082 | is_putc(stream, 0); 1083 | } 1084 | } else { 1085 | is_iputl(stream, 0); /* biClrUsed */ 1086 | is_iputl(stream, 0); /* biClrImportant */ 1087 | } 1088 | 1089 | fmt = _ibitmap_guess_pixfmt(bmp); 1090 | 1091 | /* image data */ 1092 | for (j = (long)bmp->h - 1; j >= 0; j--) { 1093 | for (i = 0; i < (long)bmp->w; i++) { 1094 | c = _is_getpx(bmp, i, j); 1095 | p = _im_color_get(fmt, c, pal); 1096 | if (bpp == 8) { 1097 | is_putc(stream, (long)c); 1098 | } else { 1099 | is_putc(stream, (int)((p >> 0) & 0xFF)); 1100 | is_putc(stream, (int)((p >> 8) & 0xFF)); 1101 | is_putc(stream, (int)((p >> 16) & 0xFF)); 1102 | } 1103 | } 1104 | for (i = 0; i < (long)filler; i++) is_putc(stream, 0); 1105 | } 1106 | 1107 | return 0; 1108 | } 1109 | 1110 | //--------------------------------------------------------------------- 1111 | // bmp - isave_bmp_file 1112 | //--------------------------------------------------------------------- 1113 | int isave_bmp_file(const char *file, struct IBITMAP *bmp, const IRGB *pal) 1114 | { 1115 | IMDIO stream; 1116 | int retval; 1117 | 1118 | if (is_open_file(&stream, file, "wb")) return -1; 1119 | retval = isave_bmp_stream(&stream, bmp, pal); 1120 | is_close_file(&stream); 1121 | 1122 | return retval; 1123 | } 1124 | 1125 | 1126 | //===================================================================== 1127 | // 1128 | // tga - Tagged Graphics (Truevision Inc.) Format 1129 | // 1130 | // decoding program - idcolor.h 1131 | // 1132 | //===================================================================== 1133 | 1134 | 1135 | //--------------------------------------------------------------------- 1136 | // tga - single_tga_readn 1137 | //--------------------------------------------------------------------- 1138 | static IUINT32 single_tga_readn(IMDIO *stream, int bpp) 1139 | { 1140 | IUINT32 r, g, b, a, c; 1141 | 1142 | if (bpp == 8) return is_getc(stream); 1143 | if (bpp == 15) { 1144 | c = is_igetw(stream); 1145 | r = _ipixel_scale_5[(c >> 10) & 0x1F]; 1146 | g = _ipixel_scale_5[(c >> 5) & 0x1F]; 1147 | b = _ipixel_scale_5[(c >> 0) & 0x1F]; 1148 | return IRGBA_TO_X1R5G5B5(r, g, b, 255); 1149 | } 1150 | if (bpp == 16) { 1151 | c = is_igetw(stream); 1152 | r = _ipixel_scale_5[(c >> 11) & 0x1F]; 1153 | g = _ipixel_scale_6[(c >> 5) & 0x3F]; 1154 | b = _ipixel_scale_5[(c >> 0) & 0x1F]; 1155 | return IRGBA_TO_R5G6B5(r, g, b, 255); 1156 | } 1157 | if (bpp != 24 && bpp != 32) { 1158 | return 0xffffffff; 1159 | } 1160 | 1161 | b = is_getc(stream); 1162 | g = is_getc(stream); 1163 | r = is_getc(stream); 1164 | a = (bpp == 32)? is_getc(stream) : 0; 1165 | c = IRGBA_TO_A8R8G8B8(r, g, b, a); 1166 | if (bpp == 24) c &= 0xffffff; 1167 | 1168 | return c; 1169 | } 1170 | 1171 | //--------------------------------------------------------------------- 1172 | // tga - raw_tga_readn 1173 | //--------------------------------------------------------------------- 1174 | static void *raw_tga_readn(void *b, int w, int bpp, IMDIO *stream) 1175 | { 1176 | unsigned char *lptr = (unsigned char*)b; 1177 | IUINT32 c, n; 1178 | 1179 | n = (bpp + 7) >> 3; 1180 | for (; w > 0; w--, lptr += n) { 1181 | c = single_tga_readn(stream, bpp); 1182 | if (n == 1) _ipixel_store_8(lptr, 0, c); 1183 | else if (n == 2) _ipixel_store_16(lptr, 0, c); 1184 | else if (n == 3) _ipixel_store_24(lptr, 0, c); 1185 | else if (n == 4) _ipixel_store_32(lptr, 0, c); 1186 | } 1187 | 1188 | return (void*)lptr; 1189 | } 1190 | 1191 | //--------------------------------------------------------------------- 1192 | // tga - iload_tga_stream 1193 | //--------------------------------------------------------------------- 1194 | struct IBITMAP *iload_tga_stream(IMDIO *stream, IRGB *pal) 1195 | { 1196 | unsigned char image_palette[256][3]; 1197 | unsigned char id_length, palette_type, image_type, palette_entry_size; 1198 | unsigned char bpp, descriptor_bits; 1199 | IUINT32 c, i, y, yc, n, x; 1200 | IUINT16 palette_colors; 1201 | IUINT16 image_width, image_height; 1202 | unsigned char *lptr; 1203 | struct IBITMAP *bmp; 1204 | int compressed, want_palette, count; 1205 | IRGB tmppal[256]; 1206 | 1207 | assert(stream); 1208 | 1209 | _is_perrno_set(0); 1210 | 1211 | want_palette = 1; 1212 | if (!pal) { 1213 | want_palette = 0; 1214 | pal = tmppal; 1215 | } 1216 | 1217 | id_length = is_getc(stream); 1218 | palette_type = is_getc(stream); 1219 | image_type = is_getc(stream); 1220 | is_igetw(stream); 1221 | palette_colors = is_igetw(stream); 1222 | palette_entry_size = is_getc(stream); 1223 | is_igetw(stream); 1224 | is_igetw(stream); 1225 | image_width = is_igetw(stream); 1226 | image_height = is_igetw(stream); 1227 | bpp = is_getc(stream); 1228 | descriptor_bits = is_getc(stream); 1229 | 1230 | is_seekcur(stream, id_length); 1231 | 1232 | if (palette_type == 1) { 1233 | for (i = 0; i < (IUINT32)palette_colors; i++) { 1234 | if (palette_entry_size == 16) { 1235 | c = is_igetw(stream); 1236 | image_palette[i][0] = (IUINT8)_ipixel_scale_5[(c >> 0) & 31]; 1237 | image_palette[i][1] = (IUINT8)_ipixel_scale_5[(c >> 5) & 31]; 1238 | image_palette[i][2] = (IUINT8)_ipixel_scale_5[(c >> 10) & 31]; 1239 | } 1240 | else if (palette_entry_size >= 24) { 1241 | image_palette[i][0] = is_getc(stream); 1242 | image_palette[i][1] = is_getc(stream); 1243 | image_palette[i][2] = is_getc(stream); 1244 | if (palette_entry_size == 32) is_getc(stream); 1245 | 1246 | } 1247 | } 1248 | } 1249 | else if (palette_type != 0) { 1250 | _is_perrno_set(1); 1251 | return NULL; 1252 | } 1253 | 1254 | /* 1255 | * (image_type & 7): 1/colormapped, 2/truecolor, 3/grayscale 1256 | * (image_type & 8): 0/uncompressed, 8/compressed 1257 | */ 1258 | compressed = (image_type & 8); 1259 | image_type = (image_type & 7); 1260 | 1261 | if ((image_type < 1) || (image_type > 3)) { 1262 | _is_perrno_set(2); 1263 | return NULL; 1264 | } 1265 | 1266 | if (image_type == 1) { /* paletted image */ 1267 | if ((palette_type != 1) || (bpp != 8)) { 1268 | _is_perrno_set(11); 1269 | return NULL; 1270 | } 1271 | for(i = 0; i < (IUINT32)palette_colors; i++) { 1272 | pal[i].r = image_palette[i][2]; 1273 | pal[i].g = image_palette[i][1]; 1274 | pal[i].b = image_palette[i][0]; 1275 | } 1276 | } 1277 | else if (image_type == 2) { /* truecolor image */ 1278 | if (palette_type != 0) { 1279 | _is_perrno_set(21); 1280 | return NULL; 1281 | } 1282 | if (bpp != 15 && bpp != 16 && bpp != 24 && bpp != 32) { 1283 | _is_perrno_set(22); 1284 | return NULL; 1285 | } 1286 | if (bpp == 16) bpp = 15; 1287 | } 1288 | else if (image_type == 3) { /* grayscale image */ 1289 | if ((palette_type != 0) || (bpp != 8)) { 1290 | _is_perrno_set(31); 1291 | return NULL; 1292 | } 1293 | for (i = 0; i < 256; i++) { 1294 | pal[i].r = (unsigned char)(i); 1295 | pal[i].g = (unsigned char)(i); 1296 | pal[i].b = (unsigned char)(i); 1297 | } 1298 | } 1299 | 1300 | n = (bpp + 7) >> 3; 1301 | bmp = ibitmap_create(image_width, image_height, bpp); 1302 | if (!bmp) { 1303 | _is_perrno_set(50); 1304 | return NULL; 1305 | } 1306 | for (y = 0; y < bmp->h; y++) { 1307 | memset(bmp->line[y], 0, bmp->pitch); 1308 | } 1309 | 1310 | for (y = image_height; y; y--) { 1311 | yc = (descriptor_bits & 0x20) ? image_height - y : y - 1; 1312 | lptr = (unsigned char*)(bmp->line[yc]); 1313 | if (compressed == 0) { 1314 | raw_tga_readn(lptr, image_width, bpp, stream); 1315 | } else { 1316 | for (x = 0; x < (IUINT32)image_width; x += count) { 1317 | count = is_getc(stream); 1318 | if (count & 0x80) { 1319 | count = (count & 0x7F) + 1; 1320 | c = single_tga_readn(stream, bpp); 1321 | for (i = 0; i < (IUINT32)count; i++, lptr += n) { 1322 | if (n == 1) _ipixel_store_8(lptr, 0, c); 1323 | else if (n == 2) _ipixel_store_16(lptr, 0, c); 1324 | else if (n == 3) _ipixel_store_24(lptr, 0, c); 1325 | else if (n == 4) _ipixel_store_32(lptr, 0, c); 1326 | } 1327 | } else { 1328 | count = count + 1; 1329 | raw_tga_readn(lptr, count, bpp, stream); 1330 | lptr = lptr + n * count; 1331 | } 1332 | } 1333 | } 1334 | } 1335 | 1336 | if (_is_perrno_get()) { 1337 | ibitmap_release(bmp); 1338 | return NULL; 1339 | } 1340 | 1341 | ibitmap_pixfmt_set(bmp, ibitmap_pixfmt_guess(bmp)); 1342 | 1343 | /* construct a fake palette if 8-bit mode is not involved */ 1344 | if ((bpp != 8) && want_palette) { 1345 | // _igenerate_332_palette(pal); 1346 | } 1347 | 1348 | return bmp; 1349 | } 1350 | 1351 | //--------------------------------------------------------------------- 1352 | // tga - isave_tga_stream 1353 | //--------------------------------------------------------------------- 1354 | int isave_tga_stream(IMDIO *stream, struct IBITMAP *bmp, const IRGB *pal) 1355 | { 1356 | unsigned char image_palette[256][3]; 1357 | IUINT32 c, a, r, g, b, p; 1358 | long x, y, depth, n; 1359 | IRGB tmppal[256]; 1360 | int fmt; 1361 | 1362 | assert(bmp); 1363 | assert(stream); 1364 | 1365 | if (!pal) { 1366 | memcpy(tmppal, _ipaletted, 256 * sizeof(IRGB)); 1367 | pal = tmppal; 1368 | } 1369 | 1370 | depth = bmp->bpp; 1371 | 1372 | if (depth == 15) depth = 16; 1373 | _is_perrno_set(0); 1374 | 1375 | is_putc(stream, 0); /* id length (no id saved) */ 1376 | is_putc(stream, (depth == 8) ? 1 : 0); /* palette type */ 1377 | is_putc(stream, (depth == 8) ? 1 : 2); /* image type */ 1378 | is_iputw(stream, 0); /* first colour */ 1379 | is_iputw(stream, (depth == 8) ? 256 : 0); /* number of colours */ 1380 | is_putc(stream, (depth == 8) ? 24 : 0); /* palette entry size */ 1381 | is_iputw(stream, 0); /* left */ 1382 | is_iputw(stream, 0); /* top */ 1383 | is_iputw(stream, (int)bmp->w); /* width */ 1384 | is_iputw(stream, (int)bmp->h); /* height */ 1385 | is_putc(stream, depth); /* bits per pixel */ 1386 | is_putc(stream, (depth == 32) ? 8 : 0); /* descriptor 1387 | (bottom to top, 8-bit alpha) */ 1388 | 1389 | if (depth == 8) { 1390 | for (y = 0; y < 256; y++) { 1391 | image_palette[y][2] = pal[y].r; 1392 | image_palette[y][1] = pal[y].g; 1393 | image_palette[y][0] = pal[y].b; 1394 | is_putc(stream, image_palette[y][0]); 1395 | is_putc(stream, image_palette[y][1]); 1396 | is_putc(stream, image_palette[y][2]); 1397 | } 1398 | } 1399 | 1400 | n = (bmp->bpp + 7) / 8; 1401 | 1402 | fmt = _ibitmap_guess_pixfmt(bmp); 1403 | 1404 | for (y = (long)bmp->h - 1; y >= 0; y--) { 1405 | for (x = 0; x < (long)bmp->w; x++) { 1406 | c = _is_getpx(bmp, x, y); 1407 | p = _im_color_get(fmt, c, pal); 1408 | a = (p >> 24) & 0xFF; 1409 | r = (p >> 16) & 0xFF; 1410 | g = (p >> 8) & 0xFF; 1411 | b = (p >> 0) & 0xFF; 1412 | if (n == 1) is_putc(stream, c); 1413 | else if (n == 2) { 1414 | c = ((r << 7) & 0x7C00) | ((g << 2) & 0x3E0); 1415 | is_iputw(stream, c | ((b >> 3) & 0x1F)); 1416 | } 1417 | else if (n == 3 || n == 4) { 1418 | is_putc(stream, b); 1419 | is_putc(stream, g); 1420 | is_putc(stream, r); 1421 | if (n == 4) is_putc(stream, a); 1422 | } 1423 | } 1424 | } 1425 | 1426 | return 0; 1427 | } 1428 | 1429 | //--------------------------------------------------------------------- 1430 | // tga - isave_tga_file 1431 | //--------------------------------------------------------------------- 1432 | int isave_tga_file(const char *file, struct IBITMAP *bmp, const IRGB *pal) 1433 | { 1434 | IMDIO stream; 1435 | int retval; 1436 | 1437 | if (is_open_file(&stream, file, "wb")) return -1; 1438 | retval = isave_tga_stream(&stream, bmp, pal); 1439 | is_close_file(&stream); 1440 | 1441 | return retval; 1442 | } 1443 | 1444 | //--------------------------------------------------------------------- 1445 | // Loader Definition: 1446 | // Add new loader to load other picture formats 1447 | //--------------------------------------------------------------------- 1448 | static IPICLOADER iloader_table[256]; 1449 | 1450 | void iloader_table_init(void) 1451 | { 1452 | static int inited = 0; 1453 | int i; 1454 | if (inited) return; 1455 | for (i = 0; i < 256; i++) iloader_table[i] = NULL; 1456 | inited = 1; 1457 | } 1458 | 1459 | 1460 | //--------------------------------------------------------------------- 1461 | // setup a new loader: 1462 | // using First Byte of the Picture to choose loader for different formats 1463 | // NULL for disable the loader 1464 | //--------------------------------------------------------------------- 1465 | IPICLOADER ipic_loader(unsigned char firstbyte, IPICLOADER loader) 1466 | { 1467 | IPICLOADER oldloader; 1468 | iloader_table_init(); 1469 | oldloader = iloader_table[firstbyte]; 1470 | iloader_table[firstbyte] = loader; 1471 | return oldloader; 1472 | } 1473 | 1474 | //--------------------------------------------------------------------- 1475 | // recognize data stream and load picture 1476 | //--------------------------------------------------------------------- 1477 | struct IBITMAP *iload_picture(IMDIO *stream, IRGB *pal) 1478 | { 1479 | unsigned char firstbyte; 1480 | int ch; 1481 | 1482 | assert(stream); 1483 | 1484 | iloader_table_init(); 1485 | 1486 | ch = is_getc(stream); 1487 | if (ch < 0) return NULL; 1488 | is_ungetc(stream, ch); 1489 | 1490 | firstbyte = (unsigned char)(ch & 0xff); 1491 | if (iloader_table[firstbyte] != NULL) { 1492 | return iloader_table[firstbyte](stream, pal); 1493 | } 1494 | 1495 | if (ch == 'B') { 1496 | return iload_bmp_stream(stream, pal); 1497 | } else 1498 | if (ch == 'G') { 1499 | return iload_gif_stream(stream, pal); 1500 | } 1501 | return iload_tga_stream(stream, pal); 1502 | } 1503 | 1504 | 1505 | //===================================================================== 1506 | // ORIGINAL OPERATION 1507 | //===================================================================== 1508 | static IRGB _idefault_pal[256]; 1509 | 1510 | void ipic_read_pal(void *_pal) 1511 | { 1512 | memcpy(_pal, _idefault_pal, 256 * 4); 1513 | } 1514 | 1515 | void ipic_write_pal(const void *_pal) 1516 | { 1517 | memcpy(_idefault_pal, _pal, 256 * 4); 1518 | } 1519 | 1520 | struct IBITMAP *ipic_convert(struct IBITMAP *src, int dfmt, const IRGB *pal) 1521 | { 1522 | struct IBITMAP *bmp; 1523 | int sfmt; 1524 | int w, h; 1525 | w = (int)src->w; 1526 | h = (int)src->h; 1527 | sfmt = _ibitmap_guess_pixfmt(src); 1528 | if (sfmt == dfmt) { 1529 | bmp = ibitmap_create(w, h, src->bpp); 1530 | if (bmp == NULL) return NULL; 1531 | ibitmap_blit(bmp, 0, 0, src, 0, 0, w, h, 0); 1532 | return bmp; 1533 | } 1534 | bmp = ibitmap_convfmt(dfmt, src, pal, pal); 1535 | return bmp; 1536 | } 1537 | 1538 | struct IBITMAP *ipic_load_file(const char *file, long pos, IRGB *pal) 1539 | { 1540 | IMDIO stream; 1541 | struct IBITMAP *bmp; 1542 | IRGB *p = pal == NULL? _ipaletted : pal; 1543 | 1544 | if (is_open_file(&stream, file, "rb")) { 1545 | _is_perrno_set(-1); 1546 | return NULL; 1547 | } 1548 | fseek((FILE*)(stream.data), pos, SEEK_SET); 1549 | bmp = iload_picture(&stream, p); 1550 | is_close_file(&stream); 1551 | 1552 | return bmp; 1553 | } 1554 | 1555 | struct IBITMAP *ipic_load_mem(const void *ptr, long size, IRGB *pal) 1556 | { 1557 | IMDIO stream; 1558 | struct IBITMAP *bmp; 1559 | IRGB *p = pal == NULL ? _ipaletted : pal; 1560 | size = (size <= 0)? 0x7fffffffl : size; 1561 | is_init_mem(&stream, ptr, size); 1562 | bmp = iload_picture(&stream, p); 1563 | return bmp; 1564 | } 1565 | 1566 | 1567 | //===================================================================== 1568 | // 1569 | // GIF Operation Interface 1570 | // Since lzw's patent has expired, we can decode/encode gif freely 1571 | // 1572 | //===================================================================== 1573 | 1574 | //--------------------------------------------------------------------- 1575 | // _igif_clear_table - clear lzw table 1576 | //--------------------------------------------------------------------- 1577 | static void _igif_clear_table(IGIFDESC *gif) 1578 | { 1579 | gif->empty_string = gif->cc + 2; 1580 | gif->curr_bit_size = gif->bit_size + 1; 1581 | gif->bit_overflow = 0; 1582 | } 1583 | 1584 | //--------------------------------------------------------------------- 1585 | // _igif_get_code - get input code with current bit size 1586 | //--------------------------------------------------------------------- 1587 | static void _igif_get_code(IGIFDESC *gif) 1588 | { 1589 | if (gif->bit_pos + gif->curr_bit_size > 8) { 1590 | if (gif->data_pos >= gif->data_len) { 1591 | gif->data_len = is_getc(gif->stream); 1592 | gif->data_pos = 0; 1593 | } 1594 | gif->entire = (is_getc(gif->stream) << 8) + gif->entire; 1595 | gif->data_pos++; 1596 | } 1597 | if (gif->bit_pos + gif->curr_bit_size > 16) { 1598 | if (gif->data_pos >= gif->data_len) { 1599 | gif->data_len = is_getc(gif->stream); 1600 | gif->data_pos = 0; 1601 | } 1602 | gif->entire = (is_getc(gif->stream) << 16) + gif->entire; 1603 | gif->data_pos++; 1604 | } 1605 | gif->code = (gif->entire >> gif->bit_pos) & ((1 << 1606 | gif->curr_bit_size) - 1); 1607 | if (gif->bit_pos + gif->curr_bit_size > 8) 1608 | gif->entire >>= 8; 1609 | if (gif->bit_pos + gif->curr_bit_size > 16) 1610 | gif->entire >>= 8; 1611 | gif->bit_pos = (gif->bit_pos + gif->curr_bit_size) % 8; 1612 | if (gif->bit_pos == 0) { 1613 | if (gif->data_pos >= gif->data_len) { 1614 | gif->data_len = is_getc(gif->stream); 1615 | gif->data_pos = 0; 1616 | } 1617 | gif->entire = is_getc(gif->stream); 1618 | gif->data_pos++; 1619 | } 1620 | } 1621 | 1622 | //--------------------------------------------------------------------- 1623 | // _igif_get_string - get string into gif->string 1624 | //--------------------------------------------------------------------- 1625 | static void _igif_get_string(IGIFDESC *gif, int num) 1626 | { 1627 | unsigned char *string; 1628 | int i; 1629 | string = gif->string; 1630 | if (num < gif->cc) { 1631 | gif->string_length = 1; 1632 | string[0] = gif->newc[num]; 1633 | } else { 1634 | i = gif->str[num].length; 1635 | gif->string_length = i; 1636 | for (; i > 0; ) { 1637 | i--; 1638 | string[i] = gif->newc[num]; 1639 | num = gif->str[num].base; 1640 | } 1641 | } 1642 | } 1643 | 1644 | //--------------------------------------------------------------------- 1645 | // _igif_output_string - output string to bitmap 1646 | //--------------------------------------------------------------------- 1647 | static void _igif_output_string(IGIFDESC *gif) 1648 | { 1649 | unsigned char *string, **line, *ptr, mask; 1650 | int imgx, imgy, x, y, len, last, i; 1651 | if (gif->error || gif->bitmap == NULL) return; 1652 | x = gif->x; 1653 | y = gif->y; 1654 | imgx = gif->image_x; 1655 | imgy = gif->image_y; 1656 | line = (unsigned char**)gif->bitmap->line; 1657 | string = gif->string; 1658 | last = gif->string_length; 1659 | for (; last > 0; ) { 1660 | len = gif->image_w + imgx - x; 1661 | len = len > last ? last : len; 1662 | if (gif->transparent < 0) { 1663 | memcpy(line[y] + x, string, len); 1664 | x += len; 1665 | string += len; 1666 | } else { 1667 | mask = (unsigned char)gif->transparent; 1668 | ptr = line[y] + x; 1669 | for (i = len; i > 0; i--) { 1670 | if (string[0] != mask) *ptr = *string; 1671 | string++; 1672 | ptr++; 1673 | } 1674 | x += len; 1675 | } 1676 | last -= len; 1677 | if (x >= imgx + gif->image_w) { 1678 | x = imgx; 1679 | y += gif->interlace; 1680 | if (gif->interlace) { 1681 | if (y >= imgy + gif->image_h) { 1682 | if (gif->interlace == 8 && (y - imgy) % 8 == 0) { 1683 | gif->interlace = 8; 1684 | y = imgy + 4; 1685 | } else 1686 | if (gif->interlace == 8 && (y - imgy) % 8 == 4) { 1687 | gif->interlace = 4; 1688 | y = imgy + 2; 1689 | } else 1690 | if (gif->interlace == 4) { 1691 | gif->interlace = 2; 1692 | y = imgy + 1; 1693 | } 1694 | } 1695 | } 1696 | } 1697 | } 1698 | gif->x = x; 1699 | gif->y = y; 1700 | } 1701 | 1702 | //--------------------------------------------------------------------- 1703 | // ipic_gif_open - open gif and load header 1704 | //--------------------------------------------------------------------- 1705 | int ipic_gif_open(IGIFDESC *gif, IMDIO *stream, IRGB *pal, int customer) 1706 | { 1707 | long c, i; 1708 | 1709 | assert(gif && stream); 1710 | memset(gif, 0, sizeof(IGIFDESC)); 1711 | 1712 | gif->stream = stream; 1713 | 1714 | c = is_mgetw(stream) << 8; 1715 | c = c | is_getc(stream); 1716 | gif->state = -1; 1717 | if (c != 0x474946) { 1718 | return -1; 1719 | } 1720 | 1721 | is_seekcur(stream, 3); 1722 | 1723 | gif->width = is_igetw(stream); 1724 | gif->height = is_igetw(stream); 1725 | gif->flags = 0; 1726 | gif->delay = 0; 1727 | gif->hotx = 0; 1728 | gif->hoty = 0; 1729 | gif->frame = -1; 1730 | 1731 | gif->pal = pal; 1732 | gif->bpp = 0; 1733 | 1734 | c = is_getc(stream); 1735 | if (c & 128) 1736 | gif->bpp = (c & 7) + 1; 1737 | 1738 | gif->background = (unsigned char)is_getc(stream); 1739 | gif->aspect = (unsigned char)is_getc(stream); 1740 | 1741 | if (gif->bpp && pal) { 1742 | for (i = 0; i < (1 << gif->bpp); i++) { 1743 | pal[i].r = is_getc(stream); 1744 | pal[i].g = is_getc(stream); 1745 | pal[i].b = is_getc(stream); 1746 | } 1747 | } 1748 | else if (gif->bpp) { 1749 | is_seekcur(stream, (1 << gif->bpp) * 3); 1750 | } 1751 | 1752 | if (customer == 0) { 1753 | gif->bitmap = ibitmap_create(gif->width, gif->height * 2, 8); 1754 | if (gif->bitmap == NULL) { 1755 | return -2; 1756 | } 1757 | ibitmap_fill(gif->bitmap, 0, 0, gif->width, gif->height * 2, 1758 | gif->background, 0); 1759 | ibitmap_pixfmt_set(gif->bitmap, IPIX_FMT_C8); 1760 | } 1761 | 1762 | gif->state = 1; 1763 | gif->error = 0; 1764 | gif->transparent = -1; 1765 | gif->flags = customer? IGIF_CUSTOMERBMP : 0; 1766 | 1767 | return 0; 1768 | } 1769 | 1770 | //--------------------------------------------------------------------- 1771 | // ipic_gif_close - close gif and free bitmap 1772 | //--------------------------------------------------------------------- 1773 | int ipic_gif_close(IGIFDESC *gif) 1774 | { 1775 | if ((gif->flags & IGIF_CUSTOMERBMP) == 0) { 1776 | ibitmap_release(gif->bitmap); 1777 | gif->bitmap = NULL; 1778 | } 1779 | if (gif->state == 2 || gif->state == 3) { 1780 | is_putc(gif->stream, 0x3b); 1781 | } 1782 | gif->state = 0; 1783 | return 0; 1784 | } 1785 | 1786 | //--------------------------------------------------------------------- 1787 | // ipic_gif_read_image_desc - read image desc 1788 | //--------------------------------------------------------------------- 1789 | static int ipic_gif_read_image_desc(IGIFDESC *gif) 1790 | { 1791 | unsigned char *string; 1792 | IMDIO *stream; 1793 | int dispose, depth, old, i; 1794 | int retval = 0; 1795 | 1796 | if (gif->state != 1) return -1; 1797 | stream = gif->stream; 1798 | string = gif->string; 1799 | 1800 | gif->image_x = is_igetw(stream); 1801 | gif->image_y = is_igetw(stream); 1802 | gif->image_w = is_igetw(stream); 1803 | gif->image_h = is_igetw(stream); 1804 | 1805 | ibitmap_blit(gif->bitmap, gif->image_x, gif->image_y, gif->bitmap, 1806 | gif->image_x, gif->image_y + gif->height, gif->image_w, 1807 | gif->image_h, 0); 1808 | 1809 | if (gif->image_x < 0 || gif->image_y < 0 || 1810 | gif->image_x + gif->image_w > gif->width || 1811 | gif->image_y + gif->image_h > gif->height) 1812 | gif->error = 1; 1813 | 1814 | i = is_getc(stream); 1815 | if (i & 64) gif->interlace = 8; 1816 | else gif->interlace = 1; 1817 | 1818 | if (i & 128) { 1819 | depth = (i & 7) + 1; 1820 | if (gif->pal) { 1821 | for (i = 0; i < (1 << depth); i++) { 1822 | gif->pal[i].r = is_getc(stream); 1823 | gif->pal[i].g = is_getc(stream); 1824 | gif->pal[i].b = is_getc(stream); 1825 | } 1826 | } else { 1827 | is_seekcur(stream, (1 << depth) * 3); 1828 | } 1829 | } 1830 | 1831 | gif->bit_size = is_getc(stream); 1832 | gif->cc = 1 << gif->bit_size; 1833 | 1834 | for (i = 0; i < gif->cc; i++) { 1835 | gif->str[i].base = -1; 1836 | gif->str[i].length = 1; 1837 | gif->newc[i] = (unsigned char)i; 1838 | } 1839 | 1840 | gif->bit_pos = 0; 1841 | gif->data_len = is_getc(stream); 1842 | gif->data_pos = 0; 1843 | gif->entire = is_getc(stream); 1844 | gif->data_pos++; 1845 | gif->string_length = 0; 1846 | gif->x = gif->image_x; 1847 | gif->y = gif->image_y; 1848 | 1849 | _igif_clear_table(gif); 1850 | _igif_get_code(gif); 1851 | if (gif->code == gif->cc) 1852 | _igif_get_code(gif); 1853 | 1854 | _igif_get_string(gif, gif->code); 1855 | _igif_output_string(gif); 1856 | old = gif->code; 1857 | 1858 | for (; ; ) { 1859 | _igif_get_code(gif); 1860 | if (gif->code == gif->cc + 1) { 1861 | break; 1862 | } 1863 | if (gif->entire < 0) { 1864 | retval = -1; 1865 | gif->error = 2; 1866 | break; 1867 | } 1868 | if (gif->code == gif->cc) { 1869 | _igif_clear_table(gif); 1870 | _igif_get_code(gif); 1871 | _igif_get_string(gif, gif->code); 1872 | _igif_output_string(gif); 1873 | old = gif->code; 1874 | } else 1875 | if (gif->code < gif->empty_string) { 1876 | _igif_get_string(gif, gif->code); 1877 | _igif_output_string(gif); 1878 | if (gif->bit_overflow == 0) { 1879 | i = gif->empty_string; 1880 | gif->str[i].base = (short)old; 1881 | gif->str[i].length = gif->str[old].length + 1; 1882 | gif->newc[i] = string[0]; 1883 | gif->empty_string++; 1884 | if (gif->empty_string == (1 << gif->curr_bit_size)) 1885 | gif->curr_bit_size++; 1886 | if (gif->curr_bit_size == 13) { 1887 | gif->curr_bit_size = 12; 1888 | gif->bit_overflow = 1; 1889 | } 1890 | } 1891 | old = gif->code; 1892 | } else { 1893 | _igif_get_string(gif, old); 1894 | string[gif->str[old].length] = string[0]; 1895 | gif->string_length++; 1896 | if (gif->bit_overflow == 0) { 1897 | i = gif->empty_string; 1898 | gif->str[i].base = (short)old; 1899 | gif->str[i].length = gif->str[old].length + 1; 1900 | gif->newc[i] = string[0]; 1901 | gif->empty_string++; 1902 | if (gif->empty_string == (1 << gif->curr_bit_size)) 1903 | gif->curr_bit_size++; 1904 | if (gif->curr_bit_size == 13) { 1905 | gif->curr_bit_size = 12; 1906 | gif->bit_overflow = 1; 1907 | } 1908 | } 1909 | _igif_output_string(gif); 1910 | old = gif->code; 1911 | } 1912 | } 1913 | 1914 | dispose = (gif->method >> 2) & 7; 1915 | if (dispose == 2) { 1916 | i = gif->transparent >= 0? gif->transparent : gif->background; 1917 | ibitmap_fill(gif->bitmap, gif->image_x, gif->image_y + gif->height, 1918 | gif->image_w, gif->image_h, i, 0); 1919 | } else 1920 | if (dispose != 3) { 1921 | ibitmap_blit(gif->bitmap, gif->image_x, gif->image_y + gif->height, 1922 | gif->bitmap, gif->image_x, gif->image_y, 1923 | gif->image_w, gif->image_h, 0); 1924 | } 1925 | 1926 | gif->frame++; 1927 | 1928 | return retval; 1929 | } 1930 | 1931 | //--------------------------------------------------------------------- 1932 | // ipic_gif_read_extension - read extension 1933 | //--------------------------------------------------------------------- 1934 | int ipic_gif_read_extension(IGIFDESC *gif, int firstcmd) 1935 | { 1936 | IMDIO *stream; 1937 | int control, c; 1938 | char ident[12]; 1939 | 1940 | stream = gif->stream; 1941 | gif->delay = 0; 1942 | gif->transparent = -1; 1943 | gif->method = 0; 1944 | 1945 | if (firstcmd < 0) control = is_getc(stream); 1946 | else control = firstcmd; 1947 | 1948 | if (control == 0xf9) { 1949 | c = is_getc(stream); 1950 | if (c != 4) return -1; 1951 | 1952 | gif->method = is_getc(stream); 1953 | gif->delay = is_igetw(stream); 1954 | 1955 | gif->transparent = is_getc(stream); 1956 | gif->bitmap->mask = (unsigned char)gif->transparent; 1957 | 1958 | if ((gif->method & 1) == 0) 1959 | gif->transparent = -1; 1960 | 1961 | c = (gif->method >> 2) & 7; 1962 | 1963 | if (c == 20) { 1964 | } 1965 | } else 1966 | if (control == 0xff) { 1967 | c = is_getc(stream); 1968 | if (c == 0x0b) { 1969 | is_reader(stream, ident, 0x0b); 1970 | if (memcmp(ident, "PIXIAGIF.CH", 0x0b) == 0) { 1971 | c = is_getc(stream); 1972 | if (c == 5) { 1973 | c = is_getc(stream); 1974 | gif->flags = (gif->flags & ~0xff) | (c & 0xff); 1975 | gif->hotx = (short)is_igetw(stream); 1976 | gif->hoty = (short)is_igetw(stream); 1977 | } else { 1978 | is_ungetc(stream, c); 1979 | } 1980 | } 1981 | } else { 1982 | is_ungetc(stream, c); 1983 | } 1984 | } 1985 | 1986 | for (; ; ) { 1987 | c = is_getc(stream); 1988 | if (c <= 0) break; 1989 | is_seekcur(stream, c); 1990 | } 1991 | 1992 | return 0; 1993 | } 1994 | 1995 | //--------------------------------------------------------------------- 1996 | // ipic_gif_read_frame - read single frame 1997 | //--------------------------------------------------------------------- 1998 | int ipic_gif_read_frame(IGIFDESC *gif) 1999 | { 2000 | int retval, type; 2001 | if (gif->state != 1) return -1; 2002 | 2003 | for (retval = 0; gif->error == 0; ) { 2004 | type = is_getc(gif->stream); 2005 | if (type < 0 || type == 0x3b || gif->error) { 2006 | retval = -2; 2007 | break; 2008 | } 2009 | if (type == 0) continue; 2010 | switch (type) 2011 | { 2012 | case 0x21: 2013 | ipic_gif_read_extension(gif, -1); 2014 | break; 2015 | case 0x2c: 2016 | ipic_gif_read_image_desc(gif); 2017 | type = 0; 2018 | break; 2019 | case 0x01: 2020 | case 0xf9: 2021 | case 0xfe: 2022 | case 0xff: 2023 | ipic_gif_read_extension(gif, type); 2024 | break; 2025 | default: 2026 | //printf("gif unknow %d\n", type); 2027 | retval = -3; 2028 | gif->error = 5; 2029 | break; 2030 | } 2031 | if (type == 0) break; 2032 | } 2033 | return retval; 2034 | } 2035 | 2036 | //--------------------------------------------------------------------- 2037 | // load gif picture from stream 2038 | //--------------------------------------------------------------------- 2039 | struct IBITMAP *iload_gif_stream(IMDIO *stream, IRGB *pal) 2040 | { 2041 | struct IBITMAP *bmp; 2042 | IGIFDESC *gif; 2043 | gif = (IGIFDESC*)malloc(sizeof(IGIFDESC)); 2044 | if (gif == NULL) return NULL; 2045 | if (ipic_gif_open(gif, stream, pal, 0) != 0) { 2046 | free(gif); 2047 | return NULL; 2048 | } 2049 | for (; ; ) { 2050 | if (ipic_gif_read_frame(gif) < 0) break; 2051 | } 2052 | bmp = ibitmap_create(gif->width, gif->height, 8); 2053 | if (bmp == NULL) { 2054 | ibitmap_release(gif->bitmap); 2055 | free(gif); 2056 | return NULL; 2057 | } 2058 | ibitmap_blit(bmp, 0, 0, gif->bitmap, 0, 0, gif->width, 2059 | gif->height, 0); 2060 | bmp->mask = (gif->transparent & 0xffff) | ((gif->flags & 0xffff) << 16); 2061 | bmp->mode = (gif->hotx << 16) | (gif->hoty & 0xffff); 2062 | ibitmap_release(gif->bitmap); 2063 | free(gif); 2064 | return bmp; 2065 | } 2066 | 2067 | //--------------------------------------------------------------------- 2068 | // open gif stream for saving 2069 | //--------------------------------------------------------------------- 2070 | int ipic_gif_wopen(IGIFDESC *gif, IMDIO *stream, const IRGB *pal, 2071 | int w, int h, int background, int aspect, int flags, long hotxy) 2072 | { 2073 | int i; 2074 | 2075 | assert(gif && stream); 2076 | memset(gif, 0, sizeof(IGIFDESC)); 2077 | 2078 | pal = pal ? pal : (const IRGB*)_ipaletted; 2079 | 2080 | gif->stream = stream; 2081 | gif->pal = (IRGB*)pal; 2082 | gif->width = w; 2083 | gif->height = h; 2084 | gif->bpp = 8; 2085 | gif->background = background; 2086 | gif->aspect = aspect <= 0 ? 0 : aspect; 2087 | 2088 | gif->image_x = 0; 2089 | gif->image_y = 0; 2090 | gif->image_w = w; 2091 | gif->image_h = h; 2092 | gif->interlace = 1; 2093 | gif->flags = flags; 2094 | gif->x = 0; 2095 | gif->y = 0; 2096 | gif->hotx = (short)((hotxy >> 16) & 0xffff); 2097 | gif->hoty = (short)(hotxy & 0xffff); 2098 | 2099 | if ((gif->flags & IGIF_CUSTOMERBMP) == 0) { 2100 | gif->bitmap = ibitmap_create(gif->width, gif->height * 2, 8); 2101 | if (gif->bitmap == NULL) { 2102 | return -1; 2103 | } 2104 | ibitmap_fill(gif->bitmap, 0, 0, gif->width, gif->height * 2, 2105 | gif->background, 0); 2106 | } 2107 | 2108 | if (gif->flags & 0xff) flags |= IGIF_ANIMATE; 2109 | 2110 | is_writer(stream, "GIF", 3); 2111 | is_writer(stream, (flags & IGIF_ANIMATE) ? "89a" : "87a", 3); 2112 | is_iputw(stream, gif->width); 2113 | is_iputw(stream, gif->height); 2114 | is_putc(stream, 0xf7); 2115 | is_putc(stream, gif->background); 2116 | is_putc(stream, gif->aspect); 2117 | 2118 | for (i = 0; i < 256; i++) { 2119 | is_putc(stream, pal[i].r); 2120 | is_putc(stream, pal[i].g); 2121 | is_putc(stream, pal[i].b); 2122 | } 2123 | 2124 | gif->transparent = -1; 2125 | gif->flags = flags; 2126 | gif->error = 0; 2127 | gif->delay = (flags & IGIF_ANIMATE) ? 0 : -1; 2128 | gif->state = (flags & IGIF_ANIMATE) ? 3 : 2; 2129 | 2130 | if (gif->flags & 0xff) { 2131 | is_putc(stream, 0x21); 2132 | is_putc(stream, 0xff); 2133 | is_putc(stream, 0x0b); 2134 | is_writer(stream, "PIXIAGIF.CH", 0x0b); 2135 | is_putc(stream, 5); 2136 | is_putc(stream, gif->flags & 0xff); 2137 | is_iputw(stream, gif->hotx); 2138 | is_iputw(stream, gif->hoty); 2139 | is_putc(stream, 0); 2140 | } 2141 | 2142 | return 0; 2143 | } 2144 | 2145 | //--------------------------------------------------------------------- 2146 | // _igif_write_code - write bits into buffer 2147 | //--------------------------------------------------------------------- 2148 | static void _igif_write_code(IGIFDESC *gif, int code, int bit_size) 2149 | { 2150 | if (code < 0) { 2151 | gif->entire &= (1 << gif->bit_pos) - 1; 2152 | gif->string[gif->data_len] = (unsigned char)gif->entire; 2153 | gif->entire >>= 8; 2154 | gif->data_len++; 2155 | is_putc(gif->stream, gif->data_len); 2156 | is_writer(gif->stream, gif->string, gif->data_len); 2157 | gif->data_len = 0; 2158 | gif->bit_pos = 0; 2159 | return; 2160 | } 2161 | 2162 | gif->entire |= code << (gif->bit_pos); 2163 | gif->bit_pos += bit_size; 2164 | while (gif->bit_pos >= 8) { 2165 | gif->string[gif->data_len] = (unsigned char)(gif->entire & 255); 2166 | gif->entire >>= 8; 2167 | gif->bit_pos -= 8; 2168 | gif->data_len++; 2169 | if (gif->data_len >= 252) { 2170 | is_putc(gif->stream, gif->data_len); 2171 | is_writer(gif->stream, gif->string, gif->data_len); 2172 | gif->data_len = 0; 2173 | } 2174 | } 2175 | } 2176 | 2177 | //--------------------------------------------------------------------- 2178 | // _igif_get_next_color - get next color 2179 | //--------------------------------------------------------------------- 2180 | static int _igif_get_next_color(IGIFDESC *gif) 2181 | { 2182 | int x = gif->x; 2183 | int y = gif->y; 2184 | int c; 2185 | 2186 | if (--gif->string_length < 0) return -1; 2187 | 2188 | c = ((unsigned char*)gif->bitmap->line[y])[x]; 2189 | if (++x >= gif->image_x + gif->image_w) { 2190 | x = gif->image_x; 2191 | y += gif->interlace; 2192 | if (gif->interlace) { 2193 | if (y >= gif->image_y + gif->image_h) { 2194 | if (gif->interlace == 8 && (y - gif->image_y) % 8 == 0) { 2195 | gif->interlace = 8; 2196 | y = gif->image_y + 4; 2197 | } else 2198 | if (gif->interlace == 8 && (y - gif->image_y) % 8 == 4) { 2199 | gif->interlace = 4; 2200 | y = gif->image_y + 2; 2201 | } else 2202 | if (gif->interlace == 4) { 2203 | gif->interlace = 2; 2204 | y = gif->image_y + 1; 2205 | } 2206 | } 2207 | } 2208 | } 2209 | gif->x = x; 2210 | gif->y = y; 2211 | return c; 2212 | } 2213 | 2214 | //--------------------------------------------------------------------- 2215 | // ipic_gif_write_image_desc - encode image desc 2216 | //--------------------------------------------------------------------- 2217 | static int ipic_gif_write_image_desc(IGIFDESC *gif, int palsize) 2218 | { 2219 | IMDIO *stream; 2220 | int palshift, mask, c, i, k; 2221 | int string_buffer = 0; 2222 | int color_num; 2223 | int written; 2224 | int hash; 2225 | int length; 2226 | int interlace; 2227 | short *next; 2228 | 2229 | if (gif->state != 2 && gif->state != 3) 2230 | return -1; 2231 | 2232 | stream = gif->stream; 2233 | is_putc(stream, 0x2c); 2234 | is_iputw(stream, gif->image_x); 2235 | is_iputw(stream, gif->image_y); 2236 | is_iputw(stream, gif->image_w); 2237 | is_iputw(stream, gif->image_h); 2238 | gif->x = gif->image_x; 2239 | gif->y = gif->image_y; 2240 | 2241 | palsize = palsize < 0 ? 0 : palsize; 2242 | for (palshift = 0; palshift < 8; palshift++) 2243 | if ((1 << (palshift + 1)) >= palsize) break; 2244 | palsize = palsize == 0 ? 0 : (1 << (palshift + 1)); 2245 | if (gif->interlace <= 1) gif->interlace = 1; 2246 | else gif->interlace = 8; 2247 | mask = palsize? 0x80 : 0; 2248 | mask |= gif->interlace == 8 ? 0x40 : 0; 2249 | mask |= palshift & 7; 2250 | 2251 | is_putc(stream, mask); 2252 | if (palsize > 0) { 2253 | if (gif->pal) { 2254 | for (i = 0; i < palsize; i++) { 2255 | is_putc(stream, gif->pal[i].r); 2256 | is_putc(stream, gif->pal[i].g); 2257 | is_putc(stream, gif->pal[i].b); 2258 | } 2259 | } else { 2260 | for (i = 0; i < palsize; i++) { 2261 | is_putc(stream, i); 2262 | is_putc(stream, i); 2263 | is_putc(stream, i); 2264 | } 2265 | } 2266 | } 2267 | 2268 | gif->string_length = gif->image_w * gif->image_h; 2269 | interlace = gif->interlace; 2270 | for (c = 0, k = 0; c >= 0; ) { 2271 | c = _igif_get_next_color(gif); 2272 | if (c > k) k = c; 2273 | } 2274 | 2275 | for (c = 1; c <= 8; c++) 2276 | if ((1 << c) >= k) break; 2277 | 2278 | gif->bit_size = c; 2279 | gif->cc = 1 << gif->bit_size; 2280 | is_putc(stream, gif->bit_size); 2281 | 2282 | for (i = 0; i < gif->cc + 2; i++) { 2283 | gif->str[i].base = -1; 2284 | gif->str[i].length = 1; 2285 | gif->newc[i] = (unsigned char)i; 2286 | } 2287 | 2288 | next = (short*)(gif->string + 2048); 2289 | for (i = 0; i < 1024; i++) next[i] = -1; 2290 | 2291 | gif->bit_pos = 0; 2292 | gif->data_len = 0; 2293 | gif->data_pos = 0; 2294 | gif->string_length = gif->image_w * gif->image_h; 2295 | gif->x = gif->image_x; 2296 | gif->y = gif->image_y; 2297 | gif->interlace = interlace; 2298 | 2299 | #define _igif_write(g, c) _igif_write_code(g, c, g->curr_bit_size) 2300 | 2301 | _igif_clear_table(gif); 2302 | _igif_write(gif, gif->cc); 2303 | 2304 | for (length = 0; ; ) { 2305 | 2306 | c = _igif_get_next_color(gif); 2307 | if (c < 0) break; 2308 | length++; 2309 | 2310 | if (length == 1) { 2311 | string_buffer = c; 2312 | continue; 2313 | } 2314 | 2315 | /* calculate hash entry */ 2316 | hash = ((string_buffer << (gif->bit_size - 1)) | c) & 0x3ff; 2317 | length++; 2318 | 2319 | /* alias str[i].length as str[i].next to reduce memory */ 2320 | for (i = next[hash]; i >= 0; i = gif->str[i].length) { 2321 | if (gif->str[i].base != string_buffer) continue; 2322 | if (gif->newc[i] == c) break; 2323 | } 2324 | 2325 | if (i >= 0) { 2326 | string_buffer = i; 2327 | written = 0; 2328 | } else { 2329 | _igif_write(gif, string_buffer); 2330 | color_num = gif->empty_string++; 2331 | written = 1; 2332 | 2333 | /* alias str[i].length as str[i].next to reduce memory */ 2334 | if (color_num < 4096) { 2335 | gif->str[color_num].base = string_buffer; 2336 | gif->str[color_num].length = next[hash]; 2337 | next[hash] = color_num; 2338 | gif->newc[color_num] = c; 2339 | } 2340 | 2341 | string_buffer = c; 2342 | length = 1; 2343 | 2344 | if (color_num >= (1 << gif->curr_bit_size)) 2345 | gif->curr_bit_size++; 2346 | 2347 | if (color_num >= 4094) { 2348 | _igif_write(gif, string_buffer); 2349 | _igif_write(gif, gif->cc); 2350 | _igif_clear_table(gif); 2351 | for (i = 0; i < 1024; i++) next[i] = -1; 2352 | length = 0; 2353 | } 2354 | } 2355 | } 2356 | 2357 | _igif_write(gif, string_buffer); 2358 | 2359 | _igif_write(gif, gif->cc + 1); 2360 | _igif_write(gif, -1); 2361 | 2362 | #undef _igif_write 2363 | 2364 | is_putc(stream, 0); 2365 | is_putc(stream, 0); 2366 | 2367 | written = written; 2368 | 2369 | return 0; 2370 | } 2371 | 2372 | //--------------------------------------------------------------------- 2373 | // ipic_gif_write_frame - write frame into gif 2374 | //--------------------------------------------------------------------- 2375 | int ipic_gif_write_frame(IGIFDESC *gif, int delay, int mask, int palsize) 2376 | { 2377 | IMDIO *stream; 2378 | 2379 | assert(gif); 2380 | stream = gif->stream; 2381 | 2382 | if (gif->flags & IGIF_ANIMATE) { 2383 | delay = delay < 0 ? 0 : delay; 2384 | is_putc(stream, 0x21); 2385 | is_putc(stream, 0xf9); 2386 | is_putc(stream, 0x04); 2387 | is_putc(stream, mask >= 0? 1 : 0); 2388 | is_iputw(stream, delay); 2389 | is_putc(stream, mask & 0xff); 2390 | is_putc(stream, 0x00); 2391 | } 2392 | 2393 | ipic_gif_write_image_desc(gif, palsize); 2394 | 2395 | return 0; 2396 | } 2397 | 2398 | //--------------------------------------------------------------------- 2399 | // save gif picture to stream 2400 | //--------------------------------------------------------------------- 2401 | int isave_gif_stream(IMDIO *stream, struct IBITMAP *bmp, const IRGB *pal) 2402 | { 2403 | IGIFDESC *gif; 2404 | long flags; 2405 | long hotxy; 2406 | 2407 | assert(stream && bmp); 2408 | 2409 | gif = (IGIFDESC*)malloc(sizeof(IGIFDESC)); 2410 | if (gif == NULL) return 0; 2411 | 2412 | flags = (bmp->mask >> 16) & 0xffff; 2413 | hotxy = bmp->mode; 2414 | if (hotxy != 0 || (flags & 0xff)) flags |= IGIF_ANIMATE; 2415 | 2416 | if (ipic_gif_wopen(gif, stream, pal, bmp->w, bmp->h, 2417 | bmp->mask & 0xff, 0, flags, hotxy)) { 2418 | free(gif); 2419 | return -1; 2420 | } 2421 | 2422 | gif->transparent = (short)(bmp->mask & 0xffff); 2423 | /*gif->transparent = -1; */ 2424 | 2425 | ibitmap_blit(gif->bitmap, 0, 0, bmp, 0, 0, bmp->w, bmp->h, 0); 2426 | ipic_gif_write_frame(gif, 0, bmp->mask & 0xff, 0); 2427 | ipic_gif_close(gif); 2428 | 2429 | free(gif); 2430 | return 0; 2431 | } 2432 | 2433 | //--------------------------------------------------------------------- 2434 | // save gif picture to stream 2435 | //--------------------------------------------------------------------- 2436 | int isave_gif_file(const char *file, struct IBITMAP *bmp, const IRGB *pal) 2437 | { 2438 | IMDIO stream; 2439 | if (is_open_file(&stream, file, "wb")) { 2440 | return -1; 2441 | } 2442 | isave_gif_stream(&stream, bmp, pal); 2443 | is_close_file(&stream); 2444 | return 0; 2445 | } 2446 | 2447 | 2448 | -------------------------------------------------------------------------------- /pixellib/ipicture.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // ipicture.h - general picture file operation 4 | // 5 | // FEATURES: 6 | // * I/O stream support 7 | // * save and load tga/bmp/gif 8 | // 9 | // NOTE: 10 | // require ibitmap.h, ibmbits.h, ibmcols.h 11 | // for more information, please see the readme file 12 | // 13 | //===================================================================== 14 | 15 | #ifndef __I_PICTURE_H__ 16 | #define __I_PICTURE_H__ 17 | 18 | #include "ibitmap.h" 19 | #include "ibmbits.h" 20 | #include "ibmcols.h" 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | 26 | 27 | //===================================================================== 28 | // 29 | // PICTURE DATA INTERFACE 30 | // 31 | // IMDIO - Media Data Input/Output Interface 32 | // PIXELS - Pixel Operation for Bitmaps 33 | // FIXUP - Pixel Format Fixing Up Interface 34 | // 35 | //===================================================================== 36 | 37 | //--------------------------------------------------------------------- 38 | // Media Data Streaming Input/Output Interface 39 | //--------------------------------------------------------------------- 40 | typedef struct IMDIO 41 | { 42 | int (*getc)(struct IMDIO *stream); 43 | int (*putc)(struct IMDIO *stream, int c); 44 | long _code, _pos, _len, _ch, _bitc, _bitd; 45 | long _cnt, _ungetc; 46 | void *data; 47 | } IMDIO; 48 | 49 | int is_getc(IMDIO *stream); 50 | int is_putc(IMDIO *stream, int c); 51 | 52 | int is_ungetc(IMDIO *stream, int c); 53 | 54 | long is_reader(IMDIO *stream, void *buffer, long size); 55 | long is_writer(IMDIO *stream, const void *buffer, long size); 56 | 57 | int is_igetw(IMDIO *stream); 58 | int is_iputw(IMDIO *stream, int w); 59 | long is_igetl(IMDIO *stream); 60 | long is_iputl(IMDIO *stream, long l); 61 | 62 | int is_mgetw(IMDIO *stream); 63 | int is_mputw(IMDIO *stream, int w); 64 | long is_mgetl(IMDIO *stream); 65 | long is_mputl(IMDIO *stream, long l); 66 | 67 | long is_igetbits(IMDIO *stream, int count); 68 | long is_iputbits(IMDIO *stream, long data, int count); 69 | void is_iflushbits(IMDIO *stream, int isflushwrite); 70 | 71 | long is_mgetbits(IMDIO *stream, int count); 72 | long is_mputbits(IMDIO *stream, long data, int count); 73 | void is_mflushbits(IMDIO *stream, int isflushwrite); 74 | 75 | void is_seekcur(IMDIO *stream, long skip); 76 | 77 | 78 | //--------------------------------------------------------------------- 79 | // stream operation 80 | //--------------------------------------------------------------------- 81 | int is_init_mem(IMDIO *stream, const void *lptr, long size); 82 | int is_open_file(IMDIO *stream, const char *filename, const char *rw); 83 | int is_close_file(IMDIO *stream); 84 | 85 | void _is_perrno_set(long v); 86 | long _is_perrno_get(void); 87 | 88 | void *is_read_marked_block(IMDIO *stream, const unsigned char *mark, 89 | int marksize, size_t *nbytes_readed); 90 | 91 | 92 | //===================================================================== 93 | // 94 | // PICTURE MEDIA OPERATION 95 | // 96 | // BMP - Windows/OS2 IBITMAP Format, load/save supported 97 | // TGA - Tagged Graphics (Truevision Inc) Format, load/save supported 98 | // GIF - Graphics Interchange Format (CompuServe Inc), load supported 99 | // 100 | //===================================================================== 101 | 102 | 103 | //--------------------------------------------------------------------- 104 | // Picture Loading / Saving - Original Interface 105 | //--------------------------------------------------------------------- 106 | // load bmp picture from stream 107 | struct IBITMAP *iload_bmp_stream(IMDIO *stream, IRGB *pal); 108 | 109 | // load bmp picture from stream 110 | struct IBITMAP *iload_tga_stream(IMDIO *stream, IRGB *pal); 111 | 112 | // load single gif frame from stream 113 | struct IBITMAP *iload_gif_stream(IMDIO *stream, IRGB *pal); 114 | 115 | // save bmp picture to stream 116 | int isave_bmp_stream(IMDIO *stream, struct IBITMAP *bmp, const IRGB *pal); 117 | 118 | // save tga picture to stream 119 | int isave_tga_stream(IMDIO *stream, struct IBITMAP *bmp, const IRGB *pal); 120 | 121 | // save gif picture to stream 122 | int isave_gif_stream(IMDIO *stream, struct IBITMAP *bmp, const IRGB *pal); 123 | 124 | 125 | 126 | //--------------------------------------------------------------------- 127 | // Picture Loading With Format Detecting 128 | //--------------------------------------------------------------------- 129 | 130 | // Loader Definition: 131 | // Add new loader to load other picture formats 132 | typedef struct IBITMAP *(*IPICLOADER)(IMDIO *stream, IRGB *pal); 133 | 134 | // setup a new loader: 135 | // using First Byte of the Picture to choose loader for different formats 136 | // NULL for disable the loader 137 | // eg: FirstByte of BMP/GIF/PNG/JPG is 'B'/'G'/0x89/0xff 138 | IPICLOADER ipic_loader(unsigned char firstbyte, IPICLOADER loader); 139 | 140 | // recognize data stream and load picture 141 | struct IBITMAP *iload_picture(IMDIO *stream, IRGB *pal); 142 | 143 | 144 | //--------------------------------------------------------------------- 145 | // Picture Saving - Standard Interface 146 | //--------------------------------------------------------------------- 147 | // save bmp picture to file 148 | int isave_bmp_file(const char *file, struct IBITMAP *bmp, const IRGB *pal); 149 | 150 | // save tga picture to file 151 | int isave_tga_file(const char *file, struct IBITMAP *bmp, const IRGB *pal); 152 | 153 | // save gif picture to file 154 | int isave_gif_file(const char *file, struct IBITMAP *bmp, const IRGB *pal); 155 | 156 | 157 | //--------------------------------------------------------------------- 158 | // ORIGINAL OPERATION 159 | //--------------------------------------------------------------------- 160 | struct IBITMAP *ipic_load_file(const char *file, long pos, IRGB *pal); 161 | struct IBITMAP *ipic_load_mem(const void *ptr, long size, IRGB *pal); 162 | 163 | struct IBITMAP *ipic_convert(struct IBITMAP *src, int fmt, const IRGB *pal); 164 | 165 | 166 | //--------------------------------------------------------------------- 167 | // GIF INTERFACE (LZW PATENT HAS EXPIRED NOW) 168 | //--------------------------------------------------------------------- 169 | struct IGIFDESC /* gif descriptor */ 170 | { 171 | int width; /* screen width */ 172 | int height; /* screen height */ 173 | int bpp; /* color depth */ 174 | int state; /* decode state */ 175 | int aspect; /* aspect */ 176 | int error; /* decode/encode error */ 177 | int empty_string; /* lzw - empty_string pointer */ 178 | int curr_bit_size; /* lzw - current bit size */ 179 | int bit_overflow; /* lzw - is table size greater than 4096 */ 180 | int bit_pos; /* lzw - loading bit position */ 181 | int data_pos; /* lzw - loading data position */ 182 | int data_len; /* lzw - loading data length */ 183 | int entire; /* lzw - loading data entire */ 184 | int code; /* lzw - code loaded */ 185 | int cc; /* lzw - table size */ 186 | int string_length; /* lzw - string length */ 187 | int bit_size; /* lzw - bit size */ 188 | int image_x; /* image descriptor - image x */ 189 | int image_y; /* image descriptor - image y */ 190 | int image_w; /* image descriptor - image width */ 191 | int image_h; /* image descriptor - image height */ 192 | int interlace; /* image descriptor - interlace */ 193 | int x; /* image descriptor - current x */ 194 | int y; /* image descriptor - current y */ 195 | int flags; /* flags */ 196 | int transparent; /* extension - color transparent */ 197 | int method; /* extension - rander method */ 198 | long delay; /* extension - time delay */ 199 | long frame; /* extension - frame count */ 200 | int hotx; /* extension - hotpoint x */ 201 | int hoty; /* extension - hotpoint y */ 202 | IRGB *pal; /* current palette */ 203 | IMDIO *stream; /* input / output stream */ 204 | struct IBITMAP *bitmap; /* bitmap */ 205 | unsigned char background; /* background color */ 206 | unsigned char string[4096]; /* decode string */ 207 | unsigned char newc[4096]; /* dict new char */ 208 | struct { short base, length; } str[4096]; /* lzw table */ 209 | }; 210 | 211 | typedef struct IGIFDESC IGIFDESC; 212 | 213 | #define IGIF_ANIMATE 256 214 | #define IGIF_CUSTOMERBMP 512 215 | #define IGIF_EXTMASK 255 216 | 217 | 218 | // load gif header, allocate bitmap if customer is false 219 | int ipic_gif_open(IGIFDESC *gif, IMDIO *stream, IRGB *pal, int customer); 220 | 221 | // close gif and free bitmap 222 | int ipic_gif_close(IGIFDESC *gif); 223 | 224 | // returns delay time, below zero for eof or error 225 | int ipic_gif_read_frame(IGIFDESC *gif); 226 | 227 | // write gif header, allocate bitmap if IGIF_CUSTOMERBMP flag is 0 228 | int ipic_gif_wopen(IGIFDESC *gif, IMDIO *stream, const IRGB *pal, 229 | int w, int h, int background, int aspect, int flags, long hotxy); 230 | 231 | // write frame into gif stream 232 | int ipic_gif_write_frame(IGIFDESC *gif, int delay, int mask, int palsize); 233 | 234 | 235 | 236 | #ifdef __cplusplus 237 | } 238 | #endif 239 | 240 | #endif 241 | 242 | 243 | -------------------------------------------------------------------------------- /pixellib/mswindx.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/pixellib/mswindx.c -------------------------------------------------------------------------------- /pixellib/mswindx.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/pixellib/mswindx.h -------------------------------------------------------------------------------- /pixellib/npixel.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/pixellib/npixel.c -------------------------------------------------------------------------------- /pixellib/npixel.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/pixellib/npixel.h -------------------------------------------------------------------------------- /wrap/PixelBitmap.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/wrap/PixelBitmap.cpp -------------------------------------------------------------------------------- /wrap/PixelBitmap.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/wrap/PixelBitmap.h -------------------------------------------------------------------------------- /wrap/PixelWin32.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/wrap/PixelWin32.cpp -------------------------------------------------------------------------------- /wrap/PixelWin32.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/wrap/PixelWin32.h --------------------------------------------------------------------------------