├── .gitignore ├── test-ok ├── in1.bmp ├── in1.png ├── in2.bmp ├── in2.png ├── out1.bmp ├── out1.png ├── out2.bmp ├── out2.png └── get-files.sh ├── Makefile ├── testcases.sh ├── LICENSE ├── costella ├── costella_image_default.h ├── costella_debug_default.h ├── costella_types_ansi.h ├── costella_debug.h ├── costella_unblock.h ├── costella_types.h ├── costella_body.h ├── costella_wrap.h ├── costella_image_chrominance.h ├── costella_image.h ├── costella_image.c ├── costella_image_convert.h ├── costella_image_win32_dib.h ├── costella_image_rgb_triple.h ├── costella_image_separate_arrays.h ├── costella_wrap.c ├── costella_base.h ├── costella_base.c ├── costella_image_convert.c └── costella_image_chrominance.c ├── README.md ├── easybmp ├── EasyBMP_VariousBMPutilities.h ├── EasyBMP_DataStructures.h ├── EasyBMP.h └── EasyBMP_BMP.h └── main.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | unblock 3 | testcase 4 | -------------------------------------------------------------------------------- /test-ok/in1.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/camilleg/unblock/HEAD/test-ok/in1.bmp -------------------------------------------------------------------------------- /test-ok/in1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/camilleg/unblock/HEAD/test-ok/in1.png -------------------------------------------------------------------------------- /test-ok/in2.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/camilleg/unblock/HEAD/test-ok/in2.bmp -------------------------------------------------------------------------------- /test-ok/in2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/camilleg/unblock/HEAD/test-ok/in2.png -------------------------------------------------------------------------------- /test-ok/out1.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/camilleg/unblock/HEAD/test-ok/out1.bmp -------------------------------------------------------------------------------- /test-ok/out1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/camilleg/unblock/HEAD/test-ok/out1.png -------------------------------------------------------------------------------- /test-ok/out2.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/camilleg/unblock/HEAD/test-ok/out2.bmp -------------------------------------------------------------------------------- /test-ok/out2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/camilleg/unblock/HEAD/test-ok/out2.png -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SRCS_CPP = main.cpp easybmp/EasyBMP.cpp 2 | SRCS_C = $(wildcard costella/*.c) 3 | 4 | OBJS := ${SRCS_CPP:.cpp=.o} ${SRCS_C:.c=.o} 5 | EXE = unblock 6 | 7 | CFLAGS = -O3 -Wall -W 8 | CXXFLAGS = $(CFLAGS) -std=c++20 -Ieasybmp -Icostella 9 | 10 | $(EXE): $(OBJS) Makefile 11 | g++ -o $@ $(OBJS) -lpng -lm 12 | 13 | clean: 14 | rm -f $(EXE) $(OBJS) testcase/out* 15 | 16 | test: $(EXE) 17 | ./testcases.sh 18 | 19 | .PHONY: all clean test 20 | -------------------------------------------------------------------------------- /test-ok/get-files.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This only shows where the standard images came from. 4 | # It need not be rerun. 5 | 6 | # Get these standard images, if we haven't already. 7 | wget -q -r -nc "http://sipi.usc.edu/database/download.php?vol=misc&img=4.1.08" -O in1.tiff # 256x256 jellybeans 8 | wget -q -r -nc "http://sipi.usc.edu/database/download.php?vol=misc&img=4.2.03" -O in2.tiff # 512x512 mandrill 9 | 10 | for i in 1 2; do 11 | # Make the standard image blocky. 12 | # cjpeg would be more lightweight than imagemagick's convert, 13 | # but it can't read tiff. 14 | convert -quality 10 in$i.tiff in$i.jpg 15 | # Make two inputs for a test case. 16 | convert in$i.jpg BMP3:in$i.bmp 17 | convert in$i.jpg in$i.png 18 | done 19 | -------------------------------------------------------------------------------- /testcases.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | mkdir -p testcase 4 | cd testcase 5 | 6 | die() { echo "$1"; exit 1; } 7 | 8 | # unblock's output as of 2021 Jan 31 is the test case's expected output. 9 | # That reassures us that the 8x8 case hasn't been broken. 10 | 11 | run() { 12 | cmd="../unblock $1 $2" 13 | eval "$cmd" || die "Command failed: $cmd" 14 | [ ! -f "$2" ] && die "No output from: $cmd" 15 | [ ! -s "$2" ] && die "Empty output from: $cmd" 16 | cmp -s ../test-ok/"$2" "$2" || die "Output $2 differs from expected ../test-ok/$2" 17 | } 18 | 19 | for i in 1 2; do 20 | run "../test-ok/in$i.bmp" "out$i.bmp" 21 | run "../test-ok/in$i.png" "out$i.png" 22 | done 23 | 24 | # upscale x2 will be a separate test case, for 16x16. 25 | # That lets us check if 16x16 outperforms 8x8, as it should. 26 | 27 | exit 0 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2025 Camille Goudeseune. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | Neither the name of the nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 9 | 10 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 11 | -------------------------------------------------------------------------------- /costella/costella_image_default.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2007 John P. Costella. 2 | ** 3 | ** Permission is hereby granted, free of charge, to any person obtaining a 4 | ** copy of this software and associated documentation files (the "Software") 5 | ** to deal in the Software without restriction, including without limitation 6 | ** the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | ** and/or sell copies of the Software, and to permit persons to whom the 8 | ** Software is furnished to do so, subject to the following conditions: 9 | ** 10 | ** The above copyright notice and this permission notice shall be included 11 | ** in all copies or substantial portions of the Software. 12 | ** 13 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 15 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. 16 | ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER 17 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING 18 | ** FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | ** DEALINGS IN THE SOFTWARE. 20 | ** 21 | ** 22 | ** costella_image_default.h: 23 | ** 24 | ** Header file that includes the default image header file if none of 25 | ** the relevant preprocessor flags are set. 26 | ** 27 | ** This version: August 3, 2007. 28 | ** 29 | ** Written in ANSI C. 30 | */ 31 | 32 | 33 | 34 | /* Include file only once. 35 | */ 36 | 37 | #ifndef _COSTELLA_IMAGE_DEFAULT_H_ 38 | #define _COSTELLA_IMAGE_DEFAULT_H_ 39 | 40 | 41 | 42 | /* Include file.. 43 | */ 44 | 45 | #include "costella_image_separate_arrays.h" 46 | 47 | 48 | 49 | /* File is now included. 50 | */ 51 | 52 | #endif 53 | 54 | 55 | 56 | /* Copyright (c) 2007 John P. Costella. 57 | ** 58 | ** End of file. 59 | */ 60 | -------------------------------------------------------------------------------- /costella/costella_debug_default.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2007 John P. Costella. 2 | ** 3 | ** Permission is hereby granted, free of charge, to any person obtaining a 4 | ** copy of this software and associated documentation files (the "Software") 5 | ** to deal in the Software without restriction, including without limitation 6 | ** the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | ** and/or sell copies of the Software, and to permit persons to whom the 8 | ** Software is furnished to do so, subject to the following conditions: 9 | ** 10 | ** The above copyright notice and this permission notice shall be included 11 | ** in all copies or substantial portions of the Software. 12 | ** 13 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 15 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. 16 | ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER 17 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING 18 | ** FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | ** DEALINGS IN THE SOFTWARE. 20 | ** 21 | ** 22 | ** costella_debug_default.h: 23 | ** 24 | ** Header file setting the COSTELLA_DEBUG flag if the symbol _DEBUG is 25 | ** defined. 26 | ** 27 | ** This version: March 28, 2007. 28 | ** 29 | ** Written in ANSI C. 30 | */ 31 | 32 | 33 | 34 | /* Include file only once. 35 | */ 36 | 37 | #ifndef _COSTELLA_DEBUG_DEFAULT_H_ 38 | #define _COSTELLA_DEBUG_DEFAULT_H_ 39 | 40 | 41 | 42 | /* Set flag. 43 | */ 44 | 45 | #ifdef _DEBUG 46 | 47 | #define COSTELLA_DEBUG 1 48 | 49 | #else 50 | 51 | #undef COSTELLA_DEBUG 52 | 53 | #endif 54 | 55 | 56 | 57 | /* File is now included. 58 | */ 59 | 60 | #endif 61 | 62 | 63 | 64 | /* Copyright (c) 2007 John P. Costella. 65 | ** 66 | ** End of file. 67 | */ 68 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### UnBlock 2 | 3 | Remove 8x8-pixel "blocky" artifacts from a heavily compressed JPEG image. 4 | 5 | ### How to build on Ubuntu 18 through 22 6 | 7 | `sudo apt install g++ libpng-dev make` 8 | 9 | `make` 10 | 11 | This also works on Windows 10 or 11, within [WSL](https://docs.microsoft.com/en-us/windows/wsl/install-win10). 12 | 13 | ### How to run 14 | 15 | `./unblock in.bmp out.bmp` 16 | 17 | `./unblock in.png out.png` 18 | 19 | ### How to test 20 | 21 | `make test` 22 | 23 | ### Software used 24 | 25 | This is a wrapper around an algorithm by John Costella. 26 | His [webpage](http://johncostella.com/unblock/) 27 | includes before-and-after pictures showing the algorithm's effectiveness. 28 | 29 | Instead of porting John's C# source code to C/C++, 30 | I built on Alexander Balakhnin's C port, 31 | in the context of a [plugin](http://avisynth.org.ru/unblock/unblock.html) 32 | for [AviSynth](http://sourceforge.net/projects/avisynth2/), 33 | based on John's own 2007 C port of "the Costella libraries." 34 | 35 | Files in .bmp format are read and written by [EasyBMP](http://easybmp.sourceforge.net/), 36 | files in .png format by [libpng](http://www.libpng.org/pub/png/libpng.html). 37 | Why not .jpg for a JPEG utility? 38 | Because my source images are still frames from mjpeg-format video. 39 | Extracting frames in a lossless format avoids the further degradation that happens with 40 | `ffmpeg -i in.avi -vcodec jpg ...`. 41 | 42 | The journal article 43 | [Stitched Panoramas from Low-Cost Airborne Video Cameras](http://uasjournal.org/volume-two/technical-paper/stitched-panoramas-low-cost-airborne-video-cameras) 44 | demonstrates an application of this software. The article is summarized in the 45 | [MIT Technology Review](https://www.technologyreview.com/2013/12/04/175236/the-future-of-photography-cameras-with-wings-or-rotors/). 46 | 47 | ### Bugs 48 | 49 | An image whose width is not a multiple of 16 pixels may misbehave. 50 | -------------------------------------------------------------------------------- /costella/costella_types_ansi.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2007 John P. Costella. 2 | ** 3 | ** Permission is hereby granted, free of charge, to any person obtaining a 4 | ** copy of this software and associated documentation files (the "Software") 5 | ** to deal in the Software without restriction, including without limitation 6 | ** the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | ** and/or sell copies of the Software, and to permit persons to whom the 8 | ** Software is furnished to do so, subject to the following conditions: 9 | ** 10 | ** The above copyright notice and this permission notice shall be included 11 | ** in all copies or substantial portions of the Software. 12 | ** 13 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 15 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. 16 | ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER 17 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING 18 | ** FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | ** DEALINGS IN THE SOFTWARE. 20 | ** 21 | ** 22 | ** costella_types_ansi.h: 23 | ** 24 | ** Header file defining standard types for the Costella libraries assuming 25 | ** nothing more than ANSI C. 26 | ** 27 | ** This version: July 9, 2007. 28 | ** 29 | ** Written in ANSI C. 30 | */ 31 | 32 | 33 | 34 | /* Include file only once. 35 | */ 36 | 37 | #ifndef _COSTELLA_TYPES_ANSI_H_ 38 | #define _COSTELLA_TYPES_ANSI_H_ 39 | 40 | 41 | 42 | /* Typedefs. 43 | */ 44 | 45 | typedef unsigned char COSTELLA_UB; 46 | typedef signed char COSTELLA_SB; 47 | 48 | typedef unsigned short COSTELLA_UW; 49 | typedef signed short COSTELLA_SW; 50 | 51 | typedef unsigned long COSTELLA_UD; 52 | typedef signed long COSTELLA_SD; 53 | 54 | typedef float COSTELLA_SF; 55 | typedef double COSTELLA_DF; 56 | 57 | 58 | 59 | /* File is now included. 60 | */ 61 | 62 | #endif 63 | 64 | 65 | 66 | /* Copyright (c) 2007 John P. Costella. 67 | ** 68 | ** End of file. 69 | */ 70 | -------------------------------------------------------------------------------- /easybmp/EasyBMP_VariousBMPutilities.h: -------------------------------------------------------------------------------- 1 | /************************************************* 2 | * * 3 | * EasyBMP Cross-Platform Windows Bitmap Library * 4 | * * 5 | * Author: Paul Macklin * 6 | * email: macklin01@users.sourceforge.net * 7 | * support: http://easybmp.sourceforge.net * 8 | * * 9 | * file: EasyBMP_VariousBMPutilities.h * 10 | * date added: 05-02-2005 * 11 | * date modified: 12-01-2006 * 12 | * version: 1.06 * 13 | * * 14 | * License: BSD (revised/modified) * 15 | * Copyright: 2005-6 by the EasyBMP Project * 16 | * * 17 | * description: Various utilities. * 18 | * * 19 | *************************************************/ 20 | 21 | #ifndef _EasyBMP_VariousBMPutilities_h_ 22 | #define _EasyBMP_VariousBMPutilities_h_ 23 | 24 | BMFH GetBMFH( const char* szFileNameIn ); 25 | BMIH GetBMIH( const char* szFileNameIn ); 26 | void DisplayBitmapInfo( const char* szFileNameIn ); 27 | int GetBitmapColorDepth( const char* szFileNameIn ); 28 | void PixelToPixelCopy( BMP& From, int FromX, int FromY, 29 | BMP& To, int ToX, int ToY); 30 | void PixelToPixelCopyTransparent( BMP& From, int FromX, int FromY, 31 | BMP& To, int ToX, int ToY, 32 | RGBApixel& Transparent ); 33 | void RangedPixelToPixelCopy( BMP& From, int FromL , int FromR, int FromB, int FromT, 34 | BMP& To, int ToX, int ToY ); 35 | void RangedPixelToPixelCopyTransparent( 36 | BMP& From, int FromL , int FromR, int FromB, int FromT, 37 | BMP& To, int ToX, int ToY , 38 | RGBApixel& Transparent ); 39 | bool CreateGrayscaleColorTable( BMP& InputImage ); 40 | 41 | bool Rescale( BMP& InputImage , char mode, int NewDimension ); 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /costella/costella_debug.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2007 John P. Costella. 2 | ** 3 | ** Permission is hereby granted, free of charge, to any person obtaining a 4 | ** copy of this software and associated documentation files (the "Software") 5 | ** to deal in the Software without restriction, including without limitation 6 | ** the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | ** and/or sell copies of the Software, and to permit persons to whom the 8 | ** Software is furnished to do so, subject to the following conditions: 9 | ** 10 | ** The above copyright notice and this permission notice shall be included 11 | ** in all copies or substantial portions of the Software. 12 | ** 13 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 15 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. 16 | ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER 17 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING 18 | ** FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | ** DEALINGS IN THE SOFTWARE. 20 | ** 21 | ** 22 | ** costella_debug.h: 23 | ** 24 | ** Header file that sets the COSTELLA_DEBUG flag when the compiler is in 25 | ** debug mode. Modify the entry below to include a different file. 26 | ** 27 | ** This version: March 28, 2007. 28 | ** 29 | ** Written in ANSI C. 30 | */ 31 | 32 | 33 | 34 | /* Include file only once. 35 | */ 36 | 37 | #ifndef _COSTELLA_DEBUG_H_ 38 | #define _COSTELLA_DEBUG_H_ 39 | 40 | 41 | 42 | /* The default file below sets the COSTELLA_DEBUG flag if the symbol _DEBUG 43 | ** is defined. For a different behavior, comment out the first entry, copy 44 | ** the file costella_debug_default.h, modify it to suit, save it under a new 45 | ** name, and include it here. 46 | */ 47 | 48 | #include "costella_debug_default.h" 49 | /* #include "costella_debug_my_architecture.h" (for example) */ 50 | 51 | 52 | 53 | /* File is now included. 54 | */ 55 | 56 | #endif 57 | 58 | 59 | 60 | /* Copyright (c) 2007 John P. Costella. 61 | ** 62 | ** End of file. 63 | */ 64 | -------------------------------------------------------------------------------- /costella/costella_unblock.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2005-2007 John P. Costella. 2 | ** 3 | ** Permission is hereby granted, free of charge, to any person obtaining a 4 | ** copy of this software and associated documentation files (the "Software") 5 | ** to deal in the Software without restriction, including without limitation 6 | ** the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | ** and/or sell copies of the Software, and to permit persons to whom the 8 | ** Software is furnished to do so, subject to the following conditions: 9 | ** 10 | ** The above copyright notice and this permission notice shall be included 11 | ** in all copies or substantial portions of the Software. 12 | ** 13 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 15 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. 16 | ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER 17 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING 18 | ** FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | ** DEALINGS IN THE SOFTWARE. 20 | ** 21 | ** 22 | ** costella_unblock.h: 23 | ** 24 | ** Header file for costella_unblock.c 25 | ** 26 | ** This version: August 2, 2007. 27 | ** 28 | ** Written in ANSI C. 29 | */ 30 | 31 | 32 | 33 | /* Include file only once. 34 | */ 35 | 36 | #ifndef _COSTELLA_UNBLOCK_H_ 37 | #define _COSTELLA_UNBLOCK_H_ 38 | 39 | 40 | 41 | /* Include file. 42 | */ 43 | 44 | #include "costella_image_chrominance.h" 45 | #include "costella_image_convert.h" 46 | 47 | 48 | 49 | /* Public interface. 50 | */ 51 | 52 | int costella_unblock_initialize( FILE* pfileError ); 53 | int costella_unblock_finalize( FILE* pfileError ); 54 | 55 | int costella_unblock( COSTELLA_IMAGE* piIn, COSTELLA_IMAGE* piOut, int 56 | bPhotographic, int bCartoon, int (*pfProgress)( void* pvPassback ), void* 57 | pvPassback, FILE* pfileError ); 58 | 59 | 60 | 61 | /* Function prototypes. 62 | */ 63 | 64 | COSTELLA_FUNCTION( CostellaUnblockInitialize, ( void ) ) 65 | COSTELLA_FUNCTION( CostellaUnblockFinalize, ( void ) ) 66 | 67 | COSTELLA_FUNCTION( CostellaUnblock, ( COSTELLA_IMAGE* piIn, COSTELLA_IMAGE* 68 | piOut, COSTELLA_B bPhotographic, COSTELLA_B bCartoon, 69 | COSTELLA_CALLBACK_FUNCTION pfProgress, COSTELLA_O* poPassback ) ) 70 | 71 | 72 | 73 | /* File is now included. 74 | */ 75 | 76 | #endif 77 | 78 | 79 | 80 | /* Copyright (c) 2005-2007 John P. Costella. 81 | ** 82 | ** End of file. 83 | */ 84 | 85 | -------------------------------------------------------------------------------- /costella/costella_types.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2007 John P. Costella. 2 | ** 3 | ** Permission is hereby granted, free of charge, to any person obtaining a 4 | ** copy of this software and associated documentation files (the "Software") 5 | ** to deal in the Software without restriction, including without limitation 6 | ** the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | ** and/or sell copies of the Software, and to permit persons to whom the 8 | ** Software is furnished to do so, subject to the following conditions: 9 | ** 10 | ** The above copyright notice and this permission notice shall be included 11 | ** in all copies or substantial portions of the Software. 12 | ** 13 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 15 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. 16 | ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER 17 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING 18 | ** FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | ** DEALINGS IN THE SOFTWARE. 20 | ** 21 | ** 22 | ** costella_types.h: 23 | ** 24 | ** Header file defining standard types for the Costella libraries. 25 | ** Modify the entry below to include a different file. 26 | ** 27 | ** This version: July 9, 2007. 28 | ** 29 | ** Written in ANSI C. 30 | */ 31 | 32 | 33 | 34 | /* Include file only once. 35 | */ 36 | 37 | #ifndef _COSTELLA_TYPES_H_ 38 | #define _COSTELLA_TYPES_H_ 39 | 40 | 41 | 42 | /* For plain vanilla ANSI C, include the first file. To optimize for a 43 | ** specific architecture, comment out the first entry, copy the file 44 | ** costella_types_ansi.h, modify it to suit, save it under a new name, and 45 | ** include it here. 46 | */ 47 | 48 | #include "costella_types_ansi.h" 49 | /* #include "costella_types_my_architecture.h" (for example) */ 50 | 51 | 52 | 53 | /* Definition that provides that COSTELLA_O* is the same as void*. 54 | */ 55 | 56 | #define COSTELLA_O void 57 | 58 | 59 | 60 | /* Types that should not be modified for any architecture. 61 | */ 62 | 63 | typedef int COSTELLA_B; 64 | typedef char COSTELLA_C; 65 | typedef unsigned int COSTELLA_MC; 66 | typedef int COSTELLA_MI; 67 | 68 | 69 | 70 | /* Flag that states whether your architecture right-shifts in the sign bit. 71 | ** Comment out this flag if you use a processor that does not. 72 | */ 73 | 74 | #define COSTELLA_SHIFT_RIGHT_IS_SIGNED 75 | 76 | 77 | 78 | /* File is now included. 79 | */ 80 | 81 | #endif 82 | 83 | 84 | 85 | /* Copyright (c) 2007 John P. Costella. 86 | ** 87 | ** End of file. 88 | */ 89 | -------------------------------------------------------------------------------- /easybmp/EasyBMP_DataStructures.h: -------------------------------------------------------------------------------- 1 | /************************************************* 2 | * * 3 | * EasyBMP Cross-Platform Windows Bitmap Library * 4 | * * 5 | * Author: Paul Macklin * 6 | * email: macklin01@users.sourceforge.net * 7 | * support: http://easybmp.sourceforge.net * 8 | * * 9 | * file: EasyBMP_DataStructures.h * 10 | * date added: 05-02-2005 * 11 | * date modified: 12-01-2006 * 12 | * version: 1.06 * 13 | * * 14 | * License: BSD (revised/modified) * 15 | * Copyright: 2005-6 by the EasyBMP Project * 16 | * * 17 | * description: Defines basic data structures for * 18 | * the BMP class * 19 | * * 20 | *************************************************/ 21 | 22 | #ifndef _EasyBMP_Custom_Math_Functions_ 23 | #define _EasyBMP_Custom_Math_Functions_ 24 | inline double Square( double number ) 25 | { return number*number; } 26 | 27 | inline int IntSquare( int number ) 28 | { return number*number; } 29 | #endif 30 | 31 | int IntPow( int base, int exponent ); 32 | 33 | #ifndef _EasyBMP_Defined_WINGDI 34 | #define _EasyBMP_Defined_WINGDI 35 | typedef unsigned char ebmpBYTE; 36 | typedef unsigned short ebmpWORD; 37 | typedef unsigned int ebmpDWORD; 38 | #endif 39 | 40 | #pragma once 41 | 42 | inline ebmpWORD FlipWORD( ebmpWORD in ) 43 | { return ( (in >> 8) | (in << 8) ); } 44 | 45 | inline ebmpDWORD FlipDWORD( ebmpDWORD in ) 46 | { 47 | return ( ((in&0xFF000000)>>24) | ((in&0x000000FF)<<24) | 48 | ((in&0x00FF0000)>>8 ) | ((in&0x0000FF00)<<8 ) ); 49 | } 50 | 51 | typedef struct RGBApixel { 52 | ebmpBYTE Blue; 53 | ebmpBYTE Green; 54 | ebmpBYTE Red; 55 | ebmpBYTE Alpha; 56 | } RGBApixel; 57 | 58 | struct BMFH{ 59 | ebmpWORD bfType; 60 | ebmpDWORD bfSize; 61 | ebmpWORD bfReserved1; 62 | ebmpWORD bfReserved2; 63 | ebmpDWORD bfOffBits; 64 | 65 | BMFH(); 66 | void display(); 67 | void SwitchEndianess(); 68 | }; 69 | 70 | struct BMIH{ 71 | ebmpDWORD biSize; 72 | ebmpDWORD biWidth; 73 | ebmpDWORD biHeight; 74 | ebmpWORD biPlanes; 75 | ebmpWORD biBitCount; 76 | ebmpDWORD biCompression; 77 | ebmpDWORD biSizeImage; 78 | ebmpDWORD biXPelsPerMeter; 79 | ebmpDWORD biYPelsPerMeter; 80 | ebmpDWORD biClrUsed; 81 | ebmpDWORD biClrImportant; 82 | 83 | BMIH(); 84 | void display(); 85 | void SwitchEndianess(); 86 | }; 87 | 88 | // vim: ts=4 sw=4 89 | -------------------------------------------------------------------------------- /easybmp/EasyBMP.h: -------------------------------------------------------------------------------- 1 | /************************************************* 2 | * * 3 | * EasyBMP Cross-Platform Windows Bitmap Library * 4 | * * 5 | * Author: Paul Macklin * 6 | * email: macklin01@users.sourceforge.net * 7 | * support: http://easybmp.sourceforge.net * 8 | * * 9 | * file: EasyBMP.h * 10 | * date added: 01-31-2005 * 11 | * date modified: 12-01-2006 * 12 | * version: 1.06 * 13 | * * 14 | * License: BSD (revised/modified) * 15 | * Copyright: 2005-6 by the EasyBMP Project * 16 | * * 17 | * description: Main include file * 18 | * * 19 | *************************************************/ 20 | 21 | #ifdef _MSC_VER 22 | // MS Visual Studio gives warnings when using 23 | // fopen. But fopen_s is not going to work well 24 | // with most compilers, and fopen_s uses different 25 | // syntax than fopen. (i.e., a macro won't work) 26 | // So, we'lll use this: 27 | #define _CRT_SECURE_NO_DEPRECATE 28 | #endif 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #ifndef EasyBMP 36 | #define EasyBMP 37 | 38 | #ifdef __BCPLUSPLUS__ 39 | // The Borland compiler must use this because something 40 | // is wrong with their cstdio file. 41 | #include 42 | #else 43 | #include 44 | #endif 45 | 46 | #ifdef __GNUC__ 47 | // If g++ specific code is ever required, this is 48 | // where it goes. 49 | #endif 50 | 51 | #ifdef __INTEL_COMPILER 52 | // If Intel specific code is ever required, this is 53 | // where it goes. 54 | #endif 55 | 56 | #ifndef _DefaultXPelsPerMeter_ 57 | #define _DefaultXPelsPerMeter_ 58 | #define DefaultXPelsPerMeter 3780 59 | // set to a default of 96 dpi 60 | #endif 61 | 62 | #ifndef _DefaultYPelsPerMeter_ 63 | #define _DefaultYPelsPerMeter_ 64 | #define DefaultYPelsPerMeter 3780 65 | // set to a default of 96 dpi 66 | #endif 67 | 68 | #include "EasyBMP_DataStructures.h" 69 | #include "EasyBMP_BMP.h" 70 | #include "EasyBMP_VariousBMPutilities.h" 71 | 72 | #ifndef _EasyBMP_Version_ 73 | #define _EasyBMP_Version_ 1.06 74 | #define _EasyBMP_Version_Integer_ 106 75 | #define _EasyBMP_Version_String_ "1.06" 76 | #endif 77 | 78 | #ifndef _EasyBMPwarnings_ 79 | #define _EasyBMPwarnings_ 80 | #endif 81 | 82 | void SetEasyBMPwarningsOff( void ); 83 | void SetEasyBMPwarningsOn( void ); 84 | bool GetEasyBMPwarningState( void ); 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /costella/costella_body.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 1989-2007 John P. Costella. 2 | ** 3 | ** Permission is hereby granted, free of charge, to any person obtaining a 4 | ** copy of this software and associated documentation files (the "Software") 5 | ** to deal in the Software without restriction, including without limitation 6 | ** the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | ** and/or sell copies of the Software, and to permit persons to whom the 8 | ** Software is furnished to do so, subject to the following conditions: 9 | ** 10 | ** The above copyright notice and this permission notice shall be included 11 | ** in all copies or substantial portions of the Software. 12 | ** 13 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 15 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. 16 | ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER 17 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING 18 | ** FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | ** DEALINGS IN THE SOFTWARE. 20 | ** 21 | ** 22 | ** costella_body.h: 23 | ** 24 | ** Start function body. 25 | ** 26 | ** This version: July 9, 2007. 27 | ** 28 | ** Written in ANSI C. 29 | */ 30 | 31 | 32 | 33 | /* Include file only once. 34 | */ 35 | 36 | #ifndef _COSTELLA_BODY_H_ 37 | #define _COSTELLA_BODY_H_ 38 | 39 | 40 | 41 | /* COSTELLA_FUNCTION: 42 | ** 43 | ** Define a function. 44 | */ 45 | 46 | #undef COSTELLA_FUNCTION 47 | 48 | #define COSTELLA_FUNCTION( lfFunctionName, larglist ) \ 49 | COSTELLA_ERROR_NODE* lfFunctionName larglist \ 50 | COSTELLA_FUNCTION_COMMON( lfFunctionName ) 51 | 52 | 53 | 54 | /* COSTELLA_ANSI_FUNCTION: 55 | ** 56 | ** Declare an "ANSI" function, i.e. one that does not follow the function 57 | ** paradigm of the Costella libraries, but which must call such functions 58 | ** and be able to use the error-handling functionality built into them. 59 | */ 60 | 61 | #undef COSTELLA_ANSI_FUNCTION 62 | 63 | #define COSTELLA_ANSI_FUNCTION( lfFunctionName, returntype, larglist ) \ 64 | returntype lfFunctionName larglist \ 65 | COSTELLA_FUNCTION_COMMON( lfFunctionName ) 66 | 67 | 68 | 69 | /* COSTELLA_FUNCTION_COMMON: 70 | ** 71 | ** Common initialization commands for the preceding macros. 72 | */ 73 | 74 | #define COSTELLA_FUNCTION_COMMON( lfFunctionName ) \ 75 | { \ 76 | static COSTELLA_C i_l_acCostellaFunctionName[] = #lfFunctionName; \ 77 | static COSTELLA_ERROR_NODE i_l_enCostella; \ 78 | COSTELLA_B i_l_bCostellaError = COSTELLA_FALSE; \ 79 | \ 80 | i_l_enCostella.acFunctionName = i_l_acCostellaFunctionName; \ 81 | i_l_enCostella.acError = 0; \ 82 | i_l_enCostella.acCleanupError = 0; \ 83 | i_l_enCostella.penNext = 0; \ 84 | i_l_enCostella.penCleanupNext = 0; \ 85 | { 86 | 87 | 88 | 89 | /* File is now included. 90 | */ 91 | 92 | #endif 93 | 94 | 95 | 96 | /* Copyright (c) 1989-2007 John P. Costella. 97 | ** 98 | ** End of file. 99 | */ 100 | -------------------------------------------------------------------------------- /costella/costella_wrap.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2006-2007 John P. Costella. 2 | ** 3 | ** Permission is hereby granted, free of charge, to any person obtaining a 4 | ** copy of this software and associated documentation files (the "Software") 5 | ** to deal in the Software without restriction, including without limitation 6 | ** the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | ** and/or sell copies of the Software, and to permit persons to whom the 8 | ** Software is furnished to do so, subject to the following conditions: 9 | ** 10 | ** The above copyright notice and this permission notice shall be included 11 | ** in all copies or substantial portions of the Software. 12 | ** 13 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 15 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. 16 | ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER 17 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING 18 | ** FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | ** DEALINGS IN THE SOFTWARE. 20 | ** 21 | ** 22 | ** costella_wrap.h: 23 | ** 24 | ** Header file for costella_wrap.c. 25 | ** 26 | ** This version: July 11, 2007. 27 | ** 28 | ** Written in ANSI C. 29 | */ 30 | 31 | 32 | 33 | /* Include file only once. 34 | */ 35 | 36 | #ifndef _COSTELLA_WRAP_H_ 37 | #define _COSTELLA_WRAP_H_ 38 | 39 | 40 | 41 | /* Include files. 42 | */ 43 | 44 | #include "costella_base.h" 45 | 46 | 47 | 48 | /* Structures. 49 | */ 50 | 51 | typedef struct 52 | { 53 | void (*pf)( void ); 54 | } 55 | COSTELLA_WRAP_FUNCTION_POINTER; 56 | 57 | 58 | typedef struct 59 | { 60 | int (*pfCallback)( void* pvPassback, void* pv ); 61 | void* pvPassback; 62 | } 63 | COSTELLA_WRAP_CALLBACK; 64 | 65 | 66 | typedef struct 67 | { 68 | int (*pfProgress)( void* pvPassback ); 69 | void* pvPassback; 70 | } 71 | COSTELLA_WRAP_PROGRESS; 72 | 73 | 74 | 75 | /* Function prototypes. 76 | */ 77 | 78 | COSTELLA_FUNCTION( CostellaWrapInitialize, ( void ) ) 79 | COSTELLA_FUNCTION( CostellaWrapFinalize, ( void ) ) 80 | 81 | COSTELLA_FUNCTION( CostellaWrapCallbackNew, ( COSTELLA_WRAP_CALLBACK** ppwc, 82 | int (*pfCallback)( void* pvPassback, void* pv ), void* pvPassback ) ) 83 | COSTELLA_FUNCTION( CostellaWrapCallbackDelete, ( COSTELLA_WRAP_CALLBACK** 84 | ppwc ) ) 85 | COSTELLA_FUNCTION( CostellaWrapCallback, ( COSTELLA_O* poPassback, 86 | COSTELLA_O* po ) ) 87 | 88 | COSTELLA_FUNCTION( CostellaWrapProgress, ( COSTELLA_O* poPassback ) ) 89 | 90 | COSTELLA_FUNCTION( CostellaWrapNewCopy, ( COSTELLA_O** 91 | ppoNewCopy, COSTELLA_O* poExisting, COSTELLA_O* poPassback ) ) 92 | COSTELLA_FUNCTION( CostellaWrapDelete, ( COSTELLA_O** ppo, COSTELLA_O* 93 | poPassback ) ) 94 | COSTELLA_FUNCTION( CostellaWrapCompare, ( COSTELLA_SB* psbCompare, 95 | COSTELLA_O* po1, COSTELLA_O* po2, COSTELLA_O* poPassback ) ) 96 | 97 | 98 | 99 | /* File is now included. 100 | */ 101 | 102 | #endif 103 | 104 | 105 | 106 | /* Copyright (c) 2006-2007 John P. Costella. 107 | ** 108 | ** End of file. 109 | */ 110 | -------------------------------------------------------------------------------- /easybmp/EasyBMP_BMP.h: -------------------------------------------------------------------------------- 1 | /************************************************* 2 | * * 3 | * EasyBMP Cross-Platform Windows Bitmap Library * 4 | * * 5 | * Author: Paul Macklin * 6 | * email: macklin01@users.sourceforge.net * 7 | * support: http://easybmp.sourceforge.net * 8 | * * 9 | * file: EasyBMP_VariousBMPutilities.h * 10 | * date added: 05-02-2005 * 11 | * date modified: 12-01-2006 * 12 | * version: 1.06 * 13 | * * 14 | * License: BSD (revised/modified) * 15 | * Copyright: 2005-6 by the EasyBMP Project * 16 | * * 17 | * description: Defines BMP class * 18 | * * 19 | *************************************************/ 20 | 21 | #ifndef _EasyBMP_BMP_h_ 22 | #define _EasyBMP_BMP_h_ 23 | 24 | bool SafeFread( char* buffer, int size, int number, FILE* fp ); 25 | bool EasyBMPcheckDataSize( void ); 26 | 27 | class BMP 28 | {private: 29 | 30 | int BitDepth; 31 | int Width; 32 | int Height; 33 | RGBApixel** Pixels; 34 | RGBApixel* Colors; 35 | int XPelsPerMeter; 36 | int YPelsPerMeter; 37 | 38 | ebmpBYTE* MetaData1; 39 | int SizeOfMetaData1; 40 | ebmpBYTE* MetaData2; 41 | int SizeOfMetaData2; 42 | 43 | bool Read32bitRow( ebmpBYTE* Buffer, int BufferSize, int Row ); 44 | bool Read24bitRow( ebmpBYTE* Buffer, int BufferSize, int Row ); 45 | bool Read8bitRow( ebmpBYTE* Buffer, int BufferSize, int Row ); 46 | bool Read4bitRow( ebmpBYTE* Buffer, int BufferSize, int Row ); 47 | bool Read1bitRow( ebmpBYTE* Buffer, int BufferSize, int Row ); 48 | 49 | bool Write32bitRow( ebmpBYTE* Buffer, int BufferSize, int Row ); 50 | bool Write24bitRow( ebmpBYTE* Buffer, int BufferSize, int Row ); 51 | bool Write8bitRow( ebmpBYTE* Buffer, int BufferSize, int Row ); 52 | bool Write4bitRow( ebmpBYTE* Buffer, int BufferSize, int Row ); 53 | bool Write1bitRow( ebmpBYTE* Buffer, int BufferSize, int Row ); 54 | 55 | ebmpBYTE FindClosestColor( RGBApixel& input ); 56 | 57 | // Disable assigment operator, because of pointer members. 58 | BMP& operator=(const BMP&) = delete; 59 | 60 | public: 61 | 62 | int TellBitDepth( void ); 63 | int TellWidth( void ); 64 | int TellHeight( void ); 65 | int TellNumberOfColors( void ); 66 | void SetDPI( int HorizontalDPI, int VerticalDPI ); 67 | int TellVerticalDPI( void ); 68 | int TellHorizontalDPI( void ); 69 | 70 | BMP(); 71 | BMP( BMP& Input ); 72 | ~BMP(); 73 | RGBApixel* operator()(int i,int j); 74 | 75 | RGBApixel GetPixel( int i, int j ) const; 76 | bool SetPixel( int i, int j, RGBApixel NewPixel ); 77 | 78 | bool CreateStandardColorTable( void ); 79 | 80 | bool SetSize( int NewWidth, int NewHeight ); 81 | bool SetBitDepth( int NewDepth ); 82 | bool WriteToFile( const char* FileName ); 83 | bool ReadFromFile( const char* FileName ); 84 | 85 | RGBApixel GetColor( int ColorNumber ); 86 | bool SetColor( int ColorNumber, RGBApixel NewColor ); 87 | }; 88 | 89 | #endif 90 | -------------------------------------------------------------------------------- /costella/costella_image_chrominance.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2005-2007 John P. Costella. 2 | ** 3 | ** Permission is hereby granted, free of charge, to any person obtaining a 4 | ** copy of this software and associated documentation files (the "Software") 5 | ** to deal in the Software without restriction, including without limitation 6 | ** the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | ** and/or sell copies of the Software, and to permit persons to whom the 8 | ** Software is furnished to do so, subject to the following conditions: 9 | ** 10 | ** The above copyright notice and this permission notice shall be included 11 | ** in all copies or substantial portions of the Software. 12 | ** 13 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 15 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. 16 | ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER 17 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING 18 | ** FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | ** DEALINGS IN THE SOFTWARE. 20 | ** 21 | ** 22 | ** costella_image_chrominance.h: 23 | ** 24 | ** Header file for costella_image_chrominance.c. 25 | ** 26 | ** This version: September 17, 2007. 27 | ** 28 | ** Written in ANSI C. 29 | */ 30 | 31 | 32 | 33 | /* Include file only once. 34 | */ 35 | 36 | #ifndef _COSTELLA_IMAGE_CHROMINANCE_H_ 37 | #define _COSTELLA_IMAGE_CHROMINANCE_H_ 38 | 39 | 40 | 41 | /* Include files. 42 | */ 43 | 44 | #include "costella_image.h" 45 | #include "costella_wrap.h" 46 | 47 | 48 | 49 | /* Public interface. 50 | */ 51 | 52 | int costella_image_chrominance_initialize( FILE* pfileError ); 53 | int costella_image_chrominance_finalize( FILE* pfileError ); 54 | 55 | int costella_image_chrominance_average_downsample_replicate( COSTELLA_IMAGE* 56 | piIn, COSTELLA_IMAGE* piOut, int (*pfProgress)( void* pvPassback ), void* 57 | pvPassback, FILE* pfileError ); 58 | int costella_image_chrominance_magic_upsample( COSTELLA_IMAGE* piIn, 59 | COSTELLA_IMAGE* piOut, int (*pfProgress)( void* pvPassback ), void* 60 | pvPassback, FILE* pfileError ); 61 | int costella_image_chrominance_replicate_eq( COSTELLA_IMAGE* pi, int 62 | (*pfProgress)( void* pvPassback ), void* pvPassback, FILE* pfileError ); 63 | 64 | 65 | 66 | /* Function prototypes. 67 | */ 68 | 69 | COSTELLA_FUNCTION( CostellaImageChrominanceInitialize, ( void ) ) 70 | COSTELLA_FUNCTION( CostellaImageChrominanceFinalize, ( void ) ) 71 | 72 | COSTELLA_FUNCTION( CostellaImageChrominanceAverageDownsampleReplicate, ( 73 | COSTELLA_IMAGE* piIn, COSTELLA_IMAGE* piOut, COSTELLA_CALLBACK_FUNCTION 74 | pfProgress, COSTELLA_O* poPassback ) ) 75 | COSTELLA_FUNCTION( CostellaImageChrominanceMagicUpsample, ( COSTELLA_IMAGE* 76 | piIn, COSTELLA_IMAGE* piOut, COSTELLA_CALLBACK_FUNCTION pfProgress, 77 | COSTELLA_O* poPassback ) ) 78 | COSTELLA_FUNCTION( CostellaImageChrominanceReplicateEq, ( COSTELLA_IMAGE* 79 | pi, COSTELLA_CALLBACK_FUNCTION pfProgress, COSTELLA_O* poPassback ) ) 80 | 81 | 82 | 83 | /* File is now included. 84 | */ 85 | 86 | #endif 87 | 88 | 89 | 90 | /* Copyright (c) 2005-2007 John P. Costella. 91 | ** 92 | ** End of file. 93 | */ 94 | -------------------------------------------------------------------------------- /costella/costella_image.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2005-2007 John P. Costella. 2 | ** 3 | ** Permission is hereby granted, free of charge, to any person obtaining a 4 | ** copy of this software and associated documentation files (the "Software") 5 | ** to deal in the Software without restriction, including without limitation 6 | ** the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | ** and/or sell copies of the Software, and to permit persons to whom the 8 | ** Software is furnished to do so, subject to the following conditions: 9 | ** 10 | ** The above copyright notice and this permission notice shall be included 11 | ** in all copies or substantial portions of the Software. 12 | ** 13 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 15 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. 16 | ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER 17 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING 18 | ** FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | ** DEALINGS IN THE SOFTWARE. 20 | ** 21 | ** 22 | ** costella_image.h: 23 | ** 24 | ** Header file for costella_image.c. 25 | ** 26 | ** This version: November 12, 2007. 27 | ** 28 | ** Written in ANSI C. 29 | */ 30 | 31 | 32 | 33 | /* Include file only once. 34 | */ 35 | 36 | #ifndef _COSTELLA_IMAGE_H_ 37 | #define _COSTELLA_IMAGE_H_ 38 | 39 | 40 | 41 | /* Include files. 42 | */ 43 | 44 | #include "costella_base.h" 45 | 46 | 47 | 48 | /* Include header file that sets up pixel storage structures and access 49 | ** routines for standard (8 bits per channel) images. 50 | */ 51 | 52 | #if defined( COSTELLA_IMAGE_SEPARATE_ARRAYS ) 53 | 54 | #include "costella_image_separate_arrays.h" 55 | 56 | #elif defined( COSTELLA_IMAGE_RGB_TRIPLE ) 57 | 58 | #include "costella_image_rgb_triple.h" 59 | 60 | #elif defined( COSTELLA_IMAGE_WIN32_DIB ) 61 | 62 | #include "costella_image_win32_dib.h" 63 | 64 | #else 65 | 66 | #include "costella_image_default.h" 67 | 68 | #endif 69 | 70 | 71 | 72 | /* Structure. 73 | */ 74 | 75 | typedef struct 76 | { 77 | COSTELLA_B bAlpha, bColor, bRgb, bDownsampledChrominance, 78 | bNonreplicatedDownsampledChrominance; 79 | COSTELLA_UD udWidth, udHeight; 80 | COSTELLA_SD sdRowStride, sdAlphaRowStride; 81 | COSTELLA_IMAGE_ALPHA ia; 82 | COSTELLA_IMAGE_GRAY ig; 83 | COSTELLA_IMAGE_COLOR ic; 84 | } 85 | COSTELLA_IMAGE; 86 | 87 | 88 | 89 | /* Public interface. 90 | */ 91 | 92 | int costella_image_initialize( FILE* pfileError ); 93 | int costella_image_finalize( FILE* pfileError ); 94 | 95 | 96 | 97 | /* Function prototypes. 98 | */ 99 | 100 | COSTELLA_FUNCTION( CostellaImageInitialize, ( void ) ) 101 | COSTELLA_FUNCTION( CostellaImageFinalize, ( void ) ) 102 | 103 | 104 | 105 | /* COSTELLA_IMAGE_LIMIT_RANGE: 106 | ** 107 | ** Limit the range of a signed integer to [0,255]. 108 | ** 109 | ** sx: Signed integer to be limited. 110 | */ 111 | 112 | #define COSTELLA_IMAGE_LIMIT_RANGE( sx ) \ 113 | ( (sx) < 0 ? 0 : ( (sx) > 255 ? 255 : (sx) ) ) 114 | 115 | 116 | 117 | /* Declaration of global variables defined in costella_eimage.c. 118 | */ 119 | 120 | #ifndef _COSTELLA_IMAGE_C_ 121 | 122 | extern COSTELLA_IMAGE giCostellaImageNull; 123 | extern COSTELLA_IMAGE_GRAY_PIXEL gigpCostellaImageNull; 124 | extern COSTELLA_IMAGE_ALPHA_PIXEL giapCostellaImageNull; 125 | extern COSTELLA_IMAGE_COLOR_PIXEL gicpCostellaImageNull; 126 | 127 | #endif 128 | 129 | 130 | 131 | /* File is now included. 132 | */ 133 | 134 | #endif 135 | 136 | 137 | 138 | /* Copyright (c) 2005-2007 John P. Costella. 139 | ** 140 | ** End of file. 141 | */ 142 | -------------------------------------------------------------------------------- /costella/costella_image.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2005-2007 John P. Costella. 2 | ** 3 | ** Permission is hereby granted, free of charge, to any person obtaining a 4 | ** copy of this software and associated documentation files (the "Software") 5 | ** to deal in the Software without restriction, including without limitation 6 | ** the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | ** and/or sell copies of the Software, and to permit persons to whom the 8 | ** Software is furnished to do so, subject to the following conditions: 9 | ** 10 | ** The above copyright notice and this permission notice shall be included 11 | ** in all copies or substantial portions of the Software. 12 | ** 13 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 15 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. 16 | ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER 17 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING 18 | ** FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | ** DEALINGS IN THE SOFTWARE. 20 | ** 21 | ** 22 | ** costella_image.c: 23 | ** 24 | ** Generic image manipulation library for the Costella libraries. 25 | ** 26 | ** Library begun: December 30, 2005. 27 | ** This version: November 12, 2007. 28 | ** 29 | ** Written in ANSI C. 30 | */ 31 | 32 | 33 | 34 | /* Include files. 35 | */ 36 | 37 | #include "costella_image.h" 38 | 39 | 40 | 41 | /* Flag preventing the redeclaration of the variables defined below. 42 | */ 43 | 44 | #define _COSTELLA_IMAGE_C_ 45 | 46 | 47 | 48 | /* Externally visible global variables. 49 | */ 50 | 51 | COSTELLA_IMAGE giCostellaImageNull; 52 | COSTELLA_IMAGE_GRAY_PIXEL gigpCostellaImageNull; 53 | COSTELLA_IMAGE_ALPHA_PIXEL giapCostellaImageNull; 54 | COSTELLA_IMAGE_COLOR_PIXEL gicpCostellaImageNull; 55 | 56 | 57 | 58 | /* Internal global variables. 59 | */ 60 | 61 | static COSTELLA_B gbInitialized = COSTELLA_FALSE; 62 | 63 | 64 | 65 | /* Start function bodies. 66 | */ 67 | 68 | #include "costella_body.h" 69 | 70 | 71 | 72 | /* costella_image_initialize: 73 | ** 74 | ** Public interface for initializing this library. 75 | */ 76 | 77 | COSTELLA_ANSI_FUNCTION( costella_image_initialize, int, ( FILE* pfileError ) 78 | ) 79 | { 80 | if( COSTELLA_CALL( CostellaImageInitialize() ) ) 81 | { 82 | COSTELLA_ERROR_FPRINT( pfileError ); 83 | COSTELLA_ANSI_RETURN( 0 ); 84 | } 85 | } 86 | COSTELLA_END_ANSI_FUNCTION( !0 ) 87 | 88 | 89 | 90 | /* costella_image_finalize: 91 | ** 92 | ** Public interface for finalizing this library. 93 | */ 94 | 95 | COSTELLA_ANSI_FUNCTION( costella_image_finalize, int, ( FILE* pfileError ) ) 96 | { 97 | if( COSTELLA_CALL( CostellaImageFinalize() ) ) 98 | { 99 | COSTELLA_ERROR_FPRINT( pfileError ); 100 | COSTELLA_ANSI_RETURN( 0 ); 101 | } 102 | } 103 | COSTELLA_END_ANSI_FUNCTION( !0 ) 104 | 105 | 106 | 107 | /* CostellaImageInitialize: 108 | ** 109 | ** Initialize the library. 110 | */ 111 | 112 | COSTELLA_FUNCTION( CostellaImageInitialize, ( void ) ) 113 | { 114 | /* Do nothing if already initialized. 115 | */ 116 | 117 | if( gbInitialized ) 118 | { 119 | COSTELLA_RETURN; 120 | } 121 | 122 | 123 | /* Set initialized flag. 124 | */ 125 | 126 | gbInitialized = COSTELLA_TRUE; 127 | 128 | 129 | /* Initialize other libraries. 130 | */ 131 | 132 | if( COSTELLA_CALL( CostellaBaseInitialize( 0, 0, 0 ) ) ) 133 | { 134 | COSTELLA_ERROR( "Initializing" ); 135 | gbInitialized = COSTELLA_FALSE; 136 | COSTELLA_RETURN; 137 | } 138 | } 139 | COSTELLA_END_FUNCTION 140 | 141 | 142 | 143 | /* CostellaImageFinalize: 144 | ** 145 | ** Finalize the library. 146 | */ 147 | 148 | COSTELLA_FUNCTION( CostellaImageFinalize, ( void ) ) 149 | { 150 | /* Do nothing if not initialized. 151 | */ 152 | 153 | if( !gbInitialized ) 154 | { 155 | COSTELLA_RETURN; 156 | } 157 | 158 | 159 | /* Clear initialized flag. 160 | */ 161 | 162 | gbInitialized = COSTELLA_FALSE; 163 | 164 | 165 | /* Finalize other libraries. 166 | */ 167 | 168 | if( COSTELLA_CALL( CostellaBaseFinalize() ) ) 169 | { 170 | COSTELLA_ERROR( "Finalizing" ); 171 | COSTELLA_RETURN; 172 | } 173 | } 174 | COSTELLA_END_FUNCTION 175 | 176 | 177 | 178 | /* Copyright (c) 2005-2007 John P. Costella. 179 | ** 180 | ** End of file. 181 | */ 182 | -------------------------------------------------------------------------------- /costella/costella_image_convert.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2005-2007 John P. Costella. 2 | ** 3 | ** Permission is hereby granted, free of charge, to any person obtaining a 4 | ** copy of this software and associated documentation files (the "Software") 5 | ** to deal in the Software without restriction, including without limitation 6 | ** the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | ** and/or sell copies of the Software, and to permit persons to whom the 8 | ** Software is furnished to do so, subject to the following conditions: 9 | ** 10 | ** The above copyright notice and this permission notice shall be included 11 | ** in all copies or substantial portions of the Software. 12 | ** 13 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 15 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. 16 | ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER 17 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING 18 | ** FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | ** DEALINGS IN THE SOFTWARE. 20 | ** 21 | ** 22 | ** costella_image_convert.h: 23 | ** 24 | ** Header file for costella_image_convert.c. 25 | ** 26 | ** This version: September 13, 2007. 27 | ** 28 | ** Written in ANSI C. 29 | */ 30 | 31 | 32 | 33 | /* Include file only once. 34 | */ 35 | 36 | #ifndef _COSTELLA_IMAGE_CONVERT_H_ 37 | #define _COSTELLA_IMAGE_CONVERT_H_ 38 | 39 | 40 | 41 | /* Include files. 42 | */ 43 | 44 | #include "costella_image.h" 45 | #include "costella_wrap.h" 46 | 47 | 48 | 49 | /* Public interface. 50 | */ 51 | 52 | int costella_image_convert_initialize( FILE* pfileError ); 53 | int costella_image_convert_finalize( FILE* pfileError ); 54 | 55 | int costella_image_convert_rgb_to_ycbcr( COSTELLA_IMAGE* piIn, 56 | COSTELLA_IMAGE* piOut, int (*pfProgress)( void* pvPassback ), void* 57 | pvPassback, FILE* pfileError ); 58 | 59 | int costella_image_convert_ycbcr_to_rgb( COSTELLA_IMAGE* piIn, 60 | COSTELLA_IMAGE* piOut, int (*pfProgress)( void* pvPassback ), void* 61 | pvPassback, FILE* pfileError ); 62 | 63 | 64 | 65 | /* Function prototypes. 66 | */ 67 | 68 | COSTELLA_FUNCTION( CostellaImageConvertInitialize, ( void ) ) 69 | COSTELLA_FUNCTION( CostellaImageConvertFinalize, ( void ) ) 70 | 71 | COSTELLA_FUNCTION( CostellaImageConvertRgbToYcbcr, ( COSTELLA_IMAGE* piIn, 72 | COSTELLA_IMAGE* piOut, COSTELLA_CALLBACK_FUNCTION pfProgress, COSTELLA_O* 73 | poPassback ) ) 74 | COSTELLA_FUNCTION( CostellaImageConvertYcbcrToRgb, ( COSTELLA_IMAGE* piIn, 75 | COSTELLA_IMAGE* piOut, COSTELLA_CALLBACK_FUNCTION pfProgress, COSTELLA_O* 76 | poPassback ) ) 77 | 78 | 79 | 80 | /* COSTELLA_IMAGE_CONVERT_RGB_TO_Y: 81 | ** 82 | ** Convert RGB channel values to a Y channel value only. 83 | ** 84 | ** lub{R,G,B}: Input {red,green,blue} channel value. 85 | ** 86 | ** lpubY: Pointer to COSTELLA_UB to contain Y output value. 87 | */ 88 | 89 | #define COSTELLA_IMAGE_CONVERT_RGB_TO_Y( lubR, lubG, lubB, lpubY ) \ 90 | { \ 91 | *(lpubY) = (COSTELLA_UB) COSTELLA_SHIFT_RIGHT_FLOOR( \ 92 | gasdCostellaImageConvertRY[ (lubR) ] + gasdCostellaImageConvertGY[ \ 93 | (lubG) ] + gasdCostellaImageConvertBY[ (lubB) ], 16 ); \ 94 | } 95 | 96 | 97 | 98 | /* COSTELLA_IMAGE_CONVERT_RGB_TO_YCBCR: 99 | ** 100 | ** Convert RGB channel values to YCbCr channel values. 101 | ** 102 | ** lub{R,G,B}: Input {red,green,blue} channel value. 103 | ** 104 | ** lpub{Y,Cb,Cr}: Pointer to COSTELLA_UB to contain {Y,Cb,Cr} output 105 | ** value. 106 | */ 107 | 108 | #define COSTELLA_IMAGE_CONVERT_RGB_TO_YCBCR( lubR, lubG, lubB, lpubY, \ 109 | lpubCb, lpubCr ) \ 110 | { \ 111 | COSTELLA_IMAGE_CONVERT_RGB_TO_Y( lubR, lubG, lubB, lpubY ); \ 112 | \ 113 | *(lpubCb) = (COSTELLA_UB) COSTELLA_SHIFT_RIGHT_FLOOR( \ 114 | gasdCostellaImageConvertRCb[ (lubR) ] + gasdCostellaImageConvertGCb[ \ 115 | (lubG) ] + gasdCostellaImageConvertBCb[ (lubB) ], 16 ); \ 116 | \ 117 | *(lpubCr) = (COSTELLA_UB) COSTELLA_SHIFT_RIGHT_FLOOR( \ 118 | gasdCostellaImageConvertRCr[ (lubR) ] + gasdCostellaImageConvertGCr[ \ 119 | (lubG) ] + gasdCostellaImageConvertBCr[ (lubB) ], 16 ); \ 120 | } 121 | 122 | 123 | 124 | /* COSTELLA_IMAGE_CONVERT_YCBCR_TO_RGB: 125 | ** 126 | ** Convert YCbCr channel values to RGB channel values. 127 | ** 128 | ** lub{Y,Cb,Cr}: Input {Y,Cb,Cr} channel value. 129 | ** 130 | ** lpub{R,G,B}: Pointer to COSTELLA_UB to contain {R,G,B} output value. 131 | */ 132 | 133 | #define COSTELLA_IMAGE_CONVERT_YCBCR_TO_RGB( lubY, lubCb, lubCr, lpubR, \ 134 | lpubG, lpubB ) \ 135 | { \ 136 | COSTELLA_SW lswR, lswG, lswB; \ 137 | \ 138 | lswR = (COSTELLA_SW) (lubY) + gaswCostellaImageConvertCrR[ (lubCr) ];\ 139 | lswG = (COSTELLA_SW) (lubY) + (COSTELLA_SW) COSTELLA_SHIFT_RIGHT_FLOOR( \ 140 | gasdCostellaImageConvertCbG[ (lubCb) ] + gasdCostellaImageConvertCrG[ \ 141 | (lubCr) ], 16 ); \ 142 | lswB = (COSTELLA_SW) (lubY) + gaswCostellaImageConvertCbB[ (lubCb) ]; \ 143 | \ 144 | *(lpubR) = (COSTELLA_UB) COSTELLA_IMAGE_LIMIT_RANGE( lswR ); \ 145 | *(lpubG) = (COSTELLA_UB) COSTELLA_IMAGE_LIMIT_RANGE( lswG ); \ 146 | *(lpubB) = (COSTELLA_UB) COSTELLA_IMAGE_LIMIT_RANGE( lswB ); \ 147 | } 148 | 149 | 150 | 151 | /* Declaration of global variables defined in costella_image_convert.c. 152 | */ 153 | 154 | #ifndef _COSTELLA_IMAGE_CONVERT_C_ 155 | 156 | extern COSTELLA_SW* gaswCostellaImageConvertCrR, 157 | * gaswCostellaImageConvertCbB; 158 | extern COSTELLA_SD* gasdCostellaImageConvertRY, 159 | * gasdCostellaImageConvertGY, * gasdCostellaImageConvertBY, 160 | * gasdCostellaImageConvertRCb, * gasdCostellaImageConvertGCb, 161 | * gasdCostellaImageConvertBCb, * gasdCostellaImageConvertRCr, 162 | * gasdCostellaImageConvertGCr, * gasdCostellaImageConvertBCr, 163 | * gasdCostellaImageConvertCbG, * gasdCostellaImageConvertCrG; 164 | 165 | #endif 166 | 167 | 168 | 169 | /* File is now included. 170 | */ 171 | 172 | #endif 173 | 174 | 175 | 176 | /* Copyright (c) 2005-2007 John P. Costella. 177 | ** 178 | ** End of file. 179 | */ 180 | -------------------------------------------------------------------------------- /costella/costella_image_win32_dib.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2005-2007 John P. Costella. 2 | ** 3 | ** Permission is hereby granted, free of charge, to any person obtaining a 4 | ** copy of this software and associated documentation files (the "Software") 5 | ** to deal in the Software without restriction, including without limitation 6 | ** the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | ** and/or sell copies of the Software, and to permit persons to whom the 8 | ** Software is furnished to do so, subject to the following conditions: 9 | ** 10 | ** The above copyright notice and this permission notice shall be included 11 | ** in all copies or substantial portions of the Software. 12 | ** 13 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 15 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. 16 | ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER 17 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING 18 | ** FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | ** DEALINGS IN THE SOFTWARE. 20 | ** 21 | ** 22 | ** costella_image_win32_dib.h: 23 | ** 24 | ** Set up pixel structure for a Win32 DIB (Device Independent Bitmap), 25 | ** which uses COLORREF structures to store the pixels. 26 | ** 27 | ** This version: May 20, 2007. 28 | ** 29 | ** Relies on Win32. 30 | */ 31 | 32 | 33 | /* Include file only once. 34 | */ 35 | 36 | #ifndef _COSTELLA_IMAGE_WIN32_DIB_H_ 37 | #define _COSTELLA_IMAGE_WIN32_DIB_H_ 38 | 39 | 40 | 41 | /* Include files. 42 | */ 43 | 44 | #include 45 | 46 | 47 | 48 | /* Typedefs. 49 | */ 50 | 51 | typedef COLORREF* COSTELLA_IMAGE_GRAY; 52 | typedef COLORREF* COSTELLA_IMAGE_ALPHA; 53 | typedef COLORREF* COSTELLA_IMAGE_COLOR; 54 | 55 | typedef COLORREF* COSTELLA_IMAGE_GRAY_PIXEL; 56 | typedef COLORREF* COSTELLA_IMAGE_ALPHA_PIXEL; 57 | typedef COLORREF* COSTELLA_IMAGE_COLOR_PIXEL; 58 | 59 | 60 | 61 | /* Macros. 62 | */ 63 | 64 | #define COSTELLA_IMAGE_GRAY_IS_SAME( lig1, lig2 ) \ 65 | ( (lig1) == (lig2) ) 66 | 67 | #define COSTELLA_IMAGE_ALPHA_IS_SAME( lia1, lia2 ) \ 68 | ( (lia1) == (lia2) ) 69 | 70 | #define COSTELLA_IMAGE_COLOR_IS_SAME( lic1, lic2 ) \ 71 | ( (lic1) == (lic2) ) 72 | 73 | 74 | #define COSTELLA_IMAGE_GRAY_PIXEL_ASSIGN( ligpRight, ligpLeft ) \ 75 | ( (ligpLeft) = (ligpRight) ) 76 | 77 | #define COSTELLA_IMAGE_ALPHA_PIXEL_ASSIGN( liapRight, liapLeft ) \ 78 | ( (liapLeft) = (liapRight) ) 79 | 80 | #define COSTELLA_IMAGE_COLOR_PIXEL_ASSIGN( licpRight, licpLeft ) \ 81 | ( (licpLeft) = (licpRight) ) 82 | 83 | 84 | #define COSTELLA_IMAGE_GRAY_PIXEL_SET_TOP_LEFT( ligp, lig, udWidth, \ 85 | udHeight, sdRowStride ) \ 86 | ( (ligp) = (lig) ) 87 | 88 | #define COSTELLA_IMAGE_ALPHA_PIXEL_SET_TOP_LEFT( liap, lia, udWidth, \ 89 | udHeight, sdRowStride ) \ 90 | ( (liap) = (lia) ) 91 | 92 | #define COSTELLA_IMAGE_COLOR_PIXEL_SET_TOP_LEFT( licp, lic, udWidth, \ 93 | udHeight, sdRowStride ) \ 94 | ( (licp) = (lic) ) 95 | 96 | 97 | #define COSTELLA_IMAGE_GRAY_PIXEL_MOVE_LEFT( ligp ) \ 98 | ( (ligp)-- ) 99 | 100 | #define COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_LEFT( liap ) \ 101 | ( (liap)-- ) 102 | 103 | #define COSTELLA_IMAGE_COLOR_PIXEL_MOVE_LEFT( licp ) \ 104 | ( (licp)-- ) 105 | 106 | 107 | #define COSTELLA_IMAGE_GRAY_PIXEL_MOVE_RIGHT( ligp ) \ 108 | ( (ligp)++ ) 109 | 110 | #define COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_RIGHT( liap ) \ 111 | ( (liap)++ ) 112 | 113 | #define COSTELLA_IMAGE_COLOR_PIXEL_MOVE_RIGHT( licp ) \ 114 | ( (licp)++ ) 115 | 116 | 117 | #define COSTELLA_IMAGE_GRAY_PIXEL_MOVE_UP( ligp, lsdRowStride ) \ 118 | ( (ligp) -= (lsdRowStride) ) 119 | 120 | #define COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_UP( liap, lsdRowStride ) \ 121 | ( (liap) -= (lsdRowStride) ) 122 | 123 | #define COSTELLA_IMAGE_COLOR_PIXEL_MOVE_UP( licp, lsdRowStride ) \ 124 | ( (licp) -= (lsdRowStride) ) 125 | 126 | 127 | #define COSTELLA_IMAGE_GRAY_PIXEL_MOVE_DOWN( ligp, lsdRowStride ) \ 128 | ( (ligp) += (lsdRowStride) ) 129 | 130 | #define COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_DOWN( liap, lsdRowStride ) \ 131 | ( (liap) += (lsdRowStride) ) 132 | 133 | #define COSTELLA_IMAGE_COLOR_PIXEL_MOVE_DOWN( licp, lsdRowStride ) \ 134 | ( (licp) += (lsdRowStride) ) 135 | 136 | 137 | #define COSTELLA_IMAGE_COLOR_PIXEL_MOVE_LEFT_TWO( licp ) \ 138 | ( (licp) -= 2 ) 139 | 140 | #define COSTELLA_IMAGE_COLOR_PIXEL_MOVE_RIGHT_TWO( licp ) \ 141 | ( (licp) += 2 ) 142 | 143 | #define COSTELLA_IMAGE_COLOR_PIXEL_MOVE_UP_TWO( licp, lsdDoubleRowStride ) \ 144 | ( (licp) -= (lsdDoubleRowStride) ) 145 | 146 | #define COSTELLA_IMAGE_COLOR_PIXEL_MOVE_DOWN_TWO( licp, lsdDoubleRowStride \ 147 | ) \ 148 | ( (licp) += (lsdDoubleRowStride) ) 149 | 150 | 151 | #define COSTELLA_IMAGE_GRAY_PIXEL_GET_Y( ligp ) \ 152 | ( (BYTE) *(ligp) ) 153 | 154 | #define COSTELLA_IMAGE_ALPHA_PIXEL_GET_A( liap ) \ 155 | ( (BYTE) ( *(liap) >> 24 ) ) 156 | 157 | #define COSTELLA_IMAGE_COLOR_PIXEL_GET_R_Y( licp ) \ 158 | ( (BYTE) ( *(licp) >> 16 ) ) 159 | 160 | #define COSTELLA_IMAGE_COLOR_PIXEL_GET_G_CB( licp ) \ 161 | ( (BYTE) ( *(licp) >> 8 ) ) 162 | 163 | #define COSTELLA_IMAGE_COLOR_PIXEL_GET_B_CR( licp ) \ 164 | ( (BYTE) *(licp) ) 165 | 166 | 167 | #define COSTELLA_IMAGE_GRAY_PIXEL_SET_Y( ligp, lubY ) \ 168 | ( *(ligp) &= 0xff000000, *(ligp) |= (COLORREF) (BYTE) (lubY) | \ 169 | (COLORREF) (BYTE) (lubY) << 8 | (COLORREF) (BYTE) (lubY) << 16 ) 170 | 171 | #define COSTELLA_IMAGE_ALPHA_PIXEL_SET_A( liap, lubA ) \ 172 | ( *(liap) &= 0x000000ff, *(liap) |= (COLORREF) (BYTE) (lubA) << 24 ) 173 | 174 | #define COSTELLA_IMAGE_COLOR_PIXEL_SET_R_Y( licp, lubRY ) \ 175 | ( *(licp) &= 0xff00ffff, *(licp) |= (COLORREF) (BYTE) (lubRY) << 16 ) 176 | 177 | #define COSTELLA_IMAGE_COLOR_PIXEL_SET_G_CB( licp, lubGCb ) \ 178 | ( *(licp) &= 0xffff00ff, *(licp) |= (COLORREF) (BYTE) (lubGCb) << 8 ) 179 | 180 | #define COSTELLA_IMAGE_COLOR_PIXEL_SET_B_CR( licp, lubBCr ) \ 181 | ( *(licp) &= 0xffffff00, *(licp) |= (COLORREF) (BYTE) (lubBCr) ) 182 | 183 | #define COSTELLA_IMAGE_COLOR_PIXEL_SET_RGB_YCBCR( licp, lubRY, lubGCb, \ 184 | lubBCr ) \ 185 | ( *(licp) &= 0xff000000, *(licp) |= (COLORREF) (BYTE) (lubBCr) | \ 186 | ( (COLORREF) (BYTE) (lubGCb) | (COLORREF) (BYTE) (lubRY) << 8 ) << 8 ) 187 | 188 | 189 | 190 | /* File is now included. 191 | */ 192 | 193 | #endif 194 | 195 | 196 | 197 | /* Copyright (c) 2005-2007 John P. Costella. 198 | ** 199 | ** End of file. 200 | */ 201 | -------------------------------------------------------------------------------- /costella/costella_image_rgb_triple.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2005-2007 John P. Costella. 2 | ** 3 | ** Permission is hereby granted, free of charge, to any person obtaining a 4 | ** copy of this software and associated documentation files (the "Software") 5 | ** to deal in the Software without restriction, including without limitation 6 | ** the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | ** and/or sell copies of the Software, and to permit persons to whom the 8 | ** Software is furnished to do so, subject to the following conditions: 9 | ** 10 | ** The above copyright notice and this permission notice shall be included 11 | ** in all copies or substantial portions of the Software. 12 | ** 13 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 15 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. 16 | ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER 17 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING 18 | ** FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | ** DEALINGS IN THE SOFTWARE. 20 | ** 21 | ** 22 | ** costella_image_rgb_triple.h: 23 | ** 24 | ** Set up pixel structure for RGB triples, such as for Windows 24-bit BMP 25 | ** files, in which components are stored in contiguous byte order 26 | ** BGRBGRBGR.... 27 | ** 28 | ** Written in ANSI C. 29 | */ 30 | 31 | 32 | 33 | /* Include file only once. 34 | */ 35 | 36 | #ifndef _COSTELLA_IMAGE_RGB_TRIPLE_H_ 37 | #define _COSTELLA_IMAGE_RGB_TRIPLE_H_ 38 | 39 | 40 | 41 | /* Typedefs. 42 | */ 43 | 44 | typedef COSTELLA_UB* COSTELLA_IMAGE_GRAY; 45 | typedef COSTELLA_UB* COSTELLA_IMAGE_ALPHA; 46 | typedef COSTELLA_UB* COSTELLA_IMAGE_COLOR; 47 | 48 | typedef COSTELLA_UB* COSTELLA_IMAGE_GRAY_PIXEL; 49 | typedef COSTELLA_UB* COSTELLA_IMAGE_ALPHA_PIXEL; 50 | 51 | typedef struct 52 | { 53 | COSTELLA_UB* pubRY; 54 | COSTELLA_UB* pubGCb; 55 | COSTELLA_UB* pubBCr; 56 | } 57 | COSTELLA_IMAGE_COLOR_PIXEL; 58 | 59 | 60 | 61 | /* Macros. 62 | */ 63 | 64 | #define COSTELLA_IMAGE_GRAY_IS_SAME( lig1, lig2 ) \ 65 | ( (lig1) == (lig2) ) 66 | 67 | #define COSTELLA_IMAGE_ALPHA_IS_SAME( lia1, lia2 ) \ 68 | ( (lia1) == (lia2) ) 69 | 70 | #define COSTELLA_IMAGE_COLOR_IS_SAME( lic1, lic2 ) \ 71 | ( (lic1) == (lic2) ) 72 | 73 | 74 | #define COSTELLA_IMAGE_GRAY_PIXEL_ASSIGN( ligpRight, ligpLeft ) \ 75 | ( (ligpLeft) = (ligpRight) ) 76 | 77 | #define COSTELLA_IMAGE_ALPHA_PIXEL_ASSIGN( liapRight, liapLeft ) \ 78 | ( (liapLeft) = (liapRight) ) 79 | 80 | #define COSTELLA_IMAGE_COLOR_PIXEL_ASSIGN( licpRight, licpLeft ) \ 81 | ( (licpLeft).pubRY = (licpRight).pubRY, (licpLeft).pubGCb = \ 82 | (licpRight).pubGCb, (licpLeft).pubBCr = (licpRight).pubBCr ) 83 | 84 | 85 | #define COSTELLA_IMAGE_GRAY_PIXEL_SET_TOP_LEFT( ligp, lig, udWidth, \ 86 | udHeight, sdRowStride ) \ 87 | ( (ligp) = (lig) ) 88 | 89 | #define COSTELLA_IMAGE_ALPHA_PIXEL_SET_TOP_LEFT( liap, lia, udWidth, \ 90 | udHeight, sdRowStride ) \ 91 | ( (liap) = (lia) ) 92 | 93 | #define COSTELLA_IMAGE_COLOR_PIXEL_SET_TOP_LEFT( licp, lic, udWidth, \ 94 | udHeight, sdRowStride ) \ 95 | ( (licp).pubRY = (lic) + 2, (licp).pubGCb = (lic) + 1, (licp).pubBCr = \ 96 | (lic) ) 97 | 98 | 99 | #define COSTELLA_IMAGE_GRAY_PIXEL_MOVE_LEFT( ligp ) \ 100 | ( (ligp)-- ) 101 | 102 | #define COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_LEFT( liap ) \ 103 | ( (liap)-- ) 104 | 105 | #define COSTELLA_IMAGE_COLOR_PIXEL_MOVE_LEFT( licp ) \ 106 | ( (licp).pubRY -= 3, (licp).pubGCb -= 3, (licp).pubBCr -= 3 ) 107 | 108 | 109 | #define COSTELLA_IMAGE_GRAY_PIXEL_MOVE_RIGHT( ligp ) \ 110 | ( (ligp)++ ) 111 | 112 | #define COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_RIGHT( liap ) \ 113 | ( (liap)++ ) 114 | 115 | #define COSTELLA_IMAGE_COLOR_PIXEL_MOVE_RIGHT( licp ) \ 116 | ( (licp).pubRY += 3, (licp).pubGCb += 3, (licp).pubBCr += 3 ) 117 | 118 | 119 | #define COSTELLA_IMAGE_GRAY_PIXEL_MOVE_UP( ligp, lsdRowStride ) \ 120 | ( (ligp) -= (lsdRowStride) ) 121 | 122 | #define COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_UP( liap, lsdRowStride ) \ 123 | ( (liap) -= (lsdRowStride) ) 124 | 125 | #define COSTELLA_IMAGE_COLOR_PIXEL_MOVE_UP( licp, lsdRowStride ) \ 126 | ( (licp).pubRY -= (lsdRowStride), (licp).pubGCb -= (lsdRowStride), \ 127 | (licp).pubBCr -= (lsdRowStride) ) 128 | 129 | 130 | #define COSTELLA_IMAGE_GRAY_PIXEL_MOVE_DOWN( ligp, lsdRowStride ) \ 131 | ( (ligp) += (lsdRowStride) ) 132 | 133 | #define COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_DOWN( liap, lsdRowStride ) \ 134 | ( (liap) += (lsdRowStride) ) 135 | 136 | #define COSTELLA_IMAGE_COLOR_PIXEL_MOVE_DOWN( licp, lsdRowStride ) \ 137 | ( (licp).pubRY += (lsdRowStride), (licp).pubGCb += (lsdRowStride), \ 138 | (licp).pubBCr += (lsdRowStride) ) 139 | 140 | 141 | #define COSTELLA_IMAGE_COLOR_PIXEL_MOVE_LEFT_TWO( licp ) \ 142 | ( (licp).pubRY -= 6, (licp).pubGCb -= 6, (licp).pubBCr -= 6 ) 143 | 144 | #define COSTELLA_IMAGE_COLOR_PIXEL_MOVE_RIGHT_TWO( licp ) \ 145 | ( (licp).pubRY += 6, (licp).pubGCb += 6, (licp).pubBCr += 6 ) 146 | 147 | #define COSTELLA_IMAGE_COLOR_PIXEL_MOVE_UP_TWO( licp, lsdDoubleRowStride ) \ 148 | ( (licp).pubRY -= (lsdDoubleRowStride), (licp).pubGCb -= \ 149 | (lsdDoubleRowStride), (licp).pubBCr -= (lsdDoubleRowStride) ) 150 | 151 | #define COSTELLA_IMAGE_COLOR_PIXEL_MOVE_DOWN_TWO( licp, lsdDoubleRowStride \ 152 | ) \ 153 | ( (licp).pubRY += (lsdDoubleRowStride), (licp).pubGCb += \ 154 | (lsdDoubleRowStride), (licp).pubBCr += (lsdDoubleRowStride) ) 155 | 156 | 157 | #define COSTELLA_IMAGE_GRAY_PIXEL_GET_Y( ligp ) \ 158 | ( *(ligp) ) 159 | 160 | #define COSTELLA_IMAGE_ALPHA_PIXEL_GET_A( liap ) \ 161 | ( *(liap) ) 162 | 163 | #define COSTELLA_IMAGE_COLOR_PIXEL_GET_R_Y( licp ) \ 164 | ( *(licp).pubRY ) 165 | 166 | #define COSTELLA_IMAGE_COLOR_PIXEL_GET_G_CB( licp ) \ 167 | ( *(licp).pubGCb ) 168 | 169 | #define COSTELLA_IMAGE_COLOR_PIXEL_GET_B_CR( licp ) \ 170 | ( *(licp).pubBCr ) 171 | 172 | 173 | #define COSTELLA_IMAGE_GRAY_PIXEL_SET_Y( ligp, lubY ) \ 174 | ( *(ligp) = (lubY) ) 175 | 176 | #define COSTELLA_IMAGE_ALPHA_PIXEL_SET_A( liap, lubA ) \ 177 | ( *(liap) = (lubA) ) 178 | 179 | #define COSTELLA_IMAGE_COLOR_PIXEL_SET_R_Y( licp, lubRY ) \ 180 | ( *(licp).pubRY = (lubRY) ) 181 | 182 | #define COSTELLA_IMAGE_COLOR_PIXEL_SET_G_CB( licp, lubGCb ) \ 183 | ( *(licp).pubGCb = (lubGCb) ) 184 | 185 | #define COSTELLA_IMAGE_COLOR_PIXEL_SET_B_CR( licp, lubBCr ) \ 186 | ( *(licp).pubBCr = (lubBCr) ) 187 | 188 | #define COSTELLA_IMAGE_COLOR_PIXEL_SET_RGB_YCBCR( licp, lubRY, lubGCb, \ 189 | lubBCr ) \ 190 | ( COSTELLA_IMAGE_COLOR_PIXEL_SET_R_Y( licp, lubRY ), \ 191 | COSTELLA_IMAGE_COLOR_PIXEL_SET_G_CB( licp, lubGCb ), \ 192 | COSTELLA_IMAGE_COLOR_PIXEL_SET_B_CR( licp, lubBCr ) ) 193 | 194 | 195 | 196 | /* File is now included. 197 | */ 198 | 199 | #endif 200 | 201 | 202 | 203 | /* Copyright (c) 2005-2007 John P. Costella. 204 | ** 205 | ** End of file. 206 | */ -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | // Convert a .bmp file (from a high-compression jpg, as from a very cheap camera) 2 | // into another .bmp file with greatly attenuated 8x8-pixel-block jpg artifacts. 3 | 4 | extern "C" { 5 | #include "costella_unblock.h" 6 | } 7 | #include "EasyBMP.h" 8 | #include 9 | #include 10 | #include 11 | 12 | using u8 = uint8_t; 13 | 14 | // Actually YCbCr, not YUV. 15 | // From https://web.archive.org/web/20180423091842/http://www.equasys.de/colorconversion.html YCbCr - RGB. 16 | void YUVfromRGB(u8& Y, u8& U, u8& V, const double R, const double G, const double B) 17 | { 18 | const auto y = 0.257 * R + 0.504 * G + 0.098 * B + 16.0; 19 | const auto u = -0.148 * R - 0.291 * G + 0.439 * B + 128.0; 20 | const auto v = 0.439 * R - 0.368 * G - 0.071 * B + 128.0; 21 | // Clamp to [0, 255]. 22 | Y = COSTELLA_IMAGE_LIMIT_RANGE(y); 23 | U = COSTELLA_IMAGE_LIMIT_RANGE(u); 24 | V = COSTELLA_IMAGE_LIMIT_RANGE(v); 25 | } 26 | void RGBfromYUV(u8& R, u8& G, u8& B, double Y, double U, double V) 27 | { 28 | Y -= 16.0; 29 | U -= 128.0; 30 | V -= 128.0; 31 | const auto r = 1.164 * Y + 1.596 * V; 32 | const auto g = 1.164 * Y - 0.392 * U - 0.813 * V; 33 | const auto b = 1.164 * Y + 2.017 * U; 34 | // Clamp to [0, 255]. 35 | R = COSTELLA_IMAGE_LIMIT_RANGE(r); 36 | G = COSTELLA_IMAGE_LIMIT_RANGE(g); 37 | B = COSTELLA_IMAGE_LIMIT_RANGE(b); 38 | } 39 | 40 | std::string filenameExtension(const std::string& s) 41 | { 42 | const auto i = s.find_last_of("."); 43 | if (i == std::string::npos) 44 | return ""; 45 | auto ext(s.substr(i + 1)); 46 | std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower); 47 | return ext; 48 | } 49 | 50 | int main(int argc, char** argv) 51 | { 52 | if (argc != 3) { 53 | LUsage: 54 | printf("usage: %s in.[bmp|png] out.[bmp|png]\n", argv[0]); 55 | return 1; 56 | } 57 | const auto ext1 = filenameExtension(argv[1]); 58 | const auto ext2 = filenameExtension(argv[2]); 59 | const bool fBMP = ext1 == "bmp"; 60 | const bool fPNG = ext1 == "png"; 61 | if (!fBMP && !fPNG) 62 | goto LUsage; 63 | if (ext2 != ext1) 64 | printf("%s: warning: filenames %s and %s have different extensions.\nFile %s will get the same format as %s.\n", argv[0], argv[1], argv[2], argv[2], argv[1]); 65 | 66 | FILE *fp; 67 | unsigned w, h; 68 | BMP bmp; 69 | png_bytep *pRows = NULL; 70 | 71 | if (fBMP) { 72 | bmp.ReadFromFile(argv[1]); 73 | w = bmp.TellWidth(); 74 | h = bmp.TellHeight(); 75 | } else { 76 | fp = fopen(argv[1], "rb"); 77 | auto pPNG = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); 78 | auto pInfoPNG = png_create_info_struct(pPNG); 79 | png_init_io(pPNG, fp); 80 | png_read_info(pPNG, pInfoPNG); 81 | if (png_get_color_type(pPNG, pInfoPNG) != PNG_COLOR_TYPE_RGB) { 82 | // Alpha, grayscale, and palette formats wouldn't have come from a JPG. 83 | printf("%s: png file %s isn't in RGB format.\n", argv[0], argv[1]); 84 | return 1; 85 | } 86 | // Transform 16 bit to 8 bit. 87 | if (png_get_bit_depth(pPNG, pInfoPNG) == 16) { 88 | png_set_strip_16(pPNG); 89 | png_read_update_info(pPNG, pInfoPNG); 90 | } 91 | w = png_get_image_width(pPNG, pInfoPNG); 92 | h = png_get_image_height(pPNG, pInfoPNG); 93 | pRows = new png_bytep[h]; 94 | const auto cb = png_get_rowbytes(pPNG, pInfoPNG); 95 | for (unsigned y = 0u; y < h; ++y) 96 | pRows[y] = new png_byte[cb]; 97 | png_read_image(pPNG, pRows); 98 | fclose(fp); 99 | png_destroy_read_struct(&pPNG, &pInfoPNG, NULL); 100 | } 101 | 102 | // Convert bmp.rgb_data or pRows to YUV color planes. 103 | const auto cb = w * h; 104 | u8 bufY[cb]; 105 | u8 bufU[cb]; 106 | u8 bufV[cb]; 107 | unsigned y, x; 108 | auto i = 0; 109 | for (y = 0u; y < h; ++y) { 110 | for (x = 0u; x < w; ++x,++i) { 111 | double R,G,B; 112 | if (fBMP) { 113 | const auto rgb = bmp(x,y); 114 | R = rgb->Red; 115 | G = rgb->Green; 116 | B = rgb->Blue; 117 | } else { 118 | const auto rgb = pRows[y] + 3*x; 119 | R = rgb[0]; 120 | G = rgb[1]; 121 | B = rgb[2]; 122 | } 123 | YUVfromRGB(bufY[i],bufU[i],bufV[i], R,G,B); 124 | } 125 | } 126 | 127 | COSTELLA_IMAGE im; 128 | im.bAlpha = 0; 129 | im.bRgb = 0; 130 | im.udHeight = h; 131 | im.udWidth = w; // may fail if not a multiple of 16 132 | im.sdRowStride = w; // maybe something about bufPitch, width bumped up to multiple of 16. 133 | im.sdAlphaRowStride = 0; 134 | #if 0 135 | // Unblock only luma (bufY). 136 | im.bColor = im.bDownsampledChrominance = im.bNonreplicatedDownsampledChrominance = 0; 137 | im.ig = bufY /* COSTELLA_IMAGE_GRAY */; 138 | #else 139 | // Unblock luma, Cb, and Cr. 140 | im.bColor = im.bDownsampledChrominance = im.bNonreplicatedDownsampledChrominance = 1; 141 | im.ic.aubRY = bufY; 142 | im.ic.aubGCb = bufU; 143 | im.ic.aubBCr = bufV; 144 | #endif 145 | 146 | costella_unblock_initialize(stdout); 147 | const auto fPhoto = 0; // API docs suggest 1, but that boosts ringing of high-contrast detail (timestamps, windows of buildings). 148 | // (Internal mucking about, in costella_unblock.c bConservativePhotographic tweaking udCumMeasuredConservative, 149 | // had either no effect or caused a segfault.) 150 | if (!costella_unblock(&im, &im, fPhoto, 0, NULL, NULL, 0)) 151 | printf("%s: costella_unblock() failed.\n", argv[0]); 152 | costella_unblock_finalize(stdout); 153 | 154 | // Convert bufY, bufU, bufV back into a bmp. 155 | // (Or, set im.bRgb=1 to avoid this conversion? That sets bOutYCbCr in CostellaUnblock(), 156 | // which causes calls to CostellaImageConvertRgbToYcbcr() and CostellaImageConvertYcbcrToRgb(). 157 | // Those call macros like COSTELLA_IMAGE_CONVERT_RGB_TO_YCBCR(), 158 | // which lookup tables like gasdCostellaImageConvertRCb[] for Red to Cb.) 159 | i = 0; 160 | for (y = 0u; y < h; ++y) { 161 | for (x = 0u; x < w; ++x,++i) { 162 | u8 R,G,B; 163 | RGBfromYUV(R,G,B, bufY[i],bufU[i],bufV[i]); 164 | if (fBMP) { 165 | auto rgb = bmp(x,y); 166 | rgb->Red = R; 167 | rgb->Green = G; 168 | rgb->Blue = B; 169 | } else { 170 | auto rgb = pRows[y] + 3*x; 171 | rgb[0] = R; 172 | rgb[1] = G; 173 | rgb[2] = B; 174 | } 175 | } 176 | } 177 | if (fBMP) { 178 | bmp.WriteToFile(argv[2]); 179 | } else { 180 | fp = fopen(argv[2], "wb"); 181 | auto pPNG = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); 182 | auto pInfoPNG = png_create_info_struct(pPNG); 183 | png_init_io(pPNG, fp); 184 | png_set_IHDR(pPNG, pInfoPNG, w, h, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); 185 | // Don't call png_set_tIME, so no tIME chunk is written, no %tEXtdate:create, %tEXtdate:modify, gAMA, cHRM, bKGD. 186 | // Then the output has no timestamp, so it can be diffed against a known-good test output. 187 | png_write_info(pPNG, pInfoPNG); 188 | png_write_image(pPNG, pRows); 189 | png_write_end(pPNG, NULL); 190 | fclose(fp); 191 | png_destroy_write_struct(&pPNG, &pInfoPNG); 192 | } 193 | return 0; 194 | } 195 | -------------------------------------------------------------------------------- /costella/costella_image_separate_arrays.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2005-2007 John P. Costella. 2 | ** 3 | ** Permission is hereby granted, free of charge, to any person obtaining a 4 | ** copy of this software and associated documentation files (the "Software") 5 | ** to deal in the Software without restriction, including without limitation 6 | ** the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | ** and/or sell copies of the Software, and to permit persons to whom the 8 | ** Software is furnished to do so, subject to the following conditions: 9 | ** 10 | ** The above copyright notice and this permission notice shall be included 11 | ** in all copies or substantial portions of the Software. 12 | ** 13 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 15 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. 16 | ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER 17 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING 18 | ** FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | ** DEALINGS IN THE SOFTWARE. 20 | ** 21 | ** 22 | ** costella_image_separate_arrays.h: 23 | ** 24 | ** Set up pixel structure for three separate arrays of bytes. 25 | ** 26 | ** This version: March 8, 2007. 27 | ** 28 | ** Written in ANSI C. 29 | */ 30 | 31 | 32 | 33 | /* Include file only once. 34 | */ 35 | 36 | #ifndef _COSTELLA_IMAGE_SEPARATE_ARRAYS_H_ 37 | #define _COSTELLA_IMAGE_SEPARATE_ARRAYS_H_ 38 | 39 | 40 | 41 | /* Typedefs. 42 | */ 43 | 44 | typedef COSTELLA_UB* COSTELLA_IMAGE_GRAY; 45 | typedef COSTELLA_UB* COSTELLA_IMAGE_ALPHA; 46 | 47 | 48 | typedef struct 49 | { 50 | COSTELLA_UB* aubRY; 51 | COSTELLA_UB* aubGCb; 52 | COSTELLA_UB* aubBCr; 53 | } 54 | COSTELLA_IMAGE_COLOR; 55 | 56 | 57 | typedef COSTELLA_UB* COSTELLA_IMAGE_GRAY_PIXEL; 58 | typedef COSTELLA_UB* COSTELLA_IMAGE_ALPHA_PIXEL; 59 | 60 | 61 | typedef struct 62 | { 63 | COSTELLA_UB* pubRY; 64 | COSTELLA_UB* pubGCb; 65 | COSTELLA_UB* pubBCr; 66 | } 67 | COSTELLA_IMAGE_COLOR_PIXEL; 68 | 69 | 70 | 71 | /* Macros. 72 | */ 73 | 74 | #define COSTELLA_IMAGE_GRAY_IS_SAME( lig1, lig2 ) \ 75 | ( (lig1) == (lig2) ) 76 | 77 | #define COSTELLA_IMAGE_ALPHA_IS_SAME( lia1, lia2 ) \ 78 | ( (lia1) == (lia2) ) 79 | 80 | #define COSTELLA_IMAGE_COLOR_IS_SAME( lic1, lic2 ) \ 81 | ( (lic1).aubRY == (lic2).aubRY && (lic1).aubGCb == (lic2).aubGCb && \ 82 | (lic1).aubBCr == (lic2).aubBCr ) 83 | 84 | 85 | #define COSTELLA_IMAGE_GRAY_PIXEL_ASSIGN( ligpRight, ligpLeft ) \ 86 | ( (ligpLeft) = (ligpRight) ) 87 | 88 | #define COSTELLA_IMAGE_ALPHA_PIXEL_ASSIGN( liapRight, liapLeft ) \ 89 | ( (liapLeft) = (liapRight) ) 90 | 91 | #define COSTELLA_IMAGE_COLOR_PIXEL_ASSIGN( licpRight, licpLeft ) \ 92 | ( (licpLeft).pubRY = (licpRight).pubRY, (licpLeft).pubGCb = \ 93 | (licpRight).pubGCb, (licpLeft).pubBCr = (licpRight).pubBCr ) 94 | 95 | 96 | #define COSTELLA_IMAGE_GRAY_PIXEL_SET_TOP_LEFT( ligp, lig, udWidth, \ 97 | udHeight, sdRowStride ) \ 98 | ( (ligp) = (lig) ) 99 | 100 | #define COSTELLA_IMAGE_ALPHA_PIXEL_SET_TOP_LEFT( liap, lia, udWidth, \ 101 | udHeight, sdRowStride ) \ 102 | ( (liap) = (lia) ) 103 | 104 | #define COSTELLA_IMAGE_COLOR_PIXEL_SET_TOP_LEFT( licp, lic, udWidth, \ 105 | udHeight, sdRowStride ) \ 106 | ( (licp).pubRY = (lic).aubRY, (licp).pubGCb = (lic).aubGCb, \ 107 | (licp).pubBCr = (lic).aubBCr ) 108 | 109 | 110 | #define COSTELLA_IMAGE_GRAY_PIXEL_MOVE_LEFT( ligp ) \ 111 | ( (ligp)-- ) 112 | 113 | #define COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_LEFT( liap ) \ 114 | ( (liap)-- ) 115 | 116 | #define COSTELLA_IMAGE_COLOR_PIXEL_MOVE_LEFT( licp ) \ 117 | ( (licp).pubRY--, (licp).pubGCb--, (licp).pubBCr-- ) 118 | 119 | 120 | #define COSTELLA_IMAGE_GRAY_PIXEL_MOVE_RIGHT( ligp ) \ 121 | ( (ligp)++ ) 122 | 123 | #define COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_RIGHT( liap ) \ 124 | ( (liap)++ ) 125 | 126 | #define COSTELLA_IMAGE_COLOR_PIXEL_MOVE_RIGHT( licp ) \ 127 | ( (licp).pubRY++, (licp).pubGCb++, (licp).pubBCr++ ) 128 | 129 | 130 | #define COSTELLA_IMAGE_GRAY_PIXEL_MOVE_UP( ligp, lsdRowStride ) \ 131 | ( (ligp) -= (lsdRowStride) ) 132 | 133 | #define COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_UP( liap, lsdRowStride ) \ 134 | ( (liap) -= (lsdRowStride) ) 135 | 136 | #define COSTELLA_IMAGE_COLOR_PIXEL_MOVE_UP( licp, lsdRowStride ) \ 137 | ( (licp).pubRY -= (lsdRowStride), (licp).pubGCb -= (lsdRowStride), \ 138 | (licp).pubBCr -= (lsdRowStride) ) 139 | 140 | 141 | #define COSTELLA_IMAGE_GRAY_PIXEL_MOVE_DOWN( ligp, lsdRowStride ) \ 142 | ( (ligp) += (lsdRowStride) ) 143 | 144 | #define COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_DOWN( liap, lsdRowStride ) \ 145 | ( (liap) += (lsdRowStride) ) 146 | 147 | #define COSTELLA_IMAGE_COLOR_PIXEL_MOVE_DOWN( licp, lsdRowStride ) \ 148 | ( (licp).pubRY += (lsdRowStride), (licp).pubGCb += (lsdRowStride), \ 149 | (licp).pubBCr += (lsdRowStride) ) 150 | 151 | 152 | #define COSTELLA_IMAGE_COLOR_PIXEL_MOVE_LEFT_TWO( licp ) \ 153 | ( (licp).pubRY -= 2, (licp).pubGCb -= 2, (licp).pubBCr -= 2 ) 154 | 155 | #define COSTELLA_IMAGE_COLOR_PIXEL_MOVE_RIGHT_TWO( licp ) \ 156 | ( (licp).pubRY += 2, (licp).pubGCb += 2, (licp).pubBCr += 2 ) 157 | 158 | #define COSTELLA_IMAGE_COLOR_PIXEL_MOVE_UP_TWO( licp, lsdDoubleRowStride ) \ 159 | ( (licp).pubRY -= (lsdDoubleRowStride), (licp).pubGCb -= \ 160 | (lsdDoubleRowStride), (licp).pubBCr -= (lsdDoubleRowStride) ) 161 | 162 | #define COSTELLA_IMAGE_COLOR_PIXEL_MOVE_DOWN_TWO( licp, lsdDoubleRowStride \ 163 | ) \ 164 | ( (licp).pubRY += (lsdDoubleRowStride), (licp).pubGCb += \ 165 | (lsdDoubleRowStride), (licp).pubBCr += (lsdDoubleRowStride) ) 166 | 167 | 168 | #define COSTELLA_IMAGE_GRAY_PIXEL_GET_Y( ligp ) \ 169 | ( *(ligp) ) 170 | 171 | #define COSTELLA_IMAGE_ALPHA_PIXEL_GET_A( liap ) \ 172 | ( *(liap) ) 173 | 174 | #define COSTELLA_IMAGE_COLOR_PIXEL_GET_R_Y( licp ) \ 175 | ( *(licp).pubRY ) 176 | 177 | #define COSTELLA_IMAGE_COLOR_PIXEL_GET_G_CB( licp ) \ 178 | ( *(licp).pubGCb ) 179 | 180 | #define COSTELLA_IMAGE_COLOR_PIXEL_GET_B_CR( licp ) \ 181 | ( *(licp).pubBCr ) 182 | 183 | 184 | #define COSTELLA_IMAGE_GRAY_PIXEL_SET_Y( ligp, lubY ) \ 185 | ( *(ligp) = (lubY) ) 186 | 187 | #define COSTELLA_IMAGE_ALPHA_PIXEL_SET_A( liap, lubA ) \ 188 | ( *(liap) = (lubA) ) 189 | 190 | #define COSTELLA_IMAGE_COLOR_PIXEL_SET_R_Y( licp, lubRY ) \ 191 | ( *(licp).pubRY = (lubRY) ) 192 | 193 | #define COSTELLA_IMAGE_COLOR_PIXEL_SET_G_CB( licp, lubGCb ) \ 194 | ( *(licp).pubGCb = (lubGCb) ) 195 | 196 | #define COSTELLA_IMAGE_COLOR_PIXEL_SET_B_CR( licp, lubBCr ) \ 197 | ( *(licp).pubBCr = (lubBCr) ) 198 | 199 | #define COSTELLA_IMAGE_COLOR_PIXEL_SET_RGB_YCBCR( licp, lubRY, lubGCb, \ 200 | lubBCr ) \ 201 | ( COSTELLA_IMAGE_COLOR_PIXEL_SET_R_Y( licp, lubRY ), \ 202 | COSTELLA_IMAGE_COLOR_PIXEL_SET_G_CB( licp, lubGCb ), \ 203 | COSTELLA_IMAGE_COLOR_PIXEL_SET_B_CR( licp, lubBCr ) ) 204 | 205 | 206 | 207 | /* File is now included. 208 | */ 209 | 210 | #endif 211 | 212 | 213 | 214 | /* Copyright (c) 2005-2007 John P. Costella. 215 | ** 216 | ** End of file. 217 | */ 218 | -------------------------------------------------------------------------------- /costella/costella_wrap.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2006-2007 John P. Costella. 2 | ** 3 | ** Permission is hereby granted, free of charge, to any person obtaining a 4 | ** copy of this software and associated documentation files (the "Software") 5 | ** to deal in the Software without restriction, including without limitation 6 | ** the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | ** and/or sell copies of the Software, and to permit persons to whom the 8 | ** Software is furnished to do so, subject to the following conditions: 9 | ** 10 | ** The above copyright notice and this permission notice shall be included 11 | ** in all copies or substantial portions of the Software. 12 | ** 13 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 15 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. 16 | ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER 17 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING 18 | ** FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | ** DEALINGS IN THE SOFTWARE. 20 | ** 21 | ** 22 | ** costella_wrap.c: 23 | ** 24 | ** Wrapping of callback functions for public interface. 25 | ** 26 | ** Library begun: December 12, 2006. 27 | ** This version: July 11, 2007. 28 | ** 29 | ** Written in ANSI C. 30 | */ 31 | 32 | 33 | 34 | /* Include file. 35 | */ 36 | 37 | #include "costella_wrap.h" 38 | 39 | 40 | 41 | /* Internal global variables. 42 | */ 43 | 44 | static COSTELLA_B gbInitialized = COSTELLA_FALSE; 45 | 46 | 47 | 48 | /* Start function bodies. 49 | */ 50 | 51 | #include "costella_body.h" 52 | 53 | 54 | 55 | /* CostellaWrapInitialize: 56 | ** 57 | ** Initialize the library. 58 | */ 59 | 60 | COSTELLA_FUNCTION( CostellaWrapInitialize, ( void ) ) 61 | { 62 | /* Do nothing if already initialized. 63 | */ 64 | 65 | if( gbInitialized ) 66 | { 67 | COSTELLA_RETURN; 68 | } 69 | 70 | 71 | /* Set initialized flag. 72 | */ 73 | 74 | gbInitialized = COSTELLA_TRUE; 75 | 76 | 77 | /* Initialize other libraries. 78 | */ 79 | 80 | if( COSTELLA_CALL( CostellaBaseInitialize( 0, 0, 0 ) ) ) 81 | { 82 | COSTELLA_ERROR( "Initialization" ); 83 | gbInitialized = COSTELLA_FALSE; 84 | COSTELLA_RETURN; 85 | } 86 | } 87 | COSTELLA_END_FUNCTION 88 | 89 | 90 | 91 | /* CostellaWrapFinalize: 92 | ** 93 | ** Finalize the library. 94 | */ 95 | 96 | COSTELLA_FUNCTION( CostellaWrapFinalize, ( void ) ) 97 | { 98 | /* Do nothing if not initialized. 99 | */ 100 | 101 | if( !gbInitialized ) 102 | { 103 | COSTELLA_RETURN; 104 | } 105 | 106 | 107 | /* Clear initialized flag. 108 | */ 109 | 110 | gbInitialized = COSTELLA_FALSE; 111 | 112 | 113 | /* Finalize other libraries. 114 | */ 115 | 116 | if( COSTELLA_CALL( CostellaBaseFinalize() ) ) 117 | { 118 | COSTELLA_ERROR( "Finalizing" ); 119 | COSTELLA_RETURN; 120 | } 121 | } 122 | COSTELLA_END_FUNCTION 123 | 124 | 125 | 126 | /* CostellaWrapCallbackNew: 127 | ** 128 | ** Create a new COSTELLA_WRAP_CALLBACK object. 129 | ** 130 | ** ppwc: Pointer to receiving pointer for the new COSTELLA_WRAP_CALLBACK 131 | ** object. 132 | ** 133 | ** pfCallback: Pointer to the ANSI callback function. 134 | ** 135 | ** pvPassback: Pointer to the ANSI passback object. 136 | */ 137 | 138 | COSTELLA_FUNCTION( CostellaWrapCallbackNew, ( COSTELLA_WRAP_CALLBACK** ppwc, 139 | int (*pfCallback)( void* pvPassback, void* pv ), void* pvPassback ) ) 140 | { 141 | COSTELLA_WRAP_CALLBACK* pwc = 0; 142 | 143 | 144 | /* Check initialization and pointers. 145 | */ 146 | 147 | #ifdef COSTELLA_DEBUG 148 | { 149 | if( !gbInitialized ) 150 | { 151 | COSTELLA_FUNDAMENTAL_ERROR( "Initialization" ); 152 | COSTELLA_RETURN; 153 | } 154 | 155 | if( !ppwc ) 156 | { 157 | COSTELLA_FUNDAMENTAL_ERROR( "Null ppwc" ); 158 | COSTELLA_RETURN; 159 | } 160 | 161 | if( *ppwc ) 162 | { 163 | COSTELLA_FUNDAMENTAL_ERROR( "Used ppwc" ); 164 | COSTELLA_RETURN; 165 | } 166 | } 167 | #endif 168 | 169 | 170 | /* Create the object. 171 | */ 172 | 173 | if( COSTELLA_MALLOC( pwc, 1 ) ) 174 | { 175 | COSTELLA_FUNDAMENTAL_ERROR( "Allocating" ); 176 | COSTELLA_RETURN; 177 | } 178 | 179 | 180 | /* Store pointer. 181 | */ 182 | 183 | *ppwc = pwc; 184 | 185 | 186 | /* Store information. 187 | */ 188 | 189 | pwc->pfCallback = pfCallback; 190 | pwc->pvPassback = pvPassback; 191 | } 192 | COSTELLA_END_FUNCTION 193 | 194 | 195 | 196 | /* CostellaWrapCallbackDelete: 197 | ** 198 | ** Delete a COSTELLA_WRAP_CALLBACK object. 199 | ** 200 | ** ppwp: Pointer to pointer to the COSTELLA_WRAP_CALLBACK object. 201 | */ 202 | 203 | COSTELLA_FUNCTION( CostellaWrapCallbackDelete, ( COSTELLA_WRAP_CALLBACK** 204 | ppwc ) ) 205 | { 206 | COSTELLA_WRAP_CALLBACK* pwc; 207 | 208 | 209 | /* Check initialization and pointers. 210 | */ 211 | 212 | #ifdef COSTELLA_DEBUG 213 | { 214 | if( !gbInitialized ) 215 | { 216 | COSTELLA_FUNDAMENTAL_ERROR( "Initialization" ); 217 | COSTELLA_RETURN; 218 | } 219 | 220 | if( !ppwc ) 221 | { 222 | COSTELLA_FUNDAMENTAL_ERROR( "Null ppwc" ); 223 | COSTELLA_RETURN; 224 | } 225 | } 226 | #endif 227 | 228 | 229 | /* Extract pointer. 230 | */ 231 | 232 | pwc = *ppwc; 233 | 234 | 235 | /* If the pointer is null, do nothing. 236 | */ 237 | 238 | if( !pwc ) 239 | { 240 | COSTELLA_RETURN; 241 | } 242 | 243 | 244 | /* Free the memory. 245 | */ 246 | 247 | if( COSTELLA_FREE( *ppwc ) ) 248 | { 249 | COSTELLA_FUNDAMENTAL_ERROR( "Freeing object" ); 250 | COSTELLA_RETURN; 251 | } 252 | } 253 | COSTELLA_END_FUNCTION 254 | 255 | 256 | 257 | /* CostellaWrapCallback: 258 | ** 259 | ** Callback function for wrapping an ANSI callback function. 260 | */ 261 | 262 | COSTELLA_FUNCTION( CostellaWrapCallback, ( COSTELLA_O* poPassback, 263 | COSTELLA_O* po ) ) 264 | { 265 | COSTELLA_WRAP_CALLBACK* pwc; 266 | int (*pfCallback)( void* pvPassback, void* pv ); 267 | void* pvPassback; 268 | 269 | 270 | /* Check initialization and pointers. 271 | */ 272 | 273 | #ifdef COSTELLA_DEBUG 274 | { 275 | if( !gbInitialized ) 276 | { 277 | COSTELLA_FUNDAMENTAL_ERROR( "Initialization" ); 278 | COSTELLA_RETURN; 279 | } 280 | 281 | if( !poPassback ) 282 | { 283 | COSTELLA_FUNDAMENTAL_ERROR( "Null poPassback" ); 284 | COSTELLA_RETURN; 285 | } 286 | } 287 | #endif 288 | 289 | 290 | /* Cast pointer. 291 | */ 292 | 293 | pwc = (COSTELLA_WRAP_CALLBACK*) poPassback; 294 | 295 | 296 | /* Extract information. 297 | */ 298 | 299 | pfCallback = pwc->pfCallback; 300 | pvPassback = pwc->pvPassback; 301 | 302 | 303 | /* Now call the ANSI callback function. 304 | */ 305 | 306 | if( pfCallback && !pfCallback( pvPassback, (void*) po ) ) 307 | { 308 | COSTELLA_ERROR( "Abort signaled by ANSI callback function; no further " 309 | "information available through this channel" ); 310 | COSTELLA_RETURN; 311 | } 312 | } 313 | COSTELLA_END_FUNCTION 314 | 315 | 316 | 317 | /* CostellaWrapProgress: 318 | ** 319 | ** Callback function for wrapping an ANSI progress callback function. 320 | */ 321 | 322 | COSTELLA_FUNCTION( CostellaWrapProgress, ( COSTELLA_O* poPassback ) ) 323 | { 324 | COSTELLA_WRAP_PROGRESS* pwp; 325 | int (*pfProgress)( void* pvPassback ); 326 | void* pvPassback; 327 | 328 | 329 | /* Check initialization and pointers. 330 | */ 331 | 332 | #ifdef COSTELLA_DEBUG 333 | { 334 | if( !gbInitialized ) 335 | { 336 | COSTELLA_FUNDAMENTAL_ERROR( "Initialization" ); 337 | COSTELLA_RETURN; 338 | } 339 | 340 | if( !poPassback ) 341 | { 342 | COSTELLA_FUNDAMENTAL_ERROR( "Null poPassback" ); 343 | COSTELLA_RETURN; 344 | } 345 | } 346 | #endif 347 | 348 | 349 | /* Cast pointer. 350 | */ 351 | 352 | pwp = (COSTELLA_WRAP_PROGRESS*) poPassback; 353 | 354 | 355 | /* Extract information. 356 | */ 357 | 358 | pfProgress = pwp->pfProgress; 359 | 360 | 361 | /* If there is no progress callback function, do nothing more. 362 | */ 363 | 364 | if( !pfProgress ) 365 | { 366 | COSTELLA_RETURN; 367 | } 368 | 369 | 370 | /* Extract information. 371 | */ 372 | 373 | pvPassback = pwp->pvPassback; 374 | 375 | 376 | /* Now call the ANSI progress callback function. 377 | */ 378 | 379 | if( !pfProgress( pvPassback ) ) 380 | { 381 | COSTELLA_ERROR( "Progress aborted by ANSI application's progress " 382 | "function; no further information available through this channel" ); 383 | COSTELLA_RETURN; 384 | } 385 | } 386 | COSTELLA_END_FUNCTION 387 | 388 | 389 | 390 | /* CostellaWrapNewCopy: 391 | ** 392 | ** Callback function for wrapping an ANSI copy creator. 393 | */ 394 | 395 | COSTELLA_FUNCTION( CostellaWrapNewCopy, ( COSTELLA_O** 396 | ppoNewCopy, COSTELLA_O* poExisting, COSTELLA_O* poPassback ) ) 397 | { 398 | COSTELLA_WRAP_FUNCTION_POINTER* pwfp; 399 | void* (*pfNewCopy)( void* pvExisting ); 400 | 401 | 402 | /* Check initialization and pointers. 403 | */ 404 | 405 | #ifdef COSTELLA_DEBUG 406 | { 407 | if( !gbInitialized ) 408 | { 409 | COSTELLA_FUNDAMENTAL_ERROR( "Initialization" ); 410 | COSTELLA_RETURN; 411 | } 412 | 413 | if( !ppoNewCopy ) 414 | { 415 | COSTELLA_FUNDAMENTAL_ERROR( "Null ppoNewCopy" ); 416 | COSTELLA_RETURN; 417 | } 418 | 419 | if( *ppoNewCopy ) 420 | { 421 | COSTELLA_FUNDAMENTAL_ERROR( "Used ppoNewCopy" ); 422 | COSTELLA_RETURN; 423 | } 424 | 425 | if( !poExisting ) 426 | { 427 | COSTELLA_FUNDAMENTAL_ERROR( "Null poExisting" ); 428 | COSTELLA_RETURN; 429 | } 430 | 431 | if( !poPassback ) 432 | { 433 | COSTELLA_FUNDAMENTAL_ERROR( "Null poPassback" ); 434 | COSTELLA_RETURN; 435 | } 436 | } 437 | #endif 438 | 439 | 440 | /* Cast pointer. 441 | */ 442 | 443 | pwfp = (COSTELLA_WRAP_FUNCTION_POINTER*) poPassback; 444 | 445 | 446 | /* Extract function pointer. 447 | */ 448 | 449 | pfNewCopy = (void* (*)( void* )) pwfp->pf; 450 | 451 | 452 | /* Now call the ANSI copy creator. 453 | */ 454 | 455 | if( !( *ppoNewCopy = pfNewCopy( (void*) poExisting ) ) ) 456 | { 457 | COSTELLA_ERROR( "ANSI application's copy creator failed; no further " 458 | "information available through this channel" ); 459 | COSTELLA_RETURN; 460 | } 461 | } 462 | COSTELLA_END_FUNCTION 463 | 464 | 465 | 466 | /* CostellaWrapDelete: 467 | ** 468 | ** Callback function for wrapping an ANSI destructor. 469 | */ 470 | 471 | COSTELLA_FUNCTION( CostellaWrapDelete, ( COSTELLA_O** ppo, COSTELLA_O* 472 | poPassback ) ) 473 | { 474 | COSTELLA_O* po; 475 | COSTELLA_WRAP_FUNCTION_POINTER* pwfp; 476 | int (*pfDelete)( void* pv ); 477 | 478 | 479 | /* Check initialization and pointers. 480 | */ 481 | 482 | #ifdef COSTELLA_DEBUG 483 | { 484 | if( !gbInitialized ) 485 | { 486 | COSTELLA_FUNDAMENTAL_ERROR( "Initialization" ); 487 | COSTELLA_RETURN; 488 | } 489 | 490 | if( !ppo ) 491 | { 492 | COSTELLA_FUNDAMENTAL_ERROR( "Null ppo" ); 493 | COSTELLA_RETURN; 494 | } 495 | 496 | if( !poPassback ) 497 | { 498 | COSTELLA_FUNDAMENTAL_ERROR( "Null poPassback" ); 499 | COSTELLA_RETURN; 500 | } 501 | } 502 | #endif 503 | 504 | 505 | /* Extract object pointer. 506 | */ 507 | 508 | po = *ppo; 509 | 510 | 511 | /* If it is null, do nothing. 512 | */ 513 | 514 | if( !po ) 515 | { 516 | COSTELLA_RETURN; 517 | } 518 | 519 | 520 | /* Cast pointer. 521 | */ 522 | 523 | pwfp = (COSTELLA_WRAP_FUNCTION_POINTER*) poPassback; 524 | 525 | 526 | /* Extract function pointer. 527 | */ 528 | 529 | pfDelete = (int (*)( void* )) pwfp->pf; 530 | 531 | 532 | /* Now call the ANSI destructor. 533 | */ 534 | 535 | if( !pfDelete( (void*) po ) ) 536 | { 537 | COSTELLA_ERROR( "ANSI application's destructor failed; no further " 538 | "information available through this channel" ); 539 | COSTELLA_RETURN; 540 | } 541 | } 542 | COSTELLA_END_FUNCTION 543 | 544 | 545 | 546 | /* CostellaWrapCompare: 547 | ** 548 | ** Callback function for wrapping an ANSI comparator. 549 | */ 550 | 551 | COSTELLA_FUNCTION( CostellaWrapCompare, ( COSTELLA_SB* psbCompare, 552 | COSTELLA_O* po1, COSTELLA_O* po2, COSTELLA_O* poPassback ) ) 553 | { 554 | COSTELLA_WRAP_FUNCTION_POINTER* pwfp; 555 | int (*pfCompare)( void* pv1, void* pv2 ); 556 | 557 | 558 | /* Check initialization and pointers. 559 | */ 560 | 561 | #ifdef COSTELLA_DEBUG 562 | { 563 | if( !gbInitialized ) 564 | { 565 | COSTELLA_FUNDAMENTAL_ERROR( "Initialization" ); 566 | COSTELLA_RETURN; 567 | } 568 | 569 | if( !psbCompare ) 570 | { 571 | COSTELLA_FUNDAMENTAL_ERROR( "Null psbCompare" ); 572 | COSTELLA_RETURN; 573 | } 574 | 575 | if( !po1 ) 576 | { 577 | COSTELLA_FUNDAMENTAL_ERROR( "Null po1" ); 578 | COSTELLA_RETURN; 579 | } 580 | 581 | if( !po2 ) 582 | { 583 | COSTELLA_FUNDAMENTAL_ERROR( "Null po2" ); 584 | COSTELLA_RETURN; 585 | } 586 | 587 | if( !poPassback ) 588 | { 589 | COSTELLA_FUNDAMENTAL_ERROR( "Null poPassback" ); 590 | COSTELLA_RETURN; 591 | } 592 | } 593 | #endif 594 | 595 | 596 | /* Cast pointer. 597 | */ 598 | 599 | pwfp = (COSTELLA_WRAP_FUNCTION_POINTER*) poPassback; 600 | 601 | 602 | /* Extract function pointer. 603 | */ 604 | 605 | pfCompare = (int (*)( void*, void* )) pwfp->pf; 606 | 607 | 608 | /* Now call the ANSI comparator. 609 | */ 610 | 611 | *psbCompare = (COSTELLA_SB) pfCompare( (void*) po1, (void*) po2 ); 612 | } 613 | COSTELLA_END_FUNCTION 614 | 615 | 616 | 617 | /* Copyright (c) 2006-2007 John P. Costella. 618 | ** 619 | ** End of file. 620 | */ 621 | -------------------------------------------------------------------------------- /costella/costella_base.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 1989-2007 John P. Costella. 2 | ** 3 | ** Permission is hereby granted, free of charge, to any person obtaining a 4 | ** copy of this software and associated documentation files (the "Software") 5 | ** to deal in the Software without restriction, including without limitation 6 | ** the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | ** and/or sell copies of the Software, and to permit persons to whom the 8 | ** Software is furnished to do so, subject to the following conditions: 9 | ** 10 | ** The above copyright notice and this permission notice shall be included 11 | ** in all copies or substantial portions of the Software. 12 | ** 13 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 15 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. 16 | ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER 17 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING 18 | ** FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | ** DEALINGS IN THE SOFTWARE. 20 | ** 21 | ** 22 | ** costella_base.h: 23 | ** 24 | ** Header file for costella_base.c. 25 | ** 26 | ** This version: November 4, 2007. 27 | ** 28 | ** Written in ANSI C. 29 | */ 30 | 31 | 32 | 33 | /* Include file only once. 34 | */ 35 | 36 | #ifndef _COSTELLA_BASE_H_ 37 | #define _COSTELLA_BASE_H_ 38 | 39 | 40 | 41 | /* Include files. 42 | */ 43 | 44 | #include "costella_types.h" 45 | #include "costella_debug.h" 46 | #include 47 | 48 | 49 | 50 | /* Public interface. 51 | */ 52 | 53 | int costella_base_initialize( void* (*pfMalloc)( unsigned int uiNumBytes ), 54 | void* (*pfRealloc)( void* pv, unsigned int uiNewNumBytes ), int (*pfFree)( 55 | void* pv ), FILE* pfileError ); 56 | int costella_base_finalize( FILE* pfileError ); 57 | 58 | 59 | 60 | /* Definitions convenient for clarity. 61 | */ 62 | 63 | #define COSTELLA_FALSE 0 64 | #define COSTELLA_TRUE (!COSTELLA_FALSE) 65 | 66 | 67 | 68 | /* COSTELLA_MALLOC: 69 | ** 70 | ** Standardized interface to the memory allocation function registered in 71 | ** CostellaBaseInitialize(). 72 | ** 73 | ** lpo: Pointer to the allocated memory, once allocated. 74 | ** 75 | ** lmc: Number of objects to allocate. 76 | ** 77 | ** Evaluates to the failure flag. 78 | */ 79 | 80 | #define COSTELLA_MALLOC( lpo, lmc ) \ 81 | ( (lpo) ? COSTELLA_TRUE : !( (lpo) = gpfCostellaBaseMalloc( ( (lmc) ? \ 82 | (COSTELLA_MC) (lmc) : 1 ) * (COSTELLA_MC) sizeof( *(lpo) ) ) ) ) 83 | 84 | 85 | 86 | /* COSTELLA_REALLOC: 87 | ** 88 | ** Standardized interface to the memory reallocation function registered 89 | ** in CostellaBaseInitialize(). 90 | ** 91 | ** lpo: Pointer previously allocated, to be reallocated. 92 | ** 93 | ** lmc: Number of objects to reallocate. 94 | ** 95 | ** Evaluates to the failure flag. 96 | */ 97 | 98 | #define COSTELLA_REALLOC( lpo, lmc ) \ 99 | ( !(lpo) ? COSTELLA_TRUE : !( (lpo) = gpfCostellaBaseRealloc( (lpo), ( \ 100 | (lmc) ? (COSTELLA_MC) (lmc) : 1 ) * (COSTELLA_MC) sizeof( *(lpo) ) ) ) ) 101 | 102 | 103 | 104 | /* COSTELLA_FREE: 105 | ** 106 | ** Standardized interface to the memory freeing function registered in 107 | ** CostellaBaseInitialize(). Only frees the pointer if it is non-null. 108 | ** 109 | ** lpo: Pointer to the memory to free. 110 | ** 111 | ** Evaluates to the failure flag. 112 | */ 113 | 114 | #define COSTELLA_FREE( lpo ) \ 115 | ( (lpo) = (lpo) ? ( gpfCostellaBaseFree( (lpo) ) ? 0 : (lpo) ) : 0 ) 116 | 117 | 118 | 119 | /* COSTELLA_MALLOC_OFFSET: 120 | ** 121 | ** Allocate memory for an offset array. 122 | ** 123 | ** lpo: Offset pointer to the allocated memory, once allocated. 124 | ** 125 | ** lmi{Min,Max}: {Min,Max}imum offset required. 126 | ** 127 | ** Evaluates to the failure flag. 128 | */ 129 | 130 | #define COSTELLA_MALLOC_OFFSET( lpo, lmiMin, lmiMax ) \ 131 | ( (lpo) || (COSTELLA_MI) (lmiMin) > (COSTELLA_MI) (lmiMax) ? \ 132 | COSTELLA_TRUE : ( ( (lpo) = gpfCostellaBaseMalloc( (COSTELLA_MC) ( \ 133 | (COSTELLA_MI) (lmiMax) - (COSTELLA_MI) (lmiMin) + 1 ) * (COSTELLA_MC) \ 134 | sizeof( *(lpo) ) ) ) ? ( (lpo) -= (lmiMin), COSTELLA_FALSE ) : \ 135 | COSTELLA_TRUE ) ) 136 | 137 | 138 | 139 | /* COSTELLA_REALLOC_OFFSET: 140 | ** 141 | ** Reallocate memory for an offset array. 142 | ** 143 | ** lpo: Pointer previously allocated, to be reallocated. 144 | ** 145 | ** lmi{Min,Max}{Old,New}: {Old,New} {min,max}imum offset. 146 | ** 147 | ** Evaluates to the failure flag. 148 | */ 149 | 150 | #define COSTELLA_REALLOC_OFFSET( lpo, lmiMinOld, lmiMinNew, lmiMaxNew ) \ 151 | ( (!lpo) || (lmiMinNew) > (lmiMaxNew) ? COSTELLA_TRUE : ( (lpo) = \ 152 | gpfCostellaBaseRealloc( (lpo) + (lmiMinOld), (COSTELLA_MC) ( (lmiMaxNew) \ 153 | - (lmiMinNew) + 1 ) * (COSTELLA_MC) sizeof( *(lpo) ) ) ) ? ( (lpo) -= \ 154 | (lmiMinNew), COSTELLA_FALSE ) : COSTELLA_TRUE ) 155 | 156 | 157 | 158 | /* COSTELLA_FREE_OFFSET: 159 | ** 160 | ** Free memory allocated with COSTELLA_MALLOC_OFFSET. Only frees the 161 | ** pointer if it is non-null. 162 | ** 163 | ** lpo: Pointer returned by COSTELLA_MALLOC_OFFSET. 164 | ** 165 | ** lmiMin: Minimum offset specified in COSTELLA_MALLOC_OFFSET. 166 | ** 167 | ** Evaluates to the failure flag. 168 | */ 169 | 170 | #define COSTELLA_FREE_OFFSET( lpo, lmiMin ) \ 171 | ( (lpo) = (lpo) ? ( gpfCostellaBaseFree( (lpo) + (lmiMin) ) ? 0 : (lpo) \ 172 | ) : COSTELLA_FALSE ) 173 | 174 | 175 | 176 | /* COSTELLA_INITIALIZE_ARRAY: 177 | ** 178 | ** Initialize an array to zero. 179 | ** 180 | ** lax: Array pointer. 181 | ** 182 | ** lmcLength: Length of the array. 183 | ** 184 | ** ltype: Type of object being initialized. 185 | */ 186 | 187 | #define COSTELLA_INITIALIZE_ARRAY( lax, lmcLength, ltype ) \ 188 | { \ 189 | ltype* lpx; \ 190 | ltype* lpxEnd; \ 191 | \ 192 | for( lpx = (lax), lpxEnd = lpx + (lmcLength); lpx != lpxEnd; lpx++ ) \ 193 | { \ 194 | *lpx = 0; \ 195 | } \ 196 | } 197 | 198 | 199 | 200 | /* COSTELLA_INITIALIZE_OFFSET_ARRAY: 201 | ** 202 | ** Initialize an offset array to zero. 203 | ** 204 | ** lax: Array pointer. 205 | ** 206 | ** lmi{Min,Max}: {Min,Max}imum offset. 207 | ** 208 | ** ltype: Type of object being initialized. 209 | ** 210 | ** Inline macro. 211 | */ 212 | 213 | #define COSTELLA_INITIALIZE_OFFSET_ARRAY( lax, lmiMin, lmiMax, ltype ) \ 214 | { \ 215 | ltype* lpx; \ 216 | ltype* lpxLast; \ 217 | \ 218 | for( lpx = (lax) + lmiMin, lpxLast = (lax) + lmiMax; lpx <= lpxLast; \ 219 | lpx++ ) \ 220 | { \ 221 | *lpx = 0; \ 222 | } \ 223 | } 224 | 225 | 226 | 227 | /* COSTELLA_SHIFT_RIGHT_TOWARDS_ZERO: 228 | ** 229 | ** Fast division macro that uses the right bit-shift operation. Shifting 230 | ** right "towards zero" means that the absolute value of the result is 231 | ** never greater than that of the true (fractional) division. 232 | ** 233 | ** lsx: Number to be divided. 234 | ** 235 | ** lubNumBits: Number of bits to shift it right. 236 | */ 237 | 238 | #define COSTELLA_SHIFT_RIGHT_TOWARDS_ZERO( lsx, lubNumBits ) \ 239 | ( (lsx) < 0 ? -( -(lsx) >> (lubNumBits) ) : (lsx) >> (lubNumBits) ) 240 | 241 | 242 | 243 | /* COSTELLA_SHIFT_RIGHT_FLOOR: 244 | ** 245 | ** Fast division macro that use the right bit-shift operation. 246 | ** 247 | ** The result is not greater than the true (fractional) division, ie, is 248 | ** not to the right of it on the number line. 249 | ** 250 | ** lsx: Number to be divided. 251 | ** 252 | ** lubNumBits: Number of bits to shift it right. 253 | */ 254 | 255 | #ifdef COSTELLA_SHIFT_RIGHT_IS_SIGNED 256 | 257 | #define COSTELLA_SHIFT_RIGHT_FLOOR( lsx, lubNumBits ) \ 258 | ( (lsx) >> (lubNumBits) ) 259 | 260 | #else 261 | 262 | #define COSTELLA_SHIFT_RIGHT_FLOOR( lsx, lubNumBits ) \ 263 | ( (lsx) < 0 ? -1 - ( ( -1 - (lsx) ) >> (lubNumBits) ) : (lsx) >> \\ 264 | (lubNumBits) ) 265 | 266 | #endif 267 | 268 | 269 | 270 | /* Function definition, flow, and error-handling procedures. Start with the 271 | ** error node structure. 272 | */ 273 | 274 | typedef struct COSTELLA_ERROR_NODE_tag 275 | { 276 | COSTELLA_B bAllocated; 277 | COSTELLA_C* acFunctionName, * acError, * acCleanupError; 278 | struct COSTELLA_ERROR_NODE_tag* penNext, * penCleanupNext; 279 | } 280 | COSTELLA_ERROR_NODE; 281 | 282 | 283 | 284 | /* COSTELLA_FUNCTION: 285 | ** 286 | ** Declare a function. Definition of such a function requires that 287 | ** costella_body.h be first included, which redefines this macro. 288 | */ 289 | 290 | #define COSTELLA_FUNCTION( lfFunctionName, larglist ) \ 291 | COSTELLA_ERROR_NODE* lfFunctionName larglist; 292 | 293 | 294 | 295 | /* COSTELLA_END_FUNCTION: 296 | ** 297 | ** End a function. 298 | */ 299 | 300 | #define COSTELLA_END_FUNCTION \ 301 | \ 302 | COSTELLA_DELETE_DAUGHTERS; \ 303 | return 0; \ 304 | } \ 305 | i_l_bCostellaError++; \ 306 | } 307 | 308 | 309 | 310 | /* COSTELLA_ANSI_FUNCTION: 311 | ** 312 | ** Declare an "ANSI" function, i.e. one that does not follow the function 313 | ** paradigm of the Costella libraries, but which must call such functions 314 | ** and be able to use the error-handling functionality built into them. 315 | ** Definition of such a function requires that costella_body.h be first 316 | ** included, which redefines this macro. 317 | */ 318 | 319 | #define COSTELLA_ANSI_FUNCTION( lfFunctionName, returntype, larglist ) \ 320 | returntype lfFunctionName larglist; 321 | 322 | 323 | 324 | /* COSTELLA_END_ANSI_FUNCTION: 325 | ** 326 | ** End a function. 327 | */ 328 | 329 | #define COSTELLA_END_ANSI_FUNCTION( returnvalue ) \ 330 | \ 331 | COSTELLA_DELETE_DAUGHTERS; \ 332 | return (returnvalue); \ 333 | } \ 334 | i_l_bCostellaError++; \ 335 | } 336 | 337 | 338 | 339 | /* COSTELLA_END_ANSI_FUNCTION_NO_RETURN_VALUE: 340 | ** 341 | ** End a function that has no return value. 342 | */ 343 | 344 | #define COSTELLA_END_ANSI_FUNCTION_NO_RETURN_VALUE \ 345 | \ 346 | COSTELLA_DELETE_DAUGHTERS; \ 347 | return; \ 348 | } \ 349 | i_l_bCostellaError++; \ 350 | } 351 | 352 | 353 | 354 | /* COSTELLA_FUNCTION_POINTER: 355 | ** 356 | ** Declare or define a pointer to a COSTELLA_FUNCTION. 357 | */ 358 | 359 | #define COSTELLA_FUNCTION_POINTER( lpf, larglist ) \ 360 | COSTELLA_ERROR_NODE* (*lpf) larglist 361 | 362 | 363 | 364 | /* COSTELLA_RETURN: 365 | ** 366 | ** Return from a function. If there has been no error, return null. 367 | ** Otherwise, try to allocate memory for a copy of the error node, and 368 | ** copy it. If the allocation fails, use the static automatic copy, but 369 | ** delete its daughter nodes to avoid re-entrant problems. 370 | */ 371 | 372 | #define COSTELLA_RETURN \ 373 | { \ 374 | if( i_l_bCostellaError ) \ 375 | { \ 376 | COSTELLA_ERROR_NODE* i_l_pen = 0; \ 377 | \ 378 | if( COSTELLA_MALLOC( i_l_pen, 1 ) ) \ 379 | { \ 380 | COSTELLA_DELETE_DAUGHTERS; \ 381 | i_l_enCostella.bAllocated = COSTELLA_FALSE; \ 382 | return &i_l_enCostella; \ 383 | } \ 384 | else \ 385 | { \ 386 | *i_l_pen = i_l_enCostella; \ 387 | i_l_pen->bAllocated = COSTELLA_TRUE; \ 388 | return i_l_pen; \ 389 | } \ 390 | } \ 391 | COSTELLA_DELETE_DAUGHTERS; \ 392 | return 0; \ 393 | } \ 394 | 395 | 396 | 397 | /* COSTELLA_ANSI_RETURN: 398 | ** 399 | ** Return from an ANSI function that has a non-void return type. 400 | */ 401 | 402 | #define COSTELLA_ANSI_RETURN( returnvalue ) \ 403 | \ 404 | COSTELLA_DELETE_DAUGHTERS; \ 405 | return (returnvalue); \ 406 | 407 | 408 | 409 | /* COSTELLA_ANSI_RETURN_NO_VALUE: 410 | ** 411 | ** Return from an ANSI function that has a void return type. 412 | */ 413 | 414 | #define COSTELLA_ANSI_RETURN_NO_VALUE \ 415 | \ 416 | COSTELLA_DELETE_DAUGHTERS; \ 417 | return; \ 418 | 419 | 420 | 421 | /* COSTELLA_FUNDAMENTAL_ERROR: 422 | ** 423 | ** Macro for registering a fundamental error, i.e., one that has no 424 | ** daughter error tree. 425 | */ 426 | 427 | #define COSTELLA_FUNDAMENTAL_ERROR( lacError ) \ 428 | COSTELLA_DELETE_DAUGHTERS; \ 429 | COSTELLA_ERROR( lacError ); \ 430 | 431 | 432 | 433 | /* COSTELLA_CALL: 434 | ** 435 | ** Macro for calling a function and automatically handling the error 436 | ** structure. 437 | */ 438 | 439 | #define COSTELLA_CALL( lcall ) \ 440 | ( COSTELLA_DELETE_DAUGHTERS, i_l_enCostella.penNext = lcall ) 441 | 442 | 443 | 444 | /* COSTELLA_ERROR: 445 | ** 446 | ** Macro for registering an error string after a COSTELLA_CALL(). 447 | */ 448 | 449 | #define COSTELLA_ERROR( lacError ) \ 450 | i_l_bCostellaError = COSTELLA_TRUE; \ 451 | i_l_enCostella.acError = lacError; 452 | 453 | 454 | 455 | /* COSTELLA_CLEANUP_FUNDAMENTAL_ERROR: 456 | ** 457 | ** Macro for registering a fundamental error encountered during cleanup. 458 | */ 459 | 460 | #define COSTELLA_CLEANUP_FUNDAMENTAL_ERROR( lacError ) \ 461 | COSTELLA_DELETE_CLEANUP_DAUGHTER; \ 462 | COSTELLA_CLEANUP_ERROR( lacError ); 463 | 464 | 465 | 466 | /* COSTELLA_CLEANUP_CALL: 467 | ** 468 | ** Macro for calling a function while cleaning up from another error. 469 | */ 470 | 471 | #define COSTELLA_CLEANUP_CALL( lcall ) \ 472 | ( COSTELLA_DELETE_CLEANUP_DAUGHTER, i_l_enCostella.penCleanupNext = \ 473 | lcall ) 474 | 475 | 476 | 477 | /* COSTELLA_CLEANUP_ERROR: 478 | ** 479 | ** Macro for registering an error string after a COSTELLA_CLEANUP_CALL(). 480 | */ 481 | 482 | #define COSTELLA_CLEANUP_ERROR( lacError ) \ 483 | i_l_bCostellaError = COSTELLA_TRUE; \ 484 | i_l_enCostella.acCleanupError = lacError; \ 485 | 486 | 487 | 488 | /* COSTELLA_DELETE_DAUGHTERS: 489 | ** 490 | ** Macro used internally to delete the daughter error trees if they have 491 | ** been allocated. 492 | */ 493 | 494 | #define COSTELLA_DELETE_DAUGHTERS \ 495 | ( i_l_enCostella.penNext ? (void) costella_base_error_node_delete( \ 496 | &i_l_enCostella.penNext ) : (void) COSTELLA_DELETE_CLEANUP_DAUGHTER ) 497 | 498 | 499 | 500 | /* COSTELLA_DELETE_CLEANUP_DAUGHTER: 501 | ** 502 | ** Macro used internally to delete the cleanup daughter error tree if it 503 | ** has been allocated. 504 | */ 505 | 506 | #define COSTELLA_DELETE_CLEANUP_DAUGHTER \ 507 | ( i_l_enCostella.penCleanupNext ? (void) \ 508 | costella_base_error_node_delete( &i_l_enCostella.penCleanupNext ) : \ 509 | (void) 0 ) 510 | 511 | 512 | 513 | /* COSTELLA_IGNORE_ERRORS: 514 | ** 515 | ** Macro for specifying that trapped errors should be ignored. 516 | */ 517 | 518 | #define COSTELLA_IGNORE_ERRORS \ 519 | COSTELLA_DELETE_DAUGHTERS 520 | 521 | 522 | 523 | /* COSTELLA_IGNORE_CLEANUP_ERROR: 524 | ** 525 | ** Macro for specifying that a trapped cleanup error should be ignored. 526 | */ 527 | 528 | #define COSTELLA_IGNORE_CLEANUP_ERROR \ 529 | COSTELLA_DELETE_CLEANUP_DAUGHTER 530 | 531 | 532 | 533 | /* COSTELLA_ERROR_ROOT_NODE: 534 | ** 535 | ** Alias for the root node of the error tree. 536 | */ 537 | 538 | #define COSTELLA_ERROR_ROOT_NODE \ 539 | (i_l_enCostella.penNext) 540 | 541 | 542 | 543 | /* COSTELLA_ERROR_FPRINT: 544 | ** 545 | ** Print the error chain to a file. 546 | */ 547 | 548 | #define COSTELLA_ERROR_FPRINT( pfile ) \ 549 | costella_base_error_fprint( (pfile), COSTELLA_ERROR_ROOT_NODE, 0, 0 ) 550 | 551 | 552 | 553 | /* COSTELLA_ERROR_APP_FPRINT: 554 | ** 555 | ** Print the error chain to a file, with application information. 556 | */ 557 | 558 | #define COSTELLA_ERROR_APP_FPRINT( pfile, lacApplicationName, \ 559 | lacApplicationError ) \ 560 | costella_base_error_fprint( (pfile), COSTELLA_ERROR_ROOT_NODE, \ 561 | (lacApplicationName), (lacApplicationError) ) 562 | 563 | 564 | 565 | /* Function prototypes. 566 | */ 567 | 568 | COSTELLA_FUNCTION( CostellaBaseInitialize, ( COSTELLA_O* (*pfMalloc)( 569 | COSTELLA_MC mc ), COSTELLA_O* (*pfRealloc)( COSTELLA_O* po, COSTELLA_MC mc 570 | ), COSTELLA_B (*pfFree)( COSTELLA_O* po ) ) ) 571 | COSTELLA_FUNCTION( CostellaBaseFinalize, ( void ) ) 572 | 573 | void costella_base_error_fprint( FILE* pfile, COSTELLA_ERROR_NODE* penRoot, 574 | COSTELLA_C* acApplicationName, COSTELLA_C* acApplicationError ); 575 | void costella_base_sprint_error_tree( COSTELLA_C* ac, COSTELLA_ERROR_NODE* 576 | penRoot ); 577 | void costella_base_error_node_delete( COSTELLA_ERROR_NODE** ppen ); 578 | 579 | 580 | 581 | /* Callback function typedef. 582 | */ 583 | 584 | typedef COSTELLA_ERROR_NODE* (*COSTELLA_CALLBACK_FUNCTION)( COSTELLA_O* 585 | poPassback ); 586 | 587 | 588 | 589 | /* Declaration of global variables defined in costella_base.c. 590 | */ 591 | 592 | #ifndef _COSTELLA_BASE_C_ 593 | 594 | extern COSTELLA_O* (*gpfCostellaBaseMalloc)( COSTELLA_MC mc ); 595 | extern COSTELLA_O* (*gpfCostellaBaseRealloc)( COSTELLA_O* po, COSTELLA_MC 596 | mc ); 597 | extern COSTELLA_B (*gpfCostellaBaseFree)( COSTELLA_O* po ); 598 | 599 | #endif 600 | 601 | 602 | 603 | /* File is now included. 604 | */ 605 | 606 | #endif 607 | 608 | 609 | 610 | /* Copyright (c) 1989-2007 John P. Costella. 611 | ** 612 | ** End of file. 613 | */ 614 | -------------------------------------------------------------------------------- /costella/costella_base.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 1989-2007 John P. Costella. 2 | ** 3 | ** Permission is hereby granted, free of charge, to any person obtaining a 4 | ** copy of this software and associated documentation files (the "Software") 5 | ** to deal in the Software without restriction, including without limitation 6 | ** the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | ** and/or sell copies of the Software, and to permit persons to whom the 8 | ** Software is furnished to do so, subject to the following conditions: 9 | ** 10 | ** The above copyright notice and this permission notice shall be included 11 | ** in all copies or substantial portions of the Software. 12 | ** 13 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 15 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. 16 | ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER 17 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING 18 | ** FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | ** DEALINGS IN THE SOFTWARE. 20 | ** 21 | ** 22 | ** costella_base.c: 23 | ** 24 | ** General functionality for the Costella libraries. 25 | ** 26 | ** Library begun: December 12, 1989. 27 | ** This version: October 10, 2007. 28 | ** 29 | ** Written in ANSI C. 30 | */ 31 | 32 | 33 | 34 | /* Flag to ensure correct declaration of global variables defined below. 35 | */ 36 | 37 | #define _COSTELLA_BASE_C_ 38 | 39 | 40 | 41 | /* Include file. 42 | */ 43 | 44 | #include "costella_base.h" 45 | #include 46 | 47 | 48 | 49 | /* Internal function prototypes. 50 | */ 51 | 52 | static COSTELLA_O* costella_base_malloc_ansi( COSTELLA_MC mc ); 53 | static COSTELLA_O* costella_base_realloc_ansi( COSTELLA_O* po, COSTELLA_MC 54 | mc ); 55 | static COSTELLA_B costella_base_free_ansi( COSTELLA_O* po ); 56 | 57 | static void costella_base_error_fprint_tree( FILE* pfile, 58 | COSTELLA_ERROR_NODE* pen, COSTELLA_UD udDepth, COSTELLA_UD udCleanup ); 59 | static void costella_base_sprint_error_tree_recurse( COSTELLA_C* ac, 60 | COSTELLA_ERROR_NODE* pen, COSTELLA_UD udDepth, COSTELLA_UD udCleanup ); 61 | 62 | 63 | 64 | /* Publicly available global variables. 65 | */ 66 | 67 | COSTELLA_O* (*gpfCostellaBaseMalloc)( COSTELLA_MC mc ) = 68 | costella_base_malloc_ansi; 69 | COSTELLA_O* (*gpfCostellaBaseRealloc)( COSTELLA_O* po, COSTELLA_MC mc ) = 70 | costella_base_realloc_ansi; 71 | COSTELLA_B (*gpfCostellaBaseFree)( COSTELLA_O* po ) = 72 | costella_base_free_ansi; 73 | 74 | 75 | 76 | /* Internal global variables. 77 | */ 78 | 79 | static COSTELLA_B gbInitialized = COSTELLA_FALSE; 80 | 81 | 82 | 83 | /* Start function bodies. 84 | */ 85 | 86 | #include "costella_body.h" 87 | 88 | 89 | 90 | /* costella_base_initialize: 91 | ** 92 | ** Public interface for initializing this library. 93 | ** 94 | ** pf{Malloc,Realloc,Free}: Pointer to function to be used for 95 | ** {allocating, reallocating, freeing} memory. 96 | */ 97 | 98 | COSTELLA_ANSI_FUNCTION( costella_base_initialize, int, ( void* (*pfMalloc)( 99 | unsigned int uiNumBytes ), void* (*pfRealloc)( void* pv, unsigned int 100 | uiNewNumBytes ), int (*pfFree)( void* pv ), FILE* pfileError ) ) 101 | { 102 | if( COSTELLA_CALL( CostellaBaseInitialize( pfMalloc, pfRealloc, pfFree ) ) 103 | ) 104 | { 105 | COSTELLA_ERROR_FPRINT( pfileError ); 106 | COSTELLA_ANSI_RETURN( 0 ); 107 | } 108 | } 109 | COSTELLA_END_ANSI_FUNCTION( !0 ) 110 | 111 | 112 | 113 | /* costella_base_finalize: 114 | ** 115 | ** Public interface for finalizing this library. Should not usually be 116 | ** used, becausee there is nothing in this library that is useful by 117 | ** itself. Included here for completeness. 118 | */ 119 | 120 | COSTELLA_ANSI_FUNCTION( costella_base_finalize, int, ( FILE* pfileError ) ) 121 | { 122 | if( COSTELLA_CALL( CostellaBaseFinalize() ) ) 123 | { 124 | COSTELLA_ERROR_FPRINT( pfileError ); 125 | COSTELLA_ANSI_RETURN( 0 ); 126 | } 127 | } 128 | COSTELLA_END_ANSI_FUNCTION( !0 ) 129 | 130 | 131 | 132 | /* CostellaBaseInitialize: 133 | ** 134 | ** Initialize the library. Repeated initialization is harmless. 135 | ** 136 | ** pfMalloc: Function to be used by all Costella libraries to allocate 137 | ** memory. Must return a pointer to the memory block, or null if the 138 | ** allocation fails. 139 | ** 140 | ** pfRealloc: Function to be used by all Costella libraries to reallocate 141 | ** memory allocated by pfMalloc. 142 | ** 143 | ** pfFree: Function to be used by all Costella libraries to free memory 144 | ** allocated by pfMalloc. 145 | */ 146 | 147 | COSTELLA_FUNCTION( CostellaBaseInitialize, ( COSTELLA_O* (*pfMalloc)( 148 | COSTELLA_MC mc ), COSTELLA_O* (*pfRealloc)( COSTELLA_O* po, COSTELLA_MC mc 149 | ), COSTELLA_B (*pfFree)( COSTELLA_O* po ) ) ) 150 | { 151 | COSTELLA_UB ubSizeMc, ubSizeMi; 152 | 153 | 154 | /* Do nothing if already initialized. 155 | */ 156 | 157 | if( gbInitialized ) 158 | { 159 | COSTELLA_RETURN; 160 | } 161 | 162 | 163 | /* Set initialized flag. 164 | */ 165 | 166 | gbInitialized = COSTELLA_TRUE; 167 | 168 | 169 | /* Store the function pointers for memory allocation, reallocation, and 170 | ** freeing. If these pointers are null, use the default ANSI functions 171 | */ 172 | 173 | if( !pfMalloc || !pfRealloc || !pfFree ) 174 | { 175 | gpfCostellaBaseMalloc = costella_base_malloc_ansi; 176 | gpfCostellaBaseRealloc = costella_base_realloc_ansi; 177 | gpfCostellaBaseFree = costella_base_free_ansi; 178 | } 179 | else 180 | { 181 | gpfCostellaBaseMalloc = pfMalloc; 182 | gpfCostellaBaseRealloc = pfRealloc; 183 | gpfCostellaBaseFree = pfFree; 184 | } 185 | 186 | 187 | /* Check that we have at least 32-bit memory addressing. 188 | */ 189 | 190 | ubSizeMc = (COSTELLA_UB) sizeof( COSTELLA_MC ); 191 | ubSizeMi = (COSTELLA_UB) sizeof( COSTELLA_MI ); 192 | 193 | if( ubSizeMc < 4 || ubSizeMi < 4 ) 194 | { 195 | gbInitialized = COSTELLA_FALSE; 196 | COSTELLA_FUNDAMENTAL_ERROR( "Memory model has less than 32 bits" ); 197 | COSTELLA_RETURN; 198 | } 199 | } 200 | COSTELLA_END_FUNCTION 201 | 202 | 203 | 204 | /* CostellaBaseFinalize: 205 | ** 206 | ** Finalize the library. 207 | */ 208 | 209 | COSTELLA_FUNCTION( CostellaBaseFinalize, ( void ) ) 210 | { 211 | /* Do nothing if not initialized. 212 | */ 213 | 214 | if( !gbInitialized ) 215 | { 216 | COSTELLA_RETURN; 217 | } 218 | 219 | 220 | /* Clear initialization flag. 221 | */ 222 | 223 | gbInitialized = COSTELLA_FALSE; 224 | 225 | 226 | /* Do something useless with hidden variable to keep compilers happy. 227 | */ 228 | 229 | i_l_enCostella.penNext = 0; 230 | } 231 | COSTELLA_END_FUNCTION 232 | 233 | 234 | 235 | /* costella_base_malloc_ansi: 236 | ** 237 | ** Memory allocation function, assuming nothing more than ANSI C. 238 | ** 239 | ** mc: Number of bytes to allocate. 240 | ** 241 | ** Returns pointer to the allocated memory, or null on failure. 242 | */ 243 | 244 | #include 245 | 246 | static COSTELLA_O* costella_base_malloc_ansi( COSTELLA_MC mc ) 247 | { 248 | return malloc( mc ); 249 | } 250 | 251 | 252 | 253 | /* costella_base_realloc_ansi: 254 | ** 255 | ** Memory reallocation function, assuming nothing more than ANSI C. 256 | ** 257 | ** po: Pointer to memory previously allocated using 258 | ** costella_base_malloc_ansi(). 259 | ** 260 | ** mc: New number of bytes to reallocate. 261 | ** 262 | ** Returns pointer to the reallocated memory, or null on failure. 263 | */ 264 | 265 | static COSTELLA_O* costella_base_realloc_ansi( COSTELLA_O* po, COSTELLA_MC 266 | mc ) 267 | { 268 | return realloc( po, mc ); 269 | } 270 | 271 | 272 | 273 | /* costella_base_free_ansi: 274 | ** 275 | ** Memory freeing function, assuming nothing more than ANSI C. 276 | ** 277 | ** po: Pointer to memory previously allocated using 278 | ** costella_base_malloc_ansi() or costella_base_realloc_ansi(). 279 | ** 280 | ** Always returns nonzero, indicating no error. 281 | */ 282 | 283 | static COSTELLA_B costella_base_free_ansi( COSTELLA_O* po ) 284 | { 285 | free( po ); 286 | 287 | return !0; 288 | } 289 | 290 | 291 | 292 | /* costella_base_error_fprint: 293 | ** 294 | ** Print an error tree to a file. 295 | ** 296 | ** pfile: Pointer to the ANSI file to write to. If null, then do nothing. 297 | ** 298 | ** penRoot: Pointer to the root COSTELLA_ERROR_NODE. 299 | ** 300 | ** acApplicationName: String pointer for an application name. If null, no 301 | ** application header is written, only the error tree. 302 | ** 303 | ** acApplicationError: String pointer for an application error 304 | ** description. If null, no application header is written, only the 305 | ** error tree. 306 | */ 307 | 308 | void costella_base_error_fprint( FILE* pfile, COSTELLA_ERROR_NODE* penRoot, 309 | COSTELLA_C* acApplicationName, COSTELLA_C* acApplicationError ) 310 | { 311 | /* If the file pointer is null, do nothing. 312 | */ 313 | 314 | if( !pfile ) 315 | { 316 | return; 317 | } 318 | 319 | 320 | /* Print the application information if it has been supplied. 321 | */ 322 | 323 | if( acApplicationName && acApplicationError ) 324 | { 325 | if( fprintf( pfile, "\nERROR:\n=====\nApplication name: " 326 | "%s\nApplication error: %s\n\n", acApplicationName, acApplicationError 327 | ) < 0 ) 328 | { 329 | return; 330 | } 331 | } 332 | 333 | 334 | /* If there is no root error node, do nothing more. 335 | */ 336 | 337 | if( !penRoot ) 338 | { 339 | return; 340 | } 341 | 342 | 343 | /* Print a spacer line if we had no application information. 344 | */ 345 | 346 | if( !acApplicationName || !acApplicationError ) 347 | { 348 | if( fprintf( pfile, "\n" ) < 0 ) 349 | { 350 | return; 351 | } 352 | } 353 | 354 | 355 | /* Print the error tree header. 356 | */ 357 | 358 | if( !acApplicationName || !acApplicationError ) 359 | { 360 | if( fprintf( pfile, 361 | "Costella library error tree:\n" 362 | "----------------------------\n" ) < 0 ) 363 | { 364 | return; 365 | } 366 | } 367 | else 368 | { 369 | if( fprintf( pfile, 370 | "AN ERROR OCCURRED: This is the costella library error tree:\n" 371 | "-----------------------------------------------------------\n" ) < 0 372 | ) 373 | { 374 | return; 375 | } 376 | } 377 | 378 | 379 | /* Print the error tree recursively. 380 | */ 381 | 382 | costella_base_error_fprint_tree( pfile, penRoot, 0, 0 ); 383 | } 384 | 385 | 386 | 387 | /* costella_base_error_fprint_tree: 388 | ** 389 | ** Internal, recursive function for printing an error tree to a file. 390 | ** 391 | ** pfile: Pointer to the FILE to print to. 392 | ** 393 | ** pen: Pointer to the current COSTELLA_ERROR_NODE. 394 | ** 395 | ** udDepth: Current depth. 396 | ** 397 | ** udCleanup: Current cleanup level. 398 | */ 399 | 400 | static void costella_base_error_fprint_tree( FILE* pfile, 401 | COSTELLA_ERROR_NODE* pen, COSTELLA_UD udDepth, COSTELLA_UD udCleanup ) 402 | { 403 | COSTELLA_UD ud; 404 | 405 | 406 | /* Check pointers. 407 | */ 408 | 409 | if( !pfile || !pen ) 410 | { 411 | return; 412 | } 413 | 414 | 415 | /* Print the indenting spaces. 416 | */ 417 | 418 | for( ud = 0; ud < udDepth; ud++ ) 419 | { 420 | if( fprintf( pfile, " " ) < 0 ) 421 | { 422 | return; 423 | } 424 | } 425 | 426 | 427 | /* Print the opening brackets for existing cleanup mode. 428 | */ 429 | 430 | for( ud = 0; ud < udCleanup; ud++ ) 431 | { 432 | if( fprintf( pfile, "[" ) < 0 ) 433 | { 434 | return; 435 | } 436 | } 437 | 438 | 439 | /* Print the function name and error string. 440 | */ 441 | 442 | if( fprintf( pfile, "%s: %s", pen->acFunctionName, pen->acError ? 443 | pen->acError : "CODING ERROR! Main error message not set before " 444 | "cleanup!" ) < 0 ) 445 | { 446 | return; 447 | } 448 | 449 | 450 | /* Print the closing brackets for existing cleanup mode. 451 | */ 452 | 453 | for( ud = 0; ud < udCleanup; ud++ ) 454 | { 455 | if( fprintf( pfile, "]" ) < 0 ) 456 | { 457 | return; 458 | } 459 | } 460 | 461 | 462 | /* Finish the line. 463 | */ 464 | 465 | if( fprintf( pfile, "\n" ) < 0 ) 466 | { 467 | return; 468 | } 469 | 470 | 471 | /* Check if this node has a next node. 472 | */ 473 | 474 | if( pen->penNext ) 475 | { 476 | /* It does. Do it. 477 | */ 478 | 479 | costella_base_error_fprint_tree( pfile, pen->penNext, udDepth + 1, 480 | udCleanup ); 481 | } 482 | 483 | 484 | /* Check if this node has a cleanup string, or if the node itself could 485 | ** not be allocated. 486 | */ 487 | 488 | if( pen->acCleanupError || !pen->bAllocated ) 489 | { 490 | /* It does. Increment cleanup level. 491 | */ 492 | 493 | udCleanup++; 494 | 495 | 496 | /* Print the indenting spaces. 497 | */ 498 | 499 | for( ud = 0; ud < udDepth; ud++ ) 500 | { 501 | if( fprintf( pfile, " " ) < 0 ) 502 | { 503 | return; 504 | } 505 | } 506 | 507 | 508 | /* Print the opening brackets for cleanup mode. 509 | */ 510 | 511 | for( ud = 0; ud < udCleanup; ud++ ) 512 | { 513 | if( fprintf( pfile, "[" ) < 0 ) 514 | { 515 | return; 516 | } 517 | } 518 | 519 | 520 | /* Print the function name and cleanup error string. 521 | */ 522 | 523 | if( pen->bAllocated ) 524 | { 525 | if( fprintf( pfile, "%s: %s", pen->acFunctionName, pen->acCleanupError 526 | ) < 0 ) 527 | { 528 | return; 529 | } 530 | } 531 | else 532 | { 533 | if( fprintf( pfile, "%s: OUT OF MEMORY! Daughter error trees " 534 | "deleted!", pen->acFunctionName ) < 0 ) 535 | { 536 | return; 537 | } 538 | } 539 | 540 | 541 | /* Print the closing brackets for cleanup mode. 542 | */ 543 | 544 | for( ud = 0; ud < udCleanup; ud++ ) 545 | { 546 | if( fprintf( pfile, "]" ) < 0 ) 547 | { 548 | return; 549 | } 550 | } 551 | 552 | 553 | /* Finish the line. 554 | */ 555 | 556 | if( fprintf( pfile, "\n" ) < 0 ) 557 | { 558 | return; 559 | } 560 | 561 | 562 | /* Check if this link has a next cleanup link. 563 | */ 564 | 565 | if( pen->penCleanupNext ) 566 | { 567 | /* It does. Do it. 568 | */ 569 | 570 | costella_base_error_fprint_tree( pfile, pen->penCleanupNext, udDepth + 571 | 1, udCleanup ); 572 | } 573 | } 574 | } 575 | 576 | 577 | 578 | /* costella_base_sprint_error_tree: 579 | ** 580 | ** Print the error tree to a string. 581 | ** 582 | ** ac: Pointer to string. 583 | ** 584 | ** penRoot: Pointer to the root COSTELLA_ERROR_NODE. 585 | */ 586 | 587 | void costella_base_sprint_error_tree( COSTELLA_C* ac, COSTELLA_ERROR_NODE* 588 | penRoot ) 589 | { 590 | /* Check pointers. 591 | */ 592 | 593 | if( !ac ) 594 | { 595 | return; 596 | } 597 | 598 | 599 | /* Start the string. 600 | */ 601 | 602 | *ac = 0; 603 | 604 | 605 | /* Call the recursive function. 606 | */ 607 | 608 | if( penRoot ) 609 | { 610 | costella_base_sprint_error_tree_recurse( ac, penRoot, 0, 0 ); 611 | } 612 | } 613 | 614 | 615 | 616 | /* costella_base_sprint_error_tree_recurse: 617 | ** 618 | ** Internal recursive function for printing the error tree to a string. 619 | ** 620 | ** ac: Pointer to the preallocated string, containing the error tree so 621 | ** far. 622 | ** 623 | ** pen: Pointer to the current COSTELLA_ERROR_NODE. 624 | ** 625 | ** udDepth: Current error depth. 626 | ** 627 | ** udCleanup: Current cleanup level. 628 | */ 629 | 630 | static void costella_base_sprint_error_tree_recurse( COSTELLA_C* ac, 631 | COSTELLA_ERROR_NODE* pen, COSTELLA_UD udDepth, COSTELLA_UD udCleanup ) 632 | { 633 | COSTELLA_C acScratch[ 256 ]; 634 | COSTELLA_UD ud; 635 | 636 | 637 | /* Check pointers. 638 | */ 639 | 640 | if( !ac || !pen ) 641 | { 642 | return; 643 | } 644 | 645 | 646 | /* Print the indenting spaces. 647 | */ 648 | 649 | for( ud = 0; ud < udDepth; ud++ ) 650 | { 651 | if( sprintf( acScratch, " " ) < 0 ) 652 | { 653 | return; 654 | } 655 | 656 | strcat( ac, acScratch ); 657 | } 658 | 659 | 660 | /* Print the opening brackets for existing cleanup mode. 661 | */ 662 | 663 | for( ud = 0; ud < udCleanup; ud++ ) 664 | { 665 | if( sprintf( acScratch, "[" ) < 0 ) 666 | { 667 | return; 668 | } 669 | 670 | strcat( ac, acScratch ); 671 | } 672 | 673 | 674 | /* Print the function name and error string. 675 | */ 676 | 677 | if( sprintf( acScratch, "%s: %s", pen->acFunctionName, pen->acError ? 678 | pen->acError : "CODING ERROR! Main error message not set before " 679 | "cleanup!" ) < 0 ) 680 | { 681 | return; 682 | } 683 | 684 | strcat( ac, acScratch ); 685 | 686 | 687 | /* Print the closing brackets for existing cleanup mode. 688 | */ 689 | 690 | for( ud = 0; ud < udCleanup; ud++ ) 691 | { 692 | if( sprintf( acScratch, "]" ) < 0 ) 693 | { 694 | return; 695 | } 696 | 697 | strcat( ac, acScratch ); 698 | } 699 | 700 | 701 | /* Finish the line. 702 | */ 703 | 704 | if( sprintf( acScratch, "\n" ) < 0 ) 705 | { 706 | return; 707 | } 708 | 709 | strcat( ac, acScratch ); 710 | 711 | 712 | /* Check if this node has a next node. 713 | */ 714 | 715 | if( pen->penNext ) 716 | { 717 | /* It does. Do it. 718 | */ 719 | 720 | costella_base_sprint_error_tree_recurse( ac, pen->penNext, udDepth + 1, 721 | udCleanup ); 722 | } 723 | 724 | 725 | /* Check if this node has a cleanup string, or if the node itself could 726 | ** not be allocated. 727 | */ 728 | 729 | if( pen->acCleanupError || !pen->bAllocated ) 730 | { 731 | /* It does. Increment cleanup level. 732 | */ 733 | 734 | udCleanup++; 735 | 736 | 737 | /* Print the indenting spaces. 738 | */ 739 | 740 | for( ud = 0; ud < udDepth; ud++ ) 741 | { 742 | if( sprintf( acScratch, " " ) < 0 ) 743 | { 744 | return; 745 | } 746 | 747 | strcat( ac, acScratch ); 748 | } 749 | 750 | 751 | /* Print the opening brackets for cleanup mode. 752 | */ 753 | 754 | for( ud = 0; ud < udCleanup; ud++ ) 755 | { 756 | if( sprintf( acScratch, "[" ) < 0 ) 757 | { 758 | return; 759 | } 760 | 761 | strcat( ac, acScratch ); 762 | } 763 | 764 | 765 | /* Print the function name and cleanup error string. 766 | */ 767 | 768 | if( pen->bAllocated ) 769 | { 770 | if( sprintf( acScratch, "%s: %s", pen->acFunctionName, 771 | pen->acCleanupError ) < 0 ) 772 | { 773 | return; 774 | } 775 | 776 | strcat( ac, acScratch ); 777 | } 778 | else 779 | { 780 | if( sprintf( acScratch, "%s: OUT OF MEMORY! Daughter error trees " 781 | "deleted!", pen->acFunctionName ) < 0 ) 782 | { 783 | return; 784 | } 785 | 786 | strcat( ac, acScratch ); 787 | } 788 | 789 | 790 | /* Print the closing brackets for cleanup mode. 791 | */ 792 | 793 | for( ud = 0; ud < udCleanup; ud++ ) 794 | { 795 | if( sprintf( acScratch, "]" ) < 0 ) 796 | { 797 | return; 798 | } 799 | 800 | strcat( ac, acScratch ); 801 | } 802 | 803 | 804 | /* Finish the line. 805 | */ 806 | 807 | if( sprintf( acScratch, "\n" ) < 0 ) 808 | { 809 | return; 810 | } 811 | 812 | strcat( ac, acScratch ); 813 | 814 | 815 | /* Check if this link has a next cleanup link. 816 | */ 817 | 818 | if( pen->penCleanupNext ) 819 | { 820 | /* It does. Do it. 821 | */ 822 | 823 | costella_base_sprint_error_tree_recurse( ac, pen->penCleanupNext, 824 | udDepth + 1, udCleanup ); 825 | } 826 | } 827 | } 828 | 829 | 830 | 831 | /* costella_base_error_node_delete: 832 | ** 833 | ** Delete a COSTELLA_ERROR_NODE. 834 | ** 835 | ** ppen: Pointer to pointer to the COSTELLA_ERROR_NODE to delete. 836 | */ 837 | 838 | void costella_base_error_node_delete( COSTELLA_ERROR_NODE** ppen ) 839 | { 840 | COSTELLA_ERROR_NODE* pen; 841 | 842 | 843 | /* Check pointer. 844 | */ 845 | 846 | if( !ppen ) 847 | { 848 | return; 849 | } 850 | 851 | 852 | /* Extract pointer. 853 | */ 854 | 855 | pen = *ppen; 856 | 857 | 858 | /* If the pointer is null, do nothing. 859 | */ 860 | 861 | if( !pen ) 862 | { 863 | return; 864 | } 865 | 866 | 867 | /* Free its daughters. 868 | */ 869 | 870 | costella_base_error_node_delete( &pen->penNext ); 871 | costella_base_error_node_delete( &pen->penCleanupNext ); 872 | 873 | 874 | /* Check if it was allocated. 875 | */ 876 | 877 | if( pen->bAllocated ) 878 | { 879 | /* It was. Free it. 880 | */ 881 | 882 | COSTELLA_FREE( *ppen ); 883 | } 884 | } 885 | 886 | 887 | 888 | /* Copyright (c) 1989-2007 John P. Costella. 889 | ** 890 | ** End of file. 891 | */ 892 | -------------------------------------------------------------------------------- /costella/costella_image_convert.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2005-2007 John P. Costella. 2 | ** 3 | ** Permission is hereby granted, free of charge, to any person obtaining a 4 | ** copy of this software and associated documentation files (the "Software") 5 | ** to deal in the Software without restriction, including without limitation 6 | ** the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | ** and/or sell copies of the Software, and to permit persons to whom the 8 | ** Software is furnished to do so, subject to the following conditions: 9 | ** 10 | ** The above copyright notice and this permission notice shall be included 11 | ** in all copies or substantial portions of the Software. 12 | ** 13 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 15 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. 16 | ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER 17 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING 18 | ** FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | ** DEALINGS IN THE SOFTWARE. 20 | ** 21 | ** 22 | ** costella_eimage_convert.c: 23 | ** 24 | ** Conversion of COSTELLA_EIMAGEs between the RGB and YCbCr colorspaces. 25 | ** 26 | ** Library begun: December 30, 2005. 27 | ** This version: November 12, 2007. 28 | ** 29 | ** Written in ANSI C. 30 | */ 31 | 32 | 33 | 34 | /* Flag to ensure correct declaration of global variables defined below. 35 | */ 36 | 37 | #define _COSTELLA_IMAGE_CONVERT_C_ 38 | 39 | 40 | 41 | /* Include files. 42 | */ 43 | 44 | #include "costella_image_convert.h" 45 | 46 | 47 | 48 | /* Externally visible global variables. 49 | */ 50 | 51 | COSTELLA_SW* gaswCostellaImageConvertCrR = 0, 52 | * gaswCostellaImageConvertCbB = 0; 53 | COSTELLA_SD* gasdCostellaImageConvertRY = 0, 54 | * gasdCostellaImageConvertGY = 0, * gasdCostellaImageConvertBY = 0, 55 | * gasdCostellaImageConvertRCb = 0, * gasdCostellaImageConvertGCb = 0, 56 | * gasdCostellaImageConvertBCb = 0, * gasdCostellaImageConvertRCr = 0, 57 | * gasdCostellaImageConvertGCr = 0, * gasdCostellaImageConvertBCr = 0, 58 | * gasdCostellaImageConvertCbG = 0, * gasdCostellaImageConvertCrG = 0; 59 | 60 | 61 | 62 | /* Internal global variables. 63 | */ 64 | 65 | static COSTELLA_B gbInitialized = COSTELLA_FALSE; 66 | 67 | 68 | 69 | /* Start function bodies. 70 | */ 71 | 72 | #include "costella_body.h" 73 | 74 | 75 | 76 | /* costella_image_convert_initialize: 77 | ** 78 | ** Public interface for initializing this library. 79 | */ 80 | 81 | COSTELLA_ANSI_FUNCTION( costella_image_convert_initialize, int, ( FILE* 82 | pfileError ) ) 83 | { 84 | if( COSTELLA_CALL( CostellaImageConvertInitialize() ) ) 85 | { 86 | COSTELLA_ERROR_FPRINT( pfileError ); 87 | COSTELLA_ANSI_RETURN( 0 ); 88 | } 89 | } 90 | COSTELLA_END_ANSI_FUNCTION( !0 ) 91 | 92 | 93 | 94 | /* costella_image_convert_finalize: 95 | ** 96 | ** Public interface for finalizing this library. 97 | */ 98 | 99 | COSTELLA_ANSI_FUNCTION( costella_image_convert_finalize, int, ( FILE* 100 | pfileError ) ) 101 | { 102 | if( COSTELLA_CALL( CostellaImageConvertFinalize() ) ) 103 | { 104 | COSTELLA_ERROR_FPRINT( pfileError ); 105 | COSTELLA_ANSI_RETURN( 0 ); 106 | } 107 | } 108 | COSTELLA_END_ANSI_FUNCTION( !0 ) 109 | 110 | 111 | 112 | /* costella_image_convert_rgb_to_ycbcr: 113 | ** 114 | ** Public interface for converting an RGB COSTELLA_IMAGE to YCbCr. 115 | ** 116 | ** pi{In,Out}: Pointer to the {input,output} COSTELLA_IMAGE. 117 | */ 118 | 119 | COSTELLA_ANSI_FUNCTION( costella_image_convert_rgb_to_ycbcr, int, ( 120 | COSTELLA_IMAGE* piIn, COSTELLA_IMAGE* piOut, int (*pfProgress)( void* 121 | pvPassback ), void* pvPassback, FILE* pfileError ) ) 122 | { 123 | COSTELLA_WRAP_PROGRESS wp; 124 | 125 | wp.pfProgress = pfProgress; 126 | wp.pvPassback = pvPassback; 127 | 128 | if( COSTELLA_CALL( CostellaImageConvertRgbToYcbcr( piIn, piOut, 129 | CostellaWrapProgress, &wp ) ) ) 130 | { 131 | COSTELLA_ERROR_FPRINT( pfileError ); 132 | COSTELLA_ANSI_RETURN( 0 ); 133 | } 134 | } 135 | COSTELLA_END_ANSI_FUNCTION( !0 ) 136 | 137 | 138 | 139 | /* costella_image_convert_ycbcr_to_rgb: 140 | ** 141 | ** Public interface for converting a YCbCr COSTELLA_IMAGE to RGB. 142 | ** 143 | ** pi{In,Out}: Pointer to the {input,output} COSTELLA_IMAGE. 144 | */ 145 | 146 | COSTELLA_ANSI_FUNCTION( costella_image_convert_ycbcr_to_rgb, int, ( 147 | COSTELLA_IMAGE* piIn, COSTELLA_IMAGE* piOut, int (*pfProgress)( void* 148 | pvPassback ), void* pvPassback, FILE* pfileError ) ) 149 | { 150 | COSTELLA_WRAP_PROGRESS wp; 151 | 152 | wp.pfProgress = pfProgress; 153 | wp.pvPassback = pvPassback; 154 | 155 | if( COSTELLA_CALL( CostellaImageConvertYcbcrToRgb( piIn, piOut, 156 | CostellaWrapProgress, &wp ) ) ) 157 | { 158 | COSTELLA_ERROR_FPRINT( pfileError ); 159 | COSTELLA_ANSI_RETURN( 0 ); 160 | } 161 | } 162 | COSTELLA_END_ANSI_FUNCTION( !0 ) 163 | 164 | 165 | 166 | /* CostellaImageConvertInitialize: 167 | ** 168 | ** Initialize the library. 169 | */ 170 | 171 | COSTELLA_FUNCTION( CostellaImageConvertInitialize, ( void ) ) 172 | { 173 | COSTELLA_UW uw; 174 | 175 | 176 | /* Do nothing if already initialized. 177 | */ 178 | 179 | if( gbInitialized ) 180 | { 181 | COSTELLA_RETURN; 182 | } 183 | 184 | 185 | /* Set initialized flag. 186 | */ 187 | 188 | gbInitialized = COSTELLA_TRUE; 189 | 190 | 191 | /* Initialize other libraries. 192 | */ 193 | 194 | if( COSTELLA_CALL( CostellaImageInitialize() ) || COSTELLA_CALL( 195 | CostellaWrapInitialize() ) ) 196 | { 197 | COSTELLA_ERROR( "Initialization" ); 198 | gbInitialized = COSTELLA_FALSE; 199 | COSTELLA_RETURN; 200 | } 201 | 202 | 203 | /* Allocate memory for the lookup tables. 204 | */ 205 | 206 | if( COSTELLA_MALLOC( gasdCostellaImageConvertRY, 256 ) || COSTELLA_MALLOC( 207 | gasdCostellaImageConvertGY, 256 ) || COSTELLA_MALLOC( 208 | gasdCostellaImageConvertBY, 256 ) || COSTELLA_MALLOC( 209 | gasdCostellaImageConvertRCb, 256 ) || COSTELLA_MALLOC( 210 | gasdCostellaImageConvertGCb, 256 ) || COSTELLA_MALLOC( 211 | gasdCostellaImageConvertBCb, 256 ) || COSTELLA_MALLOC( 212 | gasdCostellaImageConvertGCr, 256 ) || COSTELLA_MALLOC( 213 | gasdCostellaImageConvertBCr, 256 ) || COSTELLA_MALLOC( 214 | gasdCostellaImageConvertCbG, 256 ) || COSTELLA_MALLOC( 215 | gasdCostellaImageConvertCrG, 256 ) || COSTELLA_MALLOC( 216 | gaswCostellaImageConvertCrR, 256 ) || COSTELLA_MALLOC( 217 | gaswCostellaImageConvertCbB, 256 ) ) 218 | { 219 | COSTELLA_FUNDAMENTAL_ERROR( "Allocating" ); 220 | 221 | if( COSTELLA_FREE( gasdCostellaImageConvertRY ) || COSTELLA_FREE( 222 | gasdCostellaImageConvertGY ) || COSTELLA_FREE( 223 | gasdCostellaImageConvertBY ) || COSTELLA_FREE( 224 | gasdCostellaImageConvertRCb ) || COSTELLA_FREE( 225 | gasdCostellaImageConvertGCb ) || COSTELLA_FREE( 226 | gasdCostellaImageConvertBCb ) || COSTELLA_FREE( 227 | gasdCostellaImageConvertGCr ) || COSTELLA_FREE( 228 | gasdCostellaImageConvertBCr ) || COSTELLA_FREE( 229 | gasdCostellaImageConvertCbG ) || COSTELLA_FREE( 230 | gasdCostellaImageConvertCrG ) || COSTELLA_FREE( 231 | gaswCostellaImageConvertCrR ) || COSTELLA_FREE( 232 | gaswCostellaImageConvertCbB ) ) 233 | { 234 | COSTELLA_CLEANUP_FUNDAMENTAL_ERROR( "Freeing" ); 235 | } 236 | 237 | COSTELLA_RETURN; 238 | } 239 | 240 | 241 | /* Two of the tables are actually equal, so we did not allocate both. 242 | ** Simply set the pointer to be equal, for clarity. 243 | */ 244 | 245 | gasdCostellaImageConvertRCr = gasdCostellaImageConvertBCb; 246 | 247 | 248 | /* Create the RGB to YCbCr conversion tables. 249 | ** 250 | */ 251 | 252 | for( uw = 0; uw < 256; uw++ ) 253 | { 254 | gasdCostellaImageConvertRY[ uw ] = 19595L * (COSTELLA_SD) uw + 32768L; 255 | gasdCostellaImageConvertGY[ uw ] = 38470L * (COSTELLA_SD) uw; 256 | gasdCostellaImageConvertBY[ uw ] = 7471L * (COSTELLA_SD) uw; 257 | 258 | gasdCostellaImageConvertRCb[ uw ] = -11058L * (COSTELLA_SD) uw; 259 | gasdCostellaImageConvertGCb[ uw ] = -21709L * (COSTELLA_SD) uw; 260 | gasdCostellaImageConvertBCb[ uw ] = 32767L * (COSTELLA_SD) uw + 261 | 8421376L; 262 | 263 | gasdCostellaImageConvertGCr[ uw ] = -27438L * (COSTELLA_SD) uw; 264 | gasdCostellaImageConvertBCr[ uw ] = -5329L * (COSTELLA_SD) uw; 265 | } 266 | 267 | 268 | /* Create the YCbCr to RGB conversion tables. 269 | */ 270 | 271 | for( uw = 0; uw < 256; uw++ ) 272 | { 273 | gasdCostellaImageConvertCbG[ uw ] = 8910464L - 22554L * (COSTELLA_SD) 274 | uw; 275 | gasdCostellaImageConvertCrG[ uw ] = -46803L * (COSTELLA_SD) uw; 276 | 277 | 278 | gaswCostellaImageConvertCrR[ uw ] = (COSTELLA_SW) 279 | COSTELLA_SHIFT_RIGHT_FLOOR( 91885L * (COSTELLA_SD) uw - 11728512L, 16 280 | ); 281 | gaswCostellaImageConvertCbB[ uw ] = (COSTELLA_SW) 282 | COSTELLA_SHIFT_RIGHT_FLOOR( 116134L * (COSTELLA_SD) uw - 14832384L, 16 283 | ); 284 | } 285 | } 286 | COSTELLA_END_FUNCTION 287 | 288 | 289 | 290 | /* CostellaImageConvertFinalize: 291 | ** 292 | ** Finalize the library. 293 | */ 294 | 295 | COSTELLA_FUNCTION( CostellaImageConvertFinalize, ( void ) ) 296 | { 297 | /* Do nothing if not initialized. 298 | */ 299 | 300 | if( !gbInitialized ) 301 | { 302 | COSTELLA_RETURN; 303 | } 304 | 305 | 306 | /* Clear initialized flag. 307 | */ 308 | 309 | gbInitialized = COSTELLA_FALSE; 310 | 311 | 312 | /* Free the memory allocated in initialization. 313 | */ 314 | 315 | if( COSTELLA_FREE( gasdCostellaImageConvertRY ) || COSTELLA_FREE( 316 | gasdCostellaImageConvertGY ) || COSTELLA_FREE( 317 | gasdCostellaImageConvertBY ) || COSTELLA_FREE( 318 | gasdCostellaImageConvertRCb ) || COSTELLA_FREE( 319 | gasdCostellaImageConvertGCb ) || COSTELLA_FREE( 320 | gasdCostellaImageConvertBCb ) || COSTELLA_FREE( 321 | gasdCostellaImageConvertGCr ) || COSTELLA_FREE( 322 | gasdCostellaImageConvertBCr ) || COSTELLA_FREE( 323 | gasdCostellaImageConvertCbG ) || COSTELLA_FREE( 324 | gasdCostellaImageConvertCrG ) || COSTELLA_FREE( 325 | gaswCostellaImageConvertCrR ) || COSTELLA_FREE( 326 | gaswCostellaImageConvertCbB ) ) 327 | { 328 | COSTELLA_FUNDAMENTAL_ERROR( "Freeing" ); 329 | COSTELLA_RETURN; 330 | } 331 | 332 | 333 | /* Zero pointer that was set to pointer to allocated array that has now 334 | ** been freed. 335 | */ 336 | 337 | gasdCostellaImageConvertRCr = 0; 338 | 339 | 340 | /* Finalize other libraries. 341 | */ 342 | 343 | if( COSTELLA_CALL( CostellaWrapFinalize() ) || COSTELLA_CALL( 344 | CostellaImageFinalize() ) ) 345 | { 346 | COSTELLA_ERROR( "Finalizing" ); 347 | COSTELLA_RETURN; 348 | } 349 | } 350 | COSTELLA_END_FUNCTION 351 | 352 | 353 | 354 | /* CostellaImageConvertRgbToYcbcr: 355 | ** 356 | ** Convert a color image from the RGB colorspace to the YCbCr colorspace. 357 | ** 358 | ** pi{In,Out}: Pointer to the {input,output} image. Can be the same. 359 | */ 360 | 361 | COSTELLA_FUNCTION( CostellaImageConvertRgbToYcbcr, ( COSTELLA_IMAGE* piIn, 362 | COSTELLA_IMAGE* piOut, COSTELLA_CALLBACK_FUNCTION pfProgress, COSTELLA_O* 363 | poPassback ) ) 364 | { 365 | #ifdef COSTELLA_DEBUG 366 | COSTELLA_B bAlpha; 367 | #endif 368 | COSTELLA_B bCopyAlpha; 369 | COSTELLA_UB ubR, ubG, ubB, ubY, ubCb, ubCr, ubA; 370 | COSTELLA_UD udWidth, udHeight, udColumn, udRow; 371 | COSTELLA_SD sdRowStrideIn, sdRowStrideOut, sdAlphaRowStrideIn, 372 | sdAlphaRowStrideOut; 373 | COSTELLA_IMAGE_ALPHA* piaIn, * piaOut; 374 | COSTELLA_IMAGE_COLOR* picIn, * picOut; 375 | COSTELLA_IMAGE_ALPHA_PIXEL iapIn, iapInStart, iapOut, iapOutStart; 376 | COSTELLA_IMAGE_COLOR_PIXEL icpIn, icpInStart, icpOut, icpOutStart; 377 | 378 | 379 | /* Keep GCC happy. 380 | */ 381 | 382 | iapIn = iapInStart = iapOut = iapOutStart = giapCostellaImageNull; 383 | icpIn = icpInStart = icpOut = icpOutStart = gicpCostellaImageNull; 384 | 385 | 386 | /* Check initialization and pointers. 387 | */ 388 | 389 | #ifdef COSTELLA_DEBUG 390 | { 391 | if( !gbInitialized ) 392 | { 393 | COSTELLA_FUNDAMENTAL_ERROR( "Initialization" ); 394 | COSTELLA_RETURN; 395 | } 396 | 397 | if( !piIn ) 398 | { 399 | COSTELLA_FUNDAMENTAL_ERROR( "Null piIn" ); 400 | COSTELLA_RETURN; 401 | } 402 | 403 | if( !piOut ) 404 | { 405 | COSTELLA_FUNDAMENTAL_ERROR( "Null piOut" ); 406 | COSTELLA_RETURN; 407 | } 408 | } 409 | #endif 410 | 411 | 412 | /* Check that both images are color. 413 | */ 414 | 415 | #ifdef COSTELLA_DEBUG 416 | { 417 | if( !piIn->bColor ) 418 | { 419 | COSTELLA_FUNDAMENTAL_ERROR( "Input image not color" ); 420 | COSTELLA_RETURN; 421 | } 422 | 423 | if( !piOut->bColor ) 424 | { 425 | COSTELLA_FUNDAMENTAL_ERROR( "Output image not color" ); 426 | COSTELLA_RETURN; 427 | } 428 | } 429 | #endif 430 | 431 | 432 | /* Check that the input image is in the RGB colorspace. 433 | */ 434 | 435 | #ifdef COSTELLA_DEBUG 436 | { 437 | if( !piIn->bRgb ) 438 | { 439 | COSTELLA_FUNDAMENTAL_ERROR( "Input image not RGB" ); 440 | COSTELLA_RETURN; 441 | } 442 | } 443 | #endif 444 | 445 | 446 | /* Set the output image to the YCbCr colorspace. 447 | */ 448 | 449 | piOut->bRgb = COSTELLA_FALSE; 450 | 451 | 452 | /* Copy the downsampled chrominance and nonreplicated downsampled 453 | ** chrominance flags. 454 | */ 455 | 456 | piOut->bDownsampledChrominance = piIn->bDownsampledChrominance; 457 | piOut->bNonreplicatedDownsampledChrominance = 458 | piIn->bNonreplicatedDownsampledChrominance; 459 | 460 | 461 | /* Extract data. 462 | */ 463 | 464 | #ifdef COSTELLA_DEBUG 465 | bAlpha = piIn->bAlpha; 466 | #endif 467 | 468 | udWidth = piIn->udWidth; 469 | udHeight = piIn->udHeight; 470 | 471 | sdRowStrideIn = piIn->sdRowStride; 472 | sdAlphaRowStrideIn = piIn->sdAlphaRowStride; 473 | 474 | sdRowStrideOut = piOut->sdRowStride; 475 | sdAlphaRowStrideOut = piOut->sdAlphaRowStride; 476 | 477 | piaIn = &piIn->ia; 478 | piaOut = &piOut->ia; 479 | 480 | picIn = &piIn->ic; 481 | picOut = &piOut->ic; 482 | 483 | 484 | /* Check that the output image agrees with the input image. 485 | */ 486 | 487 | #ifdef COSTELLA_DEBUG 488 | { 489 | if( !piOut->bAlpha != !bAlpha ) 490 | { 491 | COSTELLA_FUNDAMENTAL_ERROR( "Alpha flags disagree" ); 492 | COSTELLA_RETURN; 493 | } 494 | 495 | if( piOut->udWidth != udWidth || piOut->udHeight != udHeight ) 496 | { 497 | COSTELLA_FUNDAMENTAL_ERROR( "Dimensions do not agree" ); 498 | COSTELLA_RETURN; 499 | } 500 | } 501 | #endif 502 | 503 | 504 | /* Check whether we need to copy the alpha channel image data. 505 | */ 506 | 507 | bCopyAlpha = !COSTELLA_IMAGE_ALPHA_IS_SAME( *piaIn, *piaOut ); 508 | 509 | 510 | /* Start at the top-left corner of images. 511 | */ 512 | 513 | COSTELLA_IMAGE_COLOR_PIXEL_SET_TOP_LEFT( icpInStart, *picIn, udWidth, 514 | udHeight, sdRowStrideIn ); 515 | COSTELLA_IMAGE_COLOR_PIXEL_SET_TOP_LEFT( icpOutStart, *picOut, udWidth, 516 | udHeight, sdRowStrideOut ); 517 | 518 | if( bCopyAlpha ) 519 | { 520 | COSTELLA_IMAGE_ALPHA_PIXEL_SET_TOP_LEFT( iapInStart, *piaIn, udWidth, 521 | udHeight, sdAlphaRowStrideIn ); 522 | COSTELLA_IMAGE_ALPHA_PIXEL_SET_TOP_LEFT( iapOutStart, *piaOut, udWidth, 523 | udHeight, sdAlphaRowStrideOut ); 524 | } 525 | 526 | 527 | /* Walk through the rows. 528 | */ 529 | 530 | for( udRow = 0; udRow < udHeight; udRow++ ) 531 | { 532 | /* Progress callback. 533 | */ 534 | 535 | if( pfProgress && COSTELLA_CALL( pfProgress( poPassback ) ) ) 536 | { 537 | COSTELLA_ERROR( "Progress callback" ) 538 | COSTELLA_RETURN; 539 | } 540 | 541 | 542 | /* Set pixels to the start of this row. 543 | */ 544 | 545 | COSTELLA_IMAGE_COLOR_PIXEL_ASSIGN( icpInStart, icpIn ); 546 | COSTELLA_IMAGE_COLOR_PIXEL_ASSIGN( icpOutStart, icpOut ); 547 | 548 | if( bCopyAlpha ) 549 | { 550 | COSTELLA_IMAGE_ALPHA_PIXEL_ASSIGN( iapInStart, iapIn ); 551 | COSTELLA_IMAGE_ALPHA_PIXEL_ASSIGN( iapOutStart, iapOut ); 552 | } 553 | 554 | 555 | /* Walk through the columns. 556 | */ 557 | 558 | for( udColumn = 0; udColumn < udWidth; udColumn++ ) 559 | { 560 | /* Extract the R, G, and B components of the input image. 561 | */ 562 | 563 | ubR = COSTELLA_IMAGE_COLOR_PIXEL_GET_R_Y( icpIn ); 564 | ubG = COSTELLA_IMAGE_COLOR_PIXEL_GET_G_CB( icpIn ); 565 | ubB = COSTELLA_IMAGE_COLOR_PIXEL_GET_B_CR( icpIn ); 566 | 567 | 568 | /* Compute Y, Cb, and Cr. 569 | */ 570 | 571 | COSTELLA_IMAGE_CONVERT_RGB_TO_YCBCR( ubR, ubG, ubB, &ubY, &ubCb, 572 | &ubCr ); 573 | 574 | 575 | /* Store them. 576 | */ 577 | 578 | COSTELLA_IMAGE_COLOR_PIXEL_SET_RGB_YCBCR( icpOut, ubY, ubCb, ubCr ); 579 | 580 | 581 | /* Copy the alpha pixel, if we need to. 582 | */ 583 | 584 | if( bCopyAlpha ) 585 | { 586 | ubA = COSTELLA_IMAGE_ALPHA_PIXEL_GET_A( iapIn ); 587 | COSTELLA_IMAGE_ALPHA_PIXEL_SET_A( iapOut, ubA ); 588 | } 589 | 590 | 591 | /* Move to the next column. 592 | */ 593 | 594 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_RIGHT( icpIn ); 595 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_RIGHT( icpOut ); 596 | 597 | if( bCopyAlpha ) 598 | { 599 | COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_RIGHT( iapIn ); 600 | COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_RIGHT( iapOut ); 601 | } 602 | } 603 | 604 | 605 | /* Walk down to the next row. 606 | */ 607 | 608 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_DOWN( icpInStart, sdRowStrideIn ); 609 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_DOWN( icpOutStart, sdRowStrideOut ); 610 | 611 | if( bCopyAlpha ) 612 | { 613 | COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_DOWN( iapInStart, sdAlphaRowStrideIn 614 | ); 615 | COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_DOWN( iapOutStart, sdAlphaRowStrideOut 616 | ); 617 | } 618 | } 619 | } 620 | COSTELLA_END_FUNCTION 621 | 622 | 623 | 624 | /* CostellaImageConvertYcbcrToRgb: 625 | ** 626 | ** Convert a color image from the YCbCr colorspace to the RGB colorspace. 627 | ** 628 | ** pi{In,Out}: Pointer to the {input,output} image. Can be the same. 629 | */ 630 | 631 | COSTELLA_FUNCTION( CostellaImageConvertYcbcrToRgb, ( COSTELLA_IMAGE* piIn, 632 | COSTELLA_IMAGE* piOut, COSTELLA_CALLBACK_FUNCTION pfProgress, COSTELLA_O* 633 | poPassback ) ) 634 | { 635 | #ifdef COSTELLA_DEBUG 636 | COSTELLA_B bAlpha; 637 | #endif 638 | COSTELLA_B bCopyAlpha, bDownsampledChrominance, 639 | bNonreplicatedDownsampledChrominance, bTop, bLeft; 640 | COSTELLA_UB ubR, ubG, ubB, ubY, ubCb, ubCr, ubA; 641 | COSTELLA_UD udWidth, udHeight, udColumn, udRow; 642 | COSTELLA_SD sdRowStrideIn, sdRowStrideOut, sdAlphaRowStrideIn, 643 | sdAlphaRowStrideOut; 644 | COSTELLA_IMAGE_ALPHA* piaIn, * piaOut; 645 | COSTELLA_IMAGE_COLOR* picIn, * picOut; 646 | COSTELLA_IMAGE_ALPHA_PIXEL iapIn, iapInStart, iapOut, iapOutStart; 647 | COSTELLA_IMAGE_COLOR_PIXEL icpIn, icpInStart, icpOut, icpOutStart; 648 | 649 | 650 | /* Keep GCC happy. 651 | */ 652 | 653 | iapIn = iapInStart = iapOut = iapOutStart = giapCostellaImageNull; 654 | icpIn = icpInStart = icpOut = icpOutStart = gicpCostellaImageNull; 655 | 656 | 657 | /* Check initialization and pointers. 658 | */ 659 | 660 | #ifdef COSTELLA_DEBUG 661 | { 662 | if( !gbInitialized ) 663 | { 664 | COSTELLA_FUNDAMENTAL_ERROR( "Initialization" ); 665 | COSTELLA_RETURN; 666 | } 667 | 668 | if( !piIn ) 669 | { 670 | COSTELLA_FUNDAMENTAL_ERROR( "Null piIn" ); 671 | COSTELLA_RETURN; 672 | } 673 | if( !piOut ) 674 | { 675 | COSTELLA_FUNDAMENTAL_ERROR( "Null piOut" ); 676 | COSTELLA_RETURN; 677 | } 678 | } 679 | #endif 680 | 681 | 682 | /* Check that both images are color. 683 | */ 684 | 685 | #ifdef COSTELLA_DEBUG 686 | { 687 | if( !piIn->bColor ) 688 | { 689 | COSTELLA_FUNDAMENTAL_ERROR( "Input image not color" ); 690 | COSTELLA_RETURN; 691 | } 692 | 693 | if( !piOut->bColor ) 694 | { 695 | COSTELLA_FUNDAMENTAL_ERROR( "Output image not color" ); 696 | COSTELLA_RETURN; 697 | } 698 | } 699 | #endif 700 | 701 | 702 | /* Check that the input image is in the YCbCr colorspace. 703 | */ 704 | 705 | #ifdef COSTELLA_DEBUG 706 | { 707 | if( piIn->bRgb ) 708 | { 709 | COSTELLA_FUNDAMENTAL_ERROR( "Input image not YCbCr" ); 710 | COSTELLA_RETURN; 711 | } 712 | } 713 | #endif 714 | 715 | 716 | /* Set the output image to the RGB colorspace. 717 | */ 718 | 719 | piOut->bRgb = COSTELLA_TRUE; 720 | 721 | 722 | /* Extract data. 723 | */ 724 | 725 | #ifdef COSTELLA_DEBUG 726 | bAlpha = piIn->bAlpha; 727 | #endif 728 | bDownsampledChrominance = piIn->bDownsampledChrominance; 729 | bNonreplicatedDownsampledChrominance = 730 | piIn->bNonreplicatedDownsampledChrominance; 731 | 732 | udWidth = piIn->udWidth; 733 | udHeight = piIn->udHeight; 734 | 735 | sdRowStrideIn = piIn->sdRowStride; 736 | sdAlphaRowStrideIn = piIn->sdAlphaRowStride; 737 | 738 | sdRowStrideOut = piOut->sdRowStride; 739 | sdAlphaRowStrideOut = piOut->sdAlphaRowStride; 740 | 741 | piaIn = &piIn->ia; 742 | piaOut = &piOut->ia; 743 | 744 | picIn = &piIn->ic; 745 | picOut = &piOut->ic; 746 | 747 | 748 | /* Set downsampled chrominance and nonreplicated downsampled chrominance 749 | ** flags in the output image. 750 | */ 751 | 752 | piOut->bDownsampledChrominance = bDownsampledChrominance; 753 | piOut->bNonreplicatedDownsampledChrominance = 754 | bNonreplicatedDownsampledChrominance; 755 | 756 | 757 | /* Check that the output image agrees with the input image. 758 | */ 759 | 760 | #ifdef COSTELLA_DEBUG 761 | { 762 | if( !piOut->bAlpha != !bAlpha ) 763 | { 764 | COSTELLA_FUNDAMENTAL_ERROR( "Alpha flags disagree" ); 765 | COSTELLA_RETURN; 766 | } 767 | 768 | if( piOut->udWidth != udWidth || piOut->udHeight != udHeight ) 769 | { 770 | COSTELLA_FUNDAMENTAL_ERROR( "Dimensions disagree" ); 771 | COSTELLA_RETURN; 772 | } 773 | } 774 | #endif 775 | 776 | 777 | /* Check whether we need to copy the alpha channel image data. 778 | */ 779 | 780 | bCopyAlpha = !COSTELLA_IMAGE_ALPHA_IS_SAME( *piaIn, *piaOut ); 781 | 782 | 783 | /* Start at the top-left corner of images. 784 | */ 785 | 786 | COSTELLA_IMAGE_COLOR_PIXEL_SET_TOP_LEFT( icpInStart, *picIn, udWidth, 787 | udHeight, sdRowStrideIn ); 788 | COSTELLA_IMAGE_COLOR_PIXEL_SET_TOP_LEFT( icpOutStart, *picOut, udWidth, 789 | udHeight, sdRowStrideOut ); 790 | 791 | if( bCopyAlpha ) 792 | { 793 | COSTELLA_IMAGE_ALPHA_PIXEL_SET_TOP_LEFT( iapInStart, *piaIn, udWidth, 794 | udHeight, sdAlphaRowStrideIn ); 795 | COSTELLA_IMAGE_ALPHA_PIXEL_SET_TOP_LEFT( iapOutStart, *piaOut, udWidth, 796 | udHeight, sdAlphaRowStrideOut ); 797 | } 798 | 799 | 800 | /* Walk through the rows. 801 | */ 802 | 803 | for( udRow = 0, bTop = COSTELLA_TRUE; udRow < udHeight; udRow++, bTop = 804 | !bTop ) 805 | { 806 | /* Progress callback. 807 | */ 808 | 809 | if( pfProgress && COSTELLA_CALL( pfProgress( poPassback ) ) ) 810 | { 811 | COSTELLA_ERROR( "Progress callback" ) 812 | COSTELLA_RETURN; 813 | } 814 | 815 | 816 | /* Set pixels to the start of this row. 817 | */ 818 | 819 | COSTELLA_IMAGE_COLOR_PIXEL_ASSIGN( icpInStart, icpIn ); 820 | COSTELLA_IMAGE_COLOR_PIXEL_ASSIGN( icpOutStart, icpOut ); 821 | 822 | if( bCopyAlpha ) 823 | { 824 | COSTELLA_IMAGE_ALPHA_PIXEL_ASSIGN( iapInStart, iapIn ); 825 | COSTELLA_IMAGE_ALPHA_PIXEL_ASSIGN( iapOutStart, iapOut ); 826 | } 827 | 828 | 829 | /* Walk through the columns. 830 | */ 831 | 832 | for( udColumn = 0, bLeft = COSTELLA_TRUE; udColumn < udWidth; 833 | udColumn++, bLeft = !bLeft ) 834 | { 835 | /* Extract Y. 836 | */ 837 | 838 | ubY = COSTELLA_IMAGE_COLOR_PIXEL_GET_R_Y( icpIn ); 839 | 840 | 841 | /* Check if we need to compute chrominance. 842 | */ 843 | 844 | if( !bNonreplicatedDownsampledChrominance || ( bLeft && bTop ) ) 845 | { 846 | /* We do need to do chrominance. Extract Cb and Cr. 847 | */ 848 | 849 | ubCb = COSTELLA_IMAGE_COLOR_PIXEL_GET_G_CB( icpIn ); 850 | ubCr = COSTELLA_IMAGE_COLOR_PIXEL_GET_B_CR( icpIn ); 851 | 852 | 853 | /* Convert to RGB. 854 | */ 855 | 856 | COSTELLA_IMAGE_CONVERT_YCBCR_TO_RGB( ubY, ubCb, ubCr, &ubR, &ubG, 857 | &ubB ); 858 | 859 | 860 | /* Store the R, G, and B components. 861 | */ 862 | 863 | COSTELLA_IMAGE_COLOR_PIXEL_SET_RGB_YCBCR( icpOut, ubR, ubG, ubB ); 864 | } 865 | else 866 | { 867 | /* We don't need to do chrominance. Set R, G, and B to the Y value. 868 | */ 869 | 870 | COSTELLA_IMAGE_COLOR_PIXEL_SET_RGB_YCBCR( icpOut, ubY, ubY, ubY ); 871 | } 872 | 873 | 874 | /* Copy the alpha pixel, if we need to. 875 | */ 876 | 877 | if( bCopyAlpha ) 878 | { 879 | ubA = COSTELLA_IMAGE_ALPHA_PIXEL_GET_A( iapIn ); 880 | COSTELLA_IMAGE_ALPHA_PIXEL_SET_A( iapOut, ubA ); 881 | } 882 | 883 | 884 | /* Move to the next column. 885 | */ 886 | 887 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_RIGHT( icpIn ); 888 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_RIGHT( icpOut ); 889 | 890 | if( bCopyAlpha ) 891 | { 892 | COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_RIGHT( iapIn ); 893 | COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_RIGHT( iapOut ); 894 | } 895 | } 896 | 897 | 898 | /* Walk down to the next row. 899 | */ 900 | 901 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_DOWN( icpInStart, sdRowStrideIn ); 902 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_DOWN( icpOutStart, sdRowStrideOut ); 903 | 904 | if( bCopyAlpha ) 905 | { 906 | COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_DOWN( iapInStart, sdAlphaRowStrideIn 907 | ); 908 | COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_DOWN( iapOutStart, sdAlphaRowStrideOut 909 | ); 910 | } 911 | } 912 | } 913 | COSTELLA_END_FUNCTION 914 | 915 | 916 | 917 | /* Copyright (c) 2005-2007 John P. Costella. 918 | ** 919 | ** End of file. 920 | */ 921 | -------------------------------------------------------------------------------- /costella/costella_image_chrominance.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2005-2007 John P. Costella. 2 | ** 3 | ** Permission is hereby granted, free of charge, to any person obtaining a 4 | ** copy of this software and associated documentation files (the "Software") 5 | ** to deal in the Software without restriction, including without limitation 6 | ** the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | ** and/or sell copies of the Software, and to permit persons to whom the 8 | ** Software is furnished to do so, subject to the following conditions: 9 | ** 10 | ** The above copyright notice and this permission notice shall be included 11 | ** in all copies or substantial portions of the Software. 12 | ** 13 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 15 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. 16 | ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER 17 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING 18 | ** FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | ** DEALINGS IN THE SOFTWARE. 20 | ** 21 | ** 22 | ** costella_image_chrominance.c: 23 | ** 24 | ** Library for performing chrominance downsampling, upsampling, and 25 | ** replication, as performed in JPEG, for COSTELLA_IMAGEs. 26 | ** 27 | ** Library begun: December 30, 2005. 28 | ** This version: November 12, 2007. 29 | ** 30 | ** Written in ANSI C. 31 | */ 32 | 33 | 34 | 35 | /* Include files. 36 | */ 37 | 38 | #include "costella_image_chrominance.h" 39 | #include 40 | 41 | 42 | 43 | /* Internal global variables. 44 | */ 45 | 46 | static COSTELLA_B gbInitialized = COSTELLA_FALSE; 47 | static COSTELLA_SW* gaswCostellaImageChrominanceMult9Add8 = 0, 48 | * gaswCostellaImageChrominanceMult3 = 0; 49 | 50 | 51 | 52 | /* Start function bodies. 53 | */ 54 | 55 | #include "costella_body.h" 56 | 57 | 58 | 59 | /* costella_image_chrominance_initialize: 60 | ** 61 | ** Public interface for initializing this library. 62 | */ 63 | 64 | COSTELLA_ANSI_FUNCTION( costella_image_chrominance_initialize, int, ( FILE* 65 | pfileError ) ) 66 | { 67 | if( COSTELLA_CALL( CostellaImageChrominanceInitialize() ) ) 68 | { 69 | COSTELLA_ERROR_FPRINT( pfileError ); 70 | COSTELLA_ANSI_RETURN( 0 ); 71 | } 72 | } 73 | COSTELLA_END_ANSI_FUNCTION( !0 ) 74 | 75 | 76 | 77 | /* costella_image_chrominance_finalize: 78 | ** 79 | ** Public interface for finalizing this library. 80 | */ 81 | 82 | COSTELLA_ANSI_FUNCTION( costella_image_chrominance_finalize, int, ( FILE* 83 | pfileError ) ) 84 | { 85 | if( COSTELLA_CALL( CostellaImageChrominanceFinalize() ) ) 86 | { 87 | COSTELLA_ERROR_FPRINT( pfileError ); 88 | COSTELLA_ANSI_RETURN( 0 ); 89 | } 90 | } 91 | COSTELLA_END_ANSI_FUNCTION( !0 ) 92 | 93 | 94 | 95 | /* costella_image_chrominance_average_downsample_replicate: 96 | ** 97 | ** Public interface for downsampling the chrominance of a COSTELLA_IMAGE 98 | ** by simple averaging, replicating the downsampled chrominance data into 99 | ** each pixel of each 2 x 2 block. 100 | ** 101 | ** pi{In,Out}: Pointer to the {input,output} COSTELLA_IMAGE. May be the 102 | ** same. The input COSTELLA_IMAGE must be in the YCbCr colorspace, and 103 | ** must not have downsampled chrominance. The output COSTELLA_IMAGE will 104 | ** be in the YCbCr colorspace, and will have replicated downsampled 105 | ** chrominance. 106 | */ 107 | 108 | COSTELLA_ANSI_FUNCTION( costella_image_chrominance_downsample, int, ( 109 | COSTELLA_IMAGE* piIn, COSTELLA_IMAGE* piOut, int (*pfProgress)( void* 110 | pvPassback ), void* pvPassback, FILE* pfileError ) ) 111 | { 112 | COSTELLA_WRAP_PROGRESS wp; 113 | 114 | wp.pfProgress = pfProgress; 115 | wp.pvPassback = pvPassback; 116 | 117 | if( COSTELLA_CALL( CostellaImageChrominanceAverageDownsampleReplicate( 118 | piIn, piOut, CostellaWrapProgress, &wp ) ) ) 119 | { 120 | COSTELLA_ERROR_FPRINT( pfileError ); 121 | COSTELLA_ANSI_RETURN( 0 ); 122 | } 123 | } 124 | COSTELLA_END_ANSI_FUNCTION( !0 ) 125 | 126 | 127 | 128 | /* costella_image_chrominance_magic_upsample: 129 | ** 130 | ** Public interface for upsampling the chrominance of a COSTELLA_IMAGE 131 | ** using the magic kernel. 132 | ** 133 | ** pi{In,Out}: Pointer to the {input,output} COSTELLA_IMAGE. May be the 134 | ** same. The input COSTELLA_IMAGE must be in the YCbCr colorspace, and 135 | ** must have downsampled chrominance (either nonreplicated or 136 | ** replicated). The output COSTELLA_IMAGE will be in the YCbCr 137 | ** colorspace, and will not have downsampled chrominance. 138 | */ 139 | 140 | COSTELLA_ANSI_FUNCTION( costella_image_chrominance_magic_upsample, int, ( 141 | COSTELLA_IMAGE* piIn, COSTELLA_IMAGE* piOut, int (*pfProgress)( void* 142 | pvPassback ), void* pvPassback, FILE* pfileError ) ) 143 | { 144 | COSTELLA_WRAP_PROGRESS wp; 145 | 146 | wp.pfProgress = pfProgress; 147 | wp.pvPassback = pvPassback; 148 | 149 | if( COSTELLA_CALL( CostellaImageChrominanceMagicUpsample( piIn, piOut, 150 | CostellaWrapProgress, &wp ) ) ) 151 | { 152 | COSTELLA_ERROR_FPRINT( pfileError ); 153 | COSTELLA_ANSI_RETURN( 0 ); 154 | } 155 | } 156 | COSTELLA_END_ANSI_FUNCTION( !0 ) 157 | 158 | 159 | 160 | /* costella_image_chrominance_replicate_eq: 161 | ** 162 | ** Public interface for replicating the chrominance data in a YCbCr 163 | ** COSTELLA_IMAGE into the other positions of each 2 x 2 block. 164 | ** 165 | ** pi: Pointer to the COSTELLA_IMAGE. It must be in the YCbCr colorspace, 166 | ** and must have nonreplicated downsampled chrominance. On exit from the 167 | ** function, it will still be in the YCbCr colorspace, and will have 168 | ** replicated downsampled chrominance. 169 | */ 170 | 171 | COSTELLA_ANSI_FUNCTION( costella_image_chrominance_replicate_eq, int, ( 172 | COSTELLA_IMAGE* pi, int (*pfProgress)( void* pvPassback ), void* 173 | pvPassback, FILE* pfileError ) ) 174 | { 175 | COSTELLA_WRAP_PROGRESS wp; 176 | 177 | wp.pfProgress = pfProgress; 178 | wp.pvPassback = pvPassback; 179 | 180 | if( COSTELLA_CALL( CostellaImageChrominanceReplicateEq( pi, 181 | CostellaWrapProgress, &wp ) ) ) 182 | { 183 | COSTELLA_ERROR_FPRINT( pfileError ); 184 | COSTELLA_ANSI_RETURN( 0 ); 185 | } 186 | } 187 | COSTELLA_END_ANSI_FUNCTION( !0 ) 188 | 189 | 190 | 191 | /* CostellaImageChrominanceInitialize: 192 | ** 193 | ** Initialize the library. 194 | */ 195 | 196 | COSTELLA_FUNCTION( CostellaImageChrominanceInitialize, ( void ) ) 197 | { 198 | COSTELLA_SW sw; 199 | COSTELLA_SW* pswMult3, * pswMult9Add8; 200 | 201 | 202 | /* Do nothing if already initialized. 203 | */ 204 | 205 | if( gbInitialized ) 206 | { 207 | COSTELLA_RETURN; 208 | } 209 | 210 | 211 | /* Set initialized flag. 212 | */ 213 | 214 | gbInitialized = COSTELLA_TRUE; 215 | 216 | 217 | /* Initialize other libraries. 218 | */ 219 | 220 | if( COSTELLA_CALL( CostellaImageInitialize() ) || COSTELLA_CALL( 221 | CostellaWrapInitialize() ) ) 222 | { 223 | COSTELLA_ERROR( "Initializing" ); 224 | gbInitialized = COSTELLA_FALSE; 225 | COSTELLA_RETURN; 226 | } 227 | 228 | 229 | /* Allocate arrays for the magic kernel. 230 | */ 231 | 232 | if( COSTELLA_MALLOC( gaswCostellaImageChrominanceMult9Add8, 256 ) || 233 | COSTELLA_MALLOC( gaswCostellaImageChrominanceMult3, 256 ) ) 234 | { 235 | COSTELLA_FUNDAMENTAL_ERROR( "Allocating" ); 236 | 237 | if( COSTELLA_FREE( gaswCostellaImageChrominanceMult9Add8 ) || 238 | COSTELLA_FREE( gaswCostellaImageChrominanceMult3 ) ) 239 | { 240 | COSTELLA_CLEANUP_FUNDAMENTAL_ERROR( "Freeing" ); 241 | } 242 | 243 | COSTELLA_RETURN; 244 | } 245 | 246 | 247 | /* Create the multiplication tables for the magic kernel. 248 | */ 249 | 250 | for( sw = 0, pswMult3 = gaswCostellaImageChrominanceMult3, pswMult9Add8 = 251 | gaswCostellaImageChrominanceMult9Add8; sw < 256; sw++, pswMult3++, 252 | pswMult9Add8++ ) 253 | { 254 | *pswMult3 = 3 * sw; 255 | *pswMult9Add8 = 9 * sw + 8; 256 | } 257 | } 258 | COSTELLA_END_FUNCTION 259 | 260 | 261 | 262 | /* CostellaImageChrominanceFinalize: 263 | ** 264 | ** Finalize the library. 265 | */ 266 | 267 | COSTELLA_FUNCTION( CostellaImageChrominanceFinalize, ( void ) ) 268 | { 269 | /* Do nothing if not initialized. 270 | */ 271 | 272 | if( !gbInitialized ) 273 | { 274 | COSTELLA_RETURN; 275 | } 276 | 277 | 278 | /* Clear initialized flag. 279 | */ 280 | 281 | gbInitialized = COSTELLA_FALSE; 282 | 283 | 284 | /* Free arrays for the magic kernel. 285 | */ 286 | 287 | if( COSTELLA_FREE( gaswCostellaImageChrominanceMult9Add8 ) || 288 | COSTELLA_FREE( gaswCostellaImageChrominanceMult3 ) ) 289 | { 290 | COSTELLA_FUNDAMENTAL_ERROR( "Freeing" ); 291 | COSTELLA_RETURN; 292 | } 293 | 294 | 295 | /* Finalize other libraries. 296 | */ 297 | 298 | if( COSTELLA_CALL( CostellaWrapFinalize() ) || COSTELLA_CALL( 299 | CostellaImageFinalize() ) ) 300 | { 301 | COSTELLA_ERROR( "Finalizing" ); 302 | COSTELLA_RETURN; 303 | } 304 | } 305 | COSTELLA_END_FUNCTION 306 | 307 | 308 | 309 | /* CostellaImageChrominanceAverageDownsampleReplicate: 310 | ** 311 | ** Downsample the chrominance of a COSTELLA_IMAGE by simple averaging, and 312 | *** replicate the downsampled chrominance data into each pixel of each 313 | ** 2 x 2 block. 314 | ** 315 | ** pi{In,Out}: Pointer to the {input,output} COSTELLA_IMAGE. May be the 316 | ** same. The input COSTELLA_IMAGE must be in the YCbCr colorspace, and 317 | ** must not have downsampled chrominance. The output COSTELLA_IMAGE will 318 | ** be in the YCbCr colorspace, and will have replicated downsampled 319 | ** chrominance. 320 | */ 321 | 322 | COSTELLA_FUNCTION( CostellaImageChrominanceAverageDownsampleReplicate, ( 323 | COSTELLA_IMAGE* piIn, COSTELLA_IMAGE* piOut, COSTELLA_CALLBACK_FUNCTION 324 | pfProgress, COSTELLA_O* poPassback ) ) 325 | { 326 | COSTELLA_B bAlpha, bCopyAlpha, bLastRow, bLastColumn; 327 | COSTELLA_UB ubYA, ubYB, ubYC, ubYD, ubCbA, ubCbB, ubCbC, ubCbD, ubCrA, 328 | ubCrB, ubCrC, ubCrD, ubAA = 0, ubAB = 0, ubAC = 0, ubAD = 0, 329 | ubCbAverage, ubCrAverage; 330 | COSTELLA_UD udWidth, udHeight, udColumn, udRow, udWidthMinusOne, 331 | udHeightMinusOne; 332 | COSTELLA_SD sdRowStrideIn, sdAlphaRowStrideIn, sdRowStrideOut, 333 | sdAlphaRowStrideOut, sdDoubleRowStrideIn, sdDoubleRowStrideOut; 334 | COSTELLA_IMAGE_ALPHA* piaIn, * piaOut; 335 | COSTELLA_IMAGE_COLOR* picIn, * picOut; 336 | COSTELLA_IMAGE_ALPHA_PIXEL iapIn, iapInStart, iapOut, iapOutStart; 337 | COSTELLA_IMAGE_COLOR_PIXEL icpIn, icpInStart, icpOut, icpOutStart; 338 | 339 | 340 | /* Keep GCC happy. 341 | */ 342 | 343 | iapIn = iapInStart = iapOut = iapOutStart = giapCostellaImageNull; 344 | icpIn = icpInStart = icpOut = icpOutStart = gicpCostellaImageNull; 345 | 346 | 347 | /* Check initialization and pointers. 348 | */ 349 | 350 | #ifdef COSTELLA_DEBUG 351 | { 352 | if( !gbInitialized ) 353 | { 354 | COSTELLA_FUNDAMENTAL_ERROR( "Initialization" ); 355 | COSTELLA_RETURN; 356 | } 357 | 358 | if( !piIn ) 359 | { 360 | COSTELLA_FUNDAMENTAL_ERROR( "Null piIn" ); 361 | COSTELLA_RETURN; 362 | } 363 | 364 | if( !piOut ) 365 | { 366 | COSTELLA_FUNDAMENTAL_ERROR( "Null piOut" ); 367 | COSTELLA_RETURN; 368 | } 369 | } 370 | #endif 371 | 372 | 373 | /* Check that the images are color. 374 | */ 375 | 376 | #ifdef COSTELLA_DEBUG 377 | { 378 | if( !piIn->bColor ) 379 | { 380 | COSTELLA_FUNDAMENTAL_ERROR( "Input image not color" ); 381 | COSTELLA_RETURN; 382 | } 383 | 384 | if( !piOut->bColor ) 385 | { 386 | COSTELLA_FUNDAMENTAL_ERROR( "Output image not color" ); 387 | COSTELLA_RETURN; 388 | } 389 | } 390 | #endif 391 | 392 | 393 | /* Check that the input image is in the YCbCr colorspace. 394 | */ 395 | 396 | #ifdef COSTELLA_DEBUG 397 | { 398 | if( piIn->bRgb ) 399 | { 400 | COSTELLA_FUNDAMENTAL_ERROR( "Input image not YCbCr" ); 401 | COSTELLA_RETURN; 402 | } 403 | } 404 | #endif 405 | 406 | 407 | /* Check that the input image does not already have downsampled 408 | ** chrominance data. 409 | */ 410 | 411 | #ifdef COSTELLA_DEBUG 412 | { 413 | if( piIn->bDownsampledChrominance ) 414 | { 415 | COSTELLA_FUNDAMENTAL_ERROR( "Input image already downsampled" ); 416 | COSTELLA_RETURN; 417 | } 418 | } 419 | #endif 420 | 421 | 422 | /* Set the output image to be in the YCbCr colorspace. 423 | */ 424 | 425 | piOut->bRgb = COSTELLA_FALSE; 426 | 427 | 428 | /* Flag that the output image will have replicated downsampled chrominance 429 | ** data. 430 | */ 431 | 432 | piOut->bDownsampledChrominance = COSTELLA_TRUE; 433 | piOut->bNonreplicatedDownsampledChrominance = COSTELLA_FALSE; 434 | 435 | 436 | /* Extract data. 437 | */ 438 | 439 | bAlpha = piIn->bAlpha; 440 | 441 | udWidth = piIn->udWidth; 442 | udHeight = piIn->udHeight; 443 | 444 | sdRowStrideIn = piIn->sdRowStride; 445 | sdAlphaRowStrideIn = piIn->sdAlphaRowStride; 446 | 447 | sdRowStrideOut = piOut->sdRowStride; 448 | sdAlphaRowStrideOut = piOut->sdAlphaRowStride; 449 | 450 | piaIn = &piIn->ia; 451 | picIn = &piIn->ic; 452 | 453 | piaOut = &piOut->ia; 454 | picOut = &piOut->ic; 455 | 456 | 457 | /* Check that the output image details agree. 458 | */ 459 | 460 | #ifdef COSTELLA_DEBUG 461 | { 462 | if( !piOut->bAlpha != !bAlpha ) 463 | { 464 | COSTELLA_FUNDAMENTAL_ERROR( "Alpha flags don't match" ); 465 | COSTELLA_RETURN; 466 | } 467 | 468 | if( piOut->udWidth != udWidth || piOut->udHeight != udHeight ) 469 | { 470 | COSTELLA_FUNDAMENTAL_ERROR( "Dimensions don't match" ); 471 | COSTELLA_RETURN; 472 | } 473 | } 474 | #endif 475 | 476 | 477 | /* Determine whether we need to copy alpha channel data. 478 | */ 479 | 480 | bCopyAlpha = bAlpha && !COSTELLA_IMAGE_ALPHA_IS_SAME( *piaIn, *piaOut ); 481 | 482 | 483 | /* Compute the double row strides. 484 | */ 485 | 486 | sdDoubleRowStrideIn = sdRowStrideIn << 1; 487 | sdDoubleRowStrideOut = sdRowStrideOut << 1; 488 | 489 | 490 | /* Compute convenient constants. 491 | */ 492 | 493 | udWidthMinusOne = udWidth - 1; 494 | udHeightMinusOne = udHeight - 1; 495 | 496 | 497 | /* Start at the top-left corner. 498 | */ 499 | 500 | COSTELLA_IMAGE_COLOR_PIXEL_SET_TOP_LEFT( icpInStart, *picIn, udWidth, 501 | udHeight, sdRowStrideIn ); 502 | COSTELLA_IMAGE_COLOR_PIXEL_SET_TOP_LEFT( icpOutStart, *picOut, udWidth, 503 | udHeight, sdRowStrideOut ); 504 | 505 | if( bCopyAlpha ) 506 | { 507 | COSTELLA_IMAGE_ALPHA_PIXEL_SET_TOP_LEFT( iapInStart, *piaIn, udWidth, 508 | udHeight, sdAlphaRowStrideIn ); 509 | COSTELLA_IMAGE_ALPHA_PIXEL_SET_TOP_LEFT( iapOutStart, *piaOut, udWidth, 510 | udHeight, sdAlphaRowStrideOut ); 511 | } 512 | 513 | 514 | /* Walk through the downsampled rows of the image. 515 | */ 516 | 517 | for( udRow = 0; udRow < udHeight; udRow += 2 ) 518 | { 519 | /* Progress callback. 520 | */ 521 | 522 | if( pfProgress && COSTELLA_CALL( pfProgress( poPassback ) ) ) 523 | { 524 | COSTELLA_ERROR( "Progress callback" ) 525 | COSTELLA_RETURN; 526 | } 527 | 528 | 529 | /* Check if we are in the last row. 530 | */ 531 | 532 | bLastRow = udRow == udHeightMinusOne; 533 | 534 | 535 | /* Start at the left of this row. 536 | */ 537 | 538 | COSTELLA_IMAGE_COLOR_PIXEL_ASSIGN( icpInStart, icpIn ); 539 | COSTELLA_IMAGE_COLOR_PIXEL_ASSIGN( icpOutStart, icpOut ); 540 | 541 | if( bCopyAlpha ) 542 | { 543 | COSTELLA_IMAGE_ALPHA_PIXEL_ASSIGN( iapInStart, iapIn ); 544 | COSTELLA_IMAGE_ALPHA_PIXEL_ASSIGN( iapOutStart, iapOut ); 545 | } 546 | 547 | 548 | /* Walk through the downsampled columns of the image. 549 | */ 550 | 551 | for( udColumn = 0; udColumn < udWidth; udColumn += 2 ) 552 | { 553 | /* Check if we are in the last column. 554 | */ 555 | 556 | bLastColumn = udColumn == udWidthMinusOne; 557 | 558 | 559 | /* Extract the top-left pixel's components. 560 | */ 561 | 562 | ubYA = COSTELLA_IMAGE_COLOR_PIXEL_GET_R_Y( icpIn ); 563 | ubCbA = COSTELLA_IMAGE_COLOR_PIXEL_GET_G_CB( icpIn ); 564 | ubCrA = COSTELLA_IMAGE_COLOR_PIXEL_GET_B_CR( icpIn ); 565 | 566 | if( bCopyAlpha ) 567 | { 568 | ubAA = COSTELLA_IMAGE_ALPHA_PIXEL_GET_A( iapIn ); 569 | } 570 | 571 | 572 | /* Check if we are in the last row. 573 | */ 574 | 575 | if( bLastRow ) 576 | { 577 | /* In the last row. Check if we are in the last column. 578 | */ 579 | 580 | if( bLastColumn ) 581 | { 582 | /* We are in the last row and the last column. The average is 583 | ** simply the top-left pixel, i.e., the only pixel. Store it. 584 | */ 585 | 586 | COSTELLA_IMAGE_COLOR_PIXEL_SET_RGB_YCBCR( icpOut, ubYA, ubCbA, 587 | ubCrA ); 588 | 589 | if( bCopyAlpha ) 590 | { 591 | COSTELLA_IMAGE_ALPHA_PIXEL_SET_A( iapOut, ubAA ); 592 | } 593 | } 594 | else 595 | { 596 | /* We are in the last row, but not the last column. Average the 597 | ** chrominance values of the two pixels in this row. Move right. 598 | */ 599 | 600 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_RIGHT( icpIn ); 601 | 602 | if( bCopyAlpha ) 603 | { 604 | COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_RIGHT( iapIn ); 605 | } 606 | 607 | 608 | /* Extract the top-right pixel's components. 609 | */ 610 | 611 | ubYD = COSTELLA_IMAGE_COLOR_PIXEL_GET_R_Y( icpIn ); 612 | ubCbD = COSTELLA_IMAGE_COLOR_PIXEL_GET_G_CB( icpIn ); 613 | ubCrD = COSTELLA_IMAGE_COLOR_PIXEL_GET_B_CR( icpIn ); 614 | 615 | if( bCopyAlpha ) 616 | { 617 | ubAD = COSTELLA_IMAGE_ALPHA_PIXEL_GET_A( iapIn ); 618 | } 619 | 620 | 621 | /* Move right for the next block. 622 | */ 623 | 624 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_RIGHT( icpIn ); 625 | 626 | if( bCopyAlpha ) 627 | { 628 | COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_RIGHT( iapIn ); 629 | } 630 | 631 | 632 | /* Average the two pixels. 633 | */ 634 | 635 | ubCbAverage = (COSTELLA_UB) ( ( (COSTELLA_UW) ubCbA + 636 | (COSTELLA_UW) ubCbD + 1 ) >> 1 ); 637 | ubCrAverage = (COSTELLA_UB) ( ( (COSTELLA_UW) ubCrA + 638 | (COSTELLA_UW) ubCrD + 1 ) >> 1 ); 639 | 640 | 641 | /* Store the average chrominance values, together with the 642 | ** original (unchanged) two luminance values, and original 643 | ** (unchanged) alpha values, if needed, in the two output pixel 644 | ** locations. Start with the top-left pixel. 645 | */ 646 | 647 | COSTELLA_IMAGE_COLOR_PIXEL_SET_RGB_YCBCR( icpOut, ubYA, 648 | ubCbAverage, ubCrAverage ); 649 | 650 | if( bCopyAlpha ) 651 | { 652 | COSTELLA_IMAGE_ALPHA_PIXEL_SET_A( iapOut, ubAA ); 653 | } 654 | 655 | 656 | /* Move right. 657 | */ 658 | 659 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_RIGHT( icpOut ); 660 | 661 | if( bCopyAlpha ) 662 | { 663 | COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_RIGHT( iapOut ); 664 | } 665 | 666 | 667 | /* Store the top-right pixel. 668 | */ 669 | 670 | COSTELLA_IMAGE_COLOR_PIXEL_SET_RGB_YCBCR( icpOut, ubYD, 671 | ubCbAverage, ubCrAverage ); 672 | 673 | if( bCopyAlpha ) 674 | { 675 | COSTELLA_IMAGE_ALPHA_PIXEL_SET_A( iapOut, ubAD ); 676 | } 677 | 678 | 679 | /* Move right for the next 2 x 2 block. 680 | */ 681 | 682 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_RIGHT( icpOut ); 683 | 684 | if( bCopyAlpha ) 685 | { 686 | COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_RIGHT( iapOut ); 687 | } 688 | } 689 | } 690 | else 691 | { 692 | /* Not in the last row. Check if we are in the last column. 693 | */ 694 | 695 | if( bLastColumn ) 696 | { 697 | /* We are in the last column, but not the last row. Average the 698 | ** chrominance values of the two pixels in this column. Move down. 699 | */ 700 | 701 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_DOWN( icpIn, sdRowStrideIn ); 702 | 703 | if( bCopyAlpha ) 704 | { 705 | COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_DOWN( iapIn, sdAlphaRowStrideIn 706 | ); 707 | } 708 | 709 | /* Extract the bottom-left pixel's components. 710 | */ 711 | 712 | ubYB = COSTELLA_IMAGE_COLOR_PIXEL_GET_R_Y( icpIn ); 713 | ubCbB = COSTELLA_IMAGE_COLOR_PIXEL_GET_G_CB( icpIn ); 714 | ubCrB = COSTELLA_IMAGE_COLOR_PIXEL_GET_B_CR( icpIn ); 715 | 716 | if( bCopyAlpha ) 717 | { 718 | ubAB = COSTELLA_IMAGE_ALPHA_PIXEL_GET_A( iapIn ); 719 | } 720 | 721 | 722 | /* Average the two pixels. 723 | */ 724 | 725 | ubCbAverage = (COSTELLA_UB) ( ( (COSTELLA_UW) ubCbA + 726 | (COSTELLA_UW) ubCbB + 1 ) >> 1 ); 727 | ubCrAverage = (COSTELLA_UB) ( ( (COSTELLA_UW) ubCrA + 728 | (COSTELLA_UW) ubCrB + 1 ) >> 1 ); 729 | 730 | 731 | /* Store the average chrominance values, together with the 732 | ** original (unchanged) two luminance values, and original 733 | ** (unchanged) alpha values, if needed, in the two output pixel 734 | ** locations. Start with the top-left pixel. 735 | */ 736 | 737 | COSTELLA_IMAGE_COLOR_PIXEL_SET_RGB_YCBCR( icpOut, ubYA, 738 | ubCbAverage, ubCrAverage ); 739 | 740 | if( bCopyAlpha ) 741 | { 742 | COSTELLA_IMAGE_ALPHA_PIXEL_SET_A( iapOut, ubAA ); 743 | } 744 | 745 | 746 | /* Move down. 747 | */ 748 | 749 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_DOWN( icpOut, sdRowStrideOut ); 750 | 751 | if( bCopyAlpha ) 752 | { 753 | COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_DOWN( iapOut, 754 | sdAlphaRowStrideOut ); 755 | } 756 | 757 | 758 | /* Store the bottom-left pixel. 759 | */ 760 | 761 | COSTELLA_IMAGE_COLOR_PIXEL_SET_RGB_YCBCR( icpOut, ubYB, 762 | ubCbAverage, ubCrAverage ); 763 | 764 | if( bCopyAlpha ) 765 | { 766 | COSTELLA_IMAGE_ALPHA_PIXEL_SET_A( iapOut, ubAB ); 767 | } 768 | } 769 | else 770 | { 771 | /* In neither the last row nor the last column. Move down. 772 | */ 773 | 774 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_DOWN( icpIn, sdRowStrideIn ); 775 | 776 | if( bCopyAlpha ) 777 | { 778 | COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_DOWN( iapIn, sdAlphaRowStrideIn 779 | ); 780 | } 781 | 782 | 783 | /* Extract the bottom-left pixel's components. 784 | */ 785 | 786 | ubYB = COSTELLA_IMAGE_COLOR_PIXEL_GET_R_Y( icpIn ); 787 | ubCbB = COSTELLA_IMAGE_COLOR_PIXEL_GET_G_CB( icpIn ); 788 | ubCrB = COSTELLA_IMAGE_COLOR_PIXEL_GET_B_CR( icpIn ); 789 | 790 | if( bCopyAlpha ) 791 | { 792 | ubAB = COSTELLA_IMAGE_ALPHA_PIXEL_GET_A( iapIn ); 793 | } 794 | 795 | 796 | /* Move right. 797 | */ 798 | 799 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_RIGHT( icpIn ); 800 | 801 | if( bCopyAlpha ) 802 | { 803 | COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_RIGHT( iapIn ); 804 | } 805 | 806 | 807 | /* Extract the bottom-right pixel's components. 808 | */ 809 | 810 | ubYC = COSTELLA_IMAGE_COLOR_PIXEL_GET_R_Y( icpIn ); 811 | ubCbC = COSTELLA_IMAGE_COLOR_PIXEL_GET_G_CB( icpIn ); 812 | ubCrC = COSTELLA_IMAGE_COLOR_PIXEL_GET_B_CR( icpIn ); 813 | 814 | if( bCopyAlpha ) 815 | { 816 | ubAC = COSTELLA_IMAGE_ALPHA_PIXEL_GET_A( iapIn ); 817 | } 818 | 819 | 820 | /* Move up. 821 | */ 822 | 823 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_UP( icpIn, sdRowStrideIn ); 824 | 825 | if( bCopyAlpha ) 826 | { 827 | COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_UP( iapIn, sdAlphaRowStrideIn ); 828 | } 829 | 830 | 831 | /* Extract the top-right pixel's components. 832 | */ 833 | 834 | ubYD = COSTELLA_IMAGE_COLOR_PIXEL_GET_R_Y( icpIn ); 835 | ubCbD = COSTELLA_IMAGE_COLOR_PIXEL_GET_G_CB( icpIn ); 836 | ubCrD = COSTELLA_IMAGE_COLOR_PIXEL_GET_B_CR( icpIn ); 837 | 838 | if( bCopyAlpha ) 839 | { 840 | ubAD = COSTELLA_IMAGE_ALPHA_PIXEL_GET_A( iapIn ); 841 | } 842 | 843 | 844 | /* Move right for the next 2 x 2 block. 845 | */ 846 | 847 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_RIGHT( icpIn ); 848 | 849 | if( bCopyAlpha ) 850 | { 851 | COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_RIGHT( iapIn ); 852 | } 853 | 854 | 855 | /* Average the four pixels. 856 | */ 857 | 858 | ubCbAverage = (COSTELLA_UB) ( ( (COSTELLA_UW) ubCbA + 859 | (COSTELLA_UW) ubCbB + (COSTELLA_UW) ubCbC + (COSTELLA_UW) ubCbD 860 | + 2 ) >> 2 ); 861 | ubCrAverage = (COSTELLA_UB) ( ( (COSTELLA_UW) ubCrA + 862 | (COSTELLA_UW) ubCrB + (COSTELLA_UW) ubCrC + (COSTELLA_UW) ubCrD 863 | + 2 ) >> 2 ); 864 | 865 | 866 | /* Store the average chrominance values, together with the 867 | ** original (unchanged) two luminance values, and original 868 | ** (unchanged) alpha values, if needed, in the two output pixel 869 | ** locations. Start with the top-left pixel. 870 | */ 871 | 872 | COSTELLA_IMAGE_COLOR_PIXEL_SET_RGB_YCBCR( icpOut, ubYA, 873 | ubCbAverage, ubCrAverage ); 874 | 875 | if( bCopyAlpha ) 876 | { 877 | COSTELLA_IMAGE_ALPHA_PIXEL_SET_A( iapOut, ubAA ); 878 | } 879 | 880 | 881 | /* Move down. 882 | */ 883 | 884 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_DOWN( icpOut, sdRowStrideOut ); 885 | 886 | if( bCopyAlpha ) 887 | { 888 | COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_DOWN( iapOut, 889 | sdAlphaRowStrideOut ); 890 | } 891 | 892 | 893 | /* Store the bottom-left pixel. 894 | */ 895 | 896 | COSTELLA_IMAGE_COLOR_PIXEL_SET_RGB_YCBCR( icpOut, ubYB, 897 | ubCbAverage, ubCrAverage ); 898 | 899 | if( bCopyAlpha ) 900 | { 901 | COSTELLA_IMAGE_ALPHA_PIXEL_SET_A( iapOut, ubAB ); 902 | } 903 | 904 | 905 | /* Move right. 906 | */ 907 | 908 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_RIGHT( icpOut ); 909 | 910 | if( bCopyAlpha ) 911 | { 912 | COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_RIGHT( iapOut ); 913 | } 914 | 915 | 916 | /* Store the bottom-right pixel. 917 | */ 918 | 919 | COSTELLA_IMAGE_COLOR_PIXEL_SET_RGB_YCBCR( icpOut, ubYC, 920 | ubCbAverage, ubCrAverage ); 921 | 922 | if( bCopyAlpha ) 923 | { 924 | COSTELLA_IMAGE_ALPHA_PIXEL_SET_A( iapOut, ubAC ); 925 | } 926 | 927 | 928 | /* Move up. 929 | */ 930 | 931 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_UP( icpOut, sdRowStrideOut ); 932 | 933 | if( bCopyAlpha ) 934 | { 935 | COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_UP( iapOut, sdAlphaRowStrideOut 936 | ); 937 | } 938 | 939 | 940 | /* Store the top-right pixel. 941 | */ 942 | 943 | COSTELLA_IMAGE_COLOR_PIXEL_SET_RGB_YCBCR( icpOut, ubYD, 944 | ubCbAverage, ubCrAverage ); 945 | 946 | if( bCopyAlpha ) 947 | { 948 | COSTELLA_IMAGE_ALPHA_PIXEL_SET_A( iapOut, ubAD ); 949 | } 950 | 951 | 952 | /* Move right for the next 2 x 2 block. 953 | */ 954 | 955 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_RIGHT( icpOut ); 956 | 957 | if( bCopyAlpha ) 958 | { 959 | COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_RIGHT( iapOut ); 960 | } 961 | } 962 | } 963 | } 964 | 965 | 966 | /* Walk down to the next row pair. 967 | */ 968 | 969 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_DOWN_TWO( icpInStart, 970 | sdDoubleRowStrideIn ); 971 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_DOWN_TWO( icpOutStart, 972 | sdDoubleRowStrideOut ); 973 | 974 | if( bCopyAlpha ) 975 | { 976 | COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_DOWN( iapInStart, sdAlphaRowStrideIn 977 | ); 978 | COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_DOWN( iapInStart, sdAlphaRowStrideIn 979 | ); 980 | COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_DOWN( iapOutStart, sdAlphaRowStrideOut 981 | ); 982 | COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_DOWN( iapOutStart, sdAlphaRowStrideOut 983 | ); 984 | } 985 | } 986 | } 987 | COSTELLA_END_FUNCTION 988 | 989 | 990 | 991 | /* CostellaImageChrominanceMagicUpsample: 992 | ** 993 | ** Upsample the chrominance channels of a YCbCr image using the magic 994 | ** kernel. 995 | ** 996 | ** pi{In,Out}: Pointer to the {input,output} COSTELLA_IMAGE. May be the 997 | ** same. The input COSTELLA_IMAGE must be in the YCbCr colorspace, and 998 | ** must have downsampled chrominance (either nonreplicated or 999 | ** replicated). The output COSTELLA_IMAGE will be in the YCbCr 1000 | ** colorspace, and will not have downsampled chrominance. 1001 | */ 1002 | 1003 | COSTELLA_FUNCTION( CostellaImageChrominanceMagicUpsample, ( COSTELLA_IMAGE* 1004 | piIn, COSTELLA_IMAGE* piOut, COSTELLA_CALLBACK_FUNCTION pfProgress, 1005 | COSTELLA_O* poPassback ) ) 1006 | { 1007 | COSTELLA_B bAlpha, bCopyY, bCopyAlpha, bTop, bLeft, bMissingLastColumn; 1008 | COSTELLA_UB ubY, ubCb, ubCr, ubA, ubCbA, ubCbB, ubCbC, ubCbD, ubCrA, 1009 | ubCrB, ubCrC, ubCrD, ubCbSavedLeft = 0, ubCrSavedLeft = 0; 1010 | COSTELLA_UB* pubCbBuffer, * pubCrBuffer, * pubCbBufferLeft, 1011 | * pubCrBufferLeft, * pubCbBufferRight, * pubCrBufferRight; 1012 | COSTELLA_UB* aubCbBuffer = 0, * aubCrBuffer = 0; 1013 | COSTELLA_UD udWidth, udHeight, udBufferWidth, udWidthMinusOne, 1014 | udHeightMinusOne, udRow, udColumn; 1015 | COSTELLA_SD sdRowStrideIn, sdRowStrideOut, sdAlphaRowStrideIn, 1016 | sdAlphaRowStrideOut; 1017 | COSTELLA_IMAGE_ALPHA* piaIn, * piaOut; 1018 | COSTELLA_IMAGE_COLOR* picIn, * picOut; 1019 | COSTELLA_IMAGE_ALPHA_PIXEL iapIn, iapInStart, iapOut, iapOutStart; 1020 | COSTELLA_IMAGE_COLOR_PIXEL icpIn, icpInTarget, icpInStart, icpOut, 1021 | icpOutStart; 1022 | 1023 | 1024 | /* Keep GCC happy. 1025 | */ 1026 | 1027 | iapIn = iapInStart = iapOut = iapOutStart = giapCostellaImageNull; 1028 | icpIn = icpInStart = icpOut = icpOutStart = gicpCostellaImageNull; 1029 | 1030 | 1031 | /* Check initialization and pointers. 1032 | */ 1033 | 1034 | #ifdef COSTELLA_DEBUG 1035 | { 1036 | if( !gbInitialized ) 1037 | { 1038 | COSTELLA_FUNDAMENTAL_ERROR( "Initialization" ); 1039 | COSTELLA_RETURN; 1040 | } 1041 | 1042 | if( !piIn ) 1043 | { 1044 | COSTELLA_FUNDAMENTAL_ERROR( "Null piIn" ); 1045 | COSTELLA_RETURN; 1046 | } 1047 | 1048 | if( !piOut ) 1049 | { 1050 | COSTELLA_FUNDAMENTAL_ERROR( "Null piOut" ); 1051 | COSTELLA_RETURN; 1052 | } 1053 | } 1054 | #endif 1055 | 1056 | 1057 | /* Check that the images are color. 1058 | */ 1059 | 1060 | #ifdef COSTELLA_DEBUG 1061 | { 1062 | if( !piIn->bColor ) 1063 | { 1064 | COSTELLA_FUNDAMENTAL_ERROR( "Input image not color" ); 1065 | COSTELLA_RETURN; 1066 | } 1067 | 1068 | if( !piOut->bColor ) 1069 | { 1070 | COSTELLA_FUNDAMENTAL_ERROR( "Output image not color" ); 1071 | COSTELLA_RETURN; 1072 | } 1073 | } 1074 | #endif 1075 | 1076 | 1077 | /* Check that the input image is in the YCbCr colorspace. 1078 | */ 1079 | 1080 | #ifdef COSTELLA_DEBUG 1081 | { 1082 | if( piIn->bRgb ) 1083 | { 1084 | COSTELLA_FUNDAMENTAL_ERROR( "Input image not YCbCr" ); 1085 | COSTELLA_RETURN; 1086 | } 1087 | } 1088 | #endif 1089 | 1090 | 1091 | /* Set the output image to be in the YCbCr colorspace. 1092 | */ 1093 | 1094 | piOut->bRgb = COSTELLA_FALSE; 1095 | 1096 | 1097 | /* Check that the input image has downsampled chrominance data. 1098 | */ 1099 | 1100 | #ifdef COSTELLA_DEBUG 1101 | { 1102 | if( !piIn->bDownsampledChrominance ) 1103 | { 1104 | COSTELLA_FUNDAMENTAL_ERROR( "Input image does not have downsampled " 1105 | "chrominance" ); 1106 | COSTELLA_RETURN; 1107 | } 1108 | } 1109 | #endif 1110 | 1111 | 1112 | /* Set the output image to not have downsampled chrominance data. 1113 | */ 1114 | 1115 | piOut->bDownsampledChrominance = COSTELLA_FALSE; 1116 | 1117 | 1118 | /* Extract data. 1119 | */ 1120 | 1121 | bAlpha = piIn->bAlpha; 1122 | 1123 | udWidth = piIn->udWidth; 1124 | udHeight = piIn->udHeight; 1125 | 1126 | sdRowStrideIn = piIn->sdRowStride; 1127 | sdAlphaRowStrideIn = piIn->sdAlphaRowStride; 1128 | 1129 | sdRowStrideOut = piOut->sdRowStride; 1130 | sdAlphaRowStrideOut = piOut->sdAlphaRowStride; 1131 | 1132 | piaIn = &piIn->ia; 1133 | picIn = &piIn->ic; 1134 | 1135 | piaOut = &piOut->ia; 1136 | picOut = &piOut->ic; 1137 | 1138 | 1139 | /* Check that the output image details agree. 1140 | */ 1141 | 1142 | #ifdef COSTELLA_DEBUG 1143 | { 1144 | if( !piOut->bAlpha != !bAlpha ) 1145 | { 1146 | COSTELLA_FUNDAMENTAL_ERROR( "Alpha flags don't match" ); 1147 | COSTELLA_RETURN; 1148 | } 1149 | 1150 | if( piOut->udWidth != udWidth || piOut->udHeight != udHeight ) 1151 | { 1152 | COSTELLA_FUNDAMENTAL_ERROR( "Dimensions don't match" ); 1153 | COSTELLA_RETURN; 1154 | } 1155 | } 1156 | #endif 1157 | 1158 | 1159 | /* Determine whether we need to copy luminance channel data. 1160 | */ 1161 | 1162 | bCopyY = !COSTELLA_IMAGE_COLOR_IS_SAME( *picIn, *picOut ); 1163 | 1164 | 1165 | /* Determine whether we need to copy alpha channel data. 1166 | */ 1167 | 1168 | bCopyAlpha = bAlpha && !COSTELLA_IMAGE_ALPHA_IS_SAME( *piaIn, *piaOut ); 1169 | 1170 | 1171 | /* Compute convenient constants. 1172 | */ 1173 | 1174 | udWidthMinusOne = udWidth - 1; 1175 | udHeightMinusOne = udHeight - 1; 1176 | 1177 | 1178 | /* Determine if we are missing the last column. 1179 | */ 1180 | 1181 | bMissingLastColumn = !!( udWidth % 2 ); 1182 | 1183 | 1184 | /* Compute buffer width. We need a buffer location for every two pixels 1185 | ** or part thereof. 1186 | */ 1187 | 1188 | udBufferWidth = ( udWidth + 1 ) >> 1; 1189 | 1190 | 1191 | /* Allocate buffer memory. 1192 | */ 1193 | 1194 | if( COSTELLA_MALLOC( aubCbBuffer, udBufferWidth ) || COSTELLA_MALLOC( 1195 | aubCrBuffer, udBufferWidth ) ) 1196 | { 1197 | COSTELLA_FUNDAMENTAL_ERROR( "Allocating" ); 1198 | 1199 | if( COSTELLA_FREE( aubCbBuffer ) || COSTELLA_FREE( aubCrBuffer ) ) 1200 | { 1201 | COSTELLA_CLEANUP_FUNDAMENTAL_ERROR( "Freeing" ); 1202 | } 1203 | 1204 | COSTELLA_RETURN; 1205 | } 1206 | 1207 | 1208 | /* Start at the top-left corner. 1209 | */ 1210 | 1211 | COSTELLA_IMAGE_COLOR_PIXEL_SET_TOP_LEFT( icpInStart, *picIn, udWidth, 1212 | udHeight, sdRowStrideIn ); 1213 | COSTELLA_IMAGE_COLOR_PIXEL_SET_TOP_LEFT( icpOutStart, *picOut, udWidth, 1214 | udHeight, sdRowStrideOut ); 1215 | 1216 | if( bCopyAlpha ) 1217 | { 1218 | COSTELLA_IMAGE_ALPHA_PIXEL_SET_TOP_LEFT( iapInStart, *piaIn, udWidth, 1219 | udHeight, sdAlphaRowStrideIn ); 1220 | COSTELLA_IMAGE_ALPHA_PIXEL_SET_TOP_LEFT( iapOutStart, *piaOut, udWidth, 1221 | udHeight, sdAlphaRowStrideOut ); 1222 | } 1223 | 1224 | 1225 | /* Walk through the rows. 1226 | */ 1227 | 1228 | for( udRow = 0, bTop = COSTELLA_TRUE; udRow < udHeight; udRow++, bTop = 1229 | !bTop ) 1230 | { 1231 | /* Progress callback. 1232 | */ 1233 | 1234 | if( pfProgress && COSTELLA_CALL( pfProgress( poPassback ) ) ) 1235 | { 1236 | COSTELLA_ERROR( "Progress callback" ) 1237 | COSTELLA_RETURN; 1238 | } 1239 | 1240 | 1241 | /* Start at the left of this row. 1242 | */ 1243 | 1244 | COSTELLA_IMAGE_COLOR_PIXEL_ASSIGN( icpInStart, icpInTarget ); 1245 | COSTELLA_IMAGE_COLOR_PIXEL_ASSIGN( icpOutStart, icpOut ); 1246 | 1247 | if( bCopyAlpha ) 1248 | { 1249 | COSTELLA_IMAGE_ALPHA_PIXEL_ASSIGN( iapInStart, iapIn ); 1250 | COSTELLA_IMAGE_ALPHA_PIXEL_ASSIGN( iapOutStart, iapOut ); 1251 | } 1252 | 1253 | 1254 | /* Walk through the columns of the image. 1255 | */ 1256 | 1257 | for( udColumn = 0, bLeft = COSTELLA_TRUE, pubCbBuffer = aubCbBuffer, 1258 | pubCrBuffer = aubCrBuffer, pubCbBufferLeft = aubCbBuffer - 1, 1259 | pubCrBufferLeft = aubCrBuffer - 1, pubCbBufferRight = aubCbBuffer + 1, 1260 | pubCrBufferRight = aubCrBuffer + 1; udColumn < udWidth; udColumn++, 1261 | bLeft = !bLeft ) 1262 | { 1263 | /* Switch on position in 2 x 2 block. 1264 | */ 1265 | 1266 | if( bTop ) 1267 | { 1268 | if( bLeft ) 1269 | { 1270 | /* Top-left. 1271 | */ 1272 | 1273 | ubCbA = COSTELLA_IMAGE_COLOR_PIXEL_GET_G_CB( icpInTarget ); 1274 | ubCrA = COSTELLA_IMAGE_COLOR_PIXEL_GET_B_CR( icpInTarget ); 1275 | 1276 | if( !udRow ) 1277 | { 1278 | ubCbB = ubCbA; 1279 | ubCrB = ubCrA; 1280 | } 1281 | else 1282 | { 1283 | ubCbB = *pubCbBuffer; 1284 | ubCrB = *pubCrBuffer; 1285 | } 1286 | 1287 | if( !udColumn ) 1288 | { 1289 | ubCbC = ubCbA; 1290 | ubCrC = ubCrA; 1291 | } 1292 | else 1293 | { 1294 | ubCbC = ubCbSavedLeft; 1295 | ubCrC = ubCrSavedLeft; 1296 | } 1297 | 1298 | if( !udColumn || !udRow ) 1299 | { 1300 | ubCbD = ubCbA; 1301 | ubCrD = ubCrA; 1302 | } 1303 | else 1304 | { 1305 | ubCbD = *pubCbBufferLeft; 1306 | ubCrD = *pubCrBufferLeft; 1307 | } 1308 | 1309 | 1310 | /* Store buffer values to our left. 1311 | */ 1312 | 1313 | if( udColumn ) 1314 | { 1315 | *pubCbBufferLeft = ubCbSavedLeft; 1316 | *pubCrBufferLeft = ubCrSavedLeft; 1317 | } 1318 | 1319 | 1320 | /* Store the current values as the new saved left values. 1321 | */ 1322 | 1323 | ubCbSavedLeft = ubCbA; 1324 | ubCrSavedLeft = ubCrA; 1325 | } 1326 | else 1327 | { 1328 | /* Top-right. 1329 | */ 1330 | 1331 | ubCbA = ubCbSavedLeft; 1332 | ubCrA = ubCrSavedLeft; 1333 | 1334 | if( !udRow ) 1335 | { 1336 | ubCbB = ubCbA; 1337 | ubCrB = ubCrA; 1338 | } 1339 | else 1340 | { 1341 | ubCbB = *pubCbBuffer; 1342 | ubCrB = *pubCrBuffer; 1343 | } 1344 | 1345 | if( udColumn == udWidthMinusOne ) 1346 | { 1347 | ubCbC = ubCbA; 1348 | ubCrC = ubCrA; 1349 | } 1350 | else 1351 | { 1352 | COSTELLA_IMAGE_COLOR_PIXEL_ASSIGN( icpInTarget, icpIn ); 1353 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_RIGHT( icpIn ); 1354 | 1355 | ubCbC = COSTELLA_IMAGE_COLOR_PIXEL_GET_G_CB( icpIn ); 1356 | ubCrC = COSTELLA_IMAGE_COLOR_PIXEL_GET_B_CR( icpIn ); 1357 | } 1358 | 1359 | if( udColumn == udWidthMinusOne || !udRow ) 1360 | { 1361 | ubCbD = ubCbA; 1362 | ubCrD = ubCrA; 1363 | } 1364 | else 1365 | { 1366 | ubCbD = *pubCbBufferRight; 1367 | ubCrD = *pubCrBufferRight; 1368 | } 1369 | } 1370 | } 1371 | else 1372 | { 1373 | if( bLeft ) 1374 | { 1375 | /* Bottom-left. 1376 | */ 1377 | 1378 | ubCbA = *pubCbBuffer; 1379 | ubCrA = *pubCrBuffer; 1380 | 1381 | if( udRow == udHeightMinusOne ) 1382 | { 1383 | ubCbB = ubCbA; 1384 | ubCrB = ubCrA; 1385 | } 1386 | else 1387 | { 1388 | COSTELLA_IMAGE_COLOR_PIXEL_ASSIGN( icpInTarget, icpIn ); 1389 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_DOWN( icpIn, sdRowStrideIn ); 1390 | 1391 | ubCbB = COSTELLA_IMAGE_COLOR_PIXEL_GET_G_CB( icpIn ); 1392 | ubCrB = COSTELLA_IMAGE_COLOR_PIXEL_GET_B_CR( icpIn ); 1393 | } 1394 | 1395 | if( !udColumn ) 1396 | { 1397 | ubCbC = ubCbA; 1398 | ubCrC = ubCrA; 1399 | } 1400 | else 1401 | { 1402 | ubCbC = *pubCbBufferLeft; 1403 | ubCrC = *pubCrBufferLeft; 1404 | } 1405 | 1406 | if( !udColumn || udRow == udHeightMinusOne ) 1407 | { 1408 | ubCbD = ubCbA; 1409 | ubCrD = ubCrA; 1410 | } 1411 | else 1412 | { 1413 | COSTELLA_IMAGE_COLOR_PIXEL_ASSIGN( icpInTarget, icpIn ); 1414 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_LEFT_TWO( icpIn ); 1415 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_DOWN( icpIn, sdRowStrideIn ); 1416 | 1417 | ubCbD = COSTELLA_IMAGE_COLOR_PIXEL_GET_G_CB( icpIn ); 1418 | ubCrD = COSTELLA_IMAGE_COLOR_PIXEL_GET_B_CR( icpIn ); 1419 | } 1420 | } 1421 | else 1422 | { 1423 | /* Bottom-right. 1424 | */ 1425 | 1426 | ubCbA = *pubCbBuffer; 1427 | ubCrA = *pubCrBuffer; 1428 | 1429 | if( udRow == udHeightMinusOne ) 1430 | { 1431 | ubCbB = ubCbA; 1432 | ubCrB = ubCrA; 1433 | } 1434 | else 1435 | { 1436 | COSTELLA_IMAGE_COLOR_PIXEL_ASSIGN( icpInTarget, icpIn ); 1437 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_LEFT( icpIn ); 1438 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_DOWN( icpIn, sdRowStrideIn ); 1439 | 1440 | ubCbB = COSTELLA_IMAGE_COLOR_PIXEL_GET_G_CB( icpIn ); 1441 | ubCrB = COSTELLA_IMAGE_COLOR_PIXEL_GET_B_CR( icpIn ); 1442 | } 1443 | 1444 | if( udColumn == udWidthMinusOne ) 1445 | { 1446 | ubCbC = ubCbA; 1447 | ubCrC = ubCrA; 1448 | } 1449 | else 1450 | { 1451 | ubCbC = *pubCbBufferRight; 1452 | ubCrC = *pubCrBufferRight; 1453 | } 1454 | 1455 | if( udColumn == udWidthMinusOne || udRow == udHeightMinusOne ) 1456 | { 1457 | ubCbD = ubCbA; 1458 | ubCrD = ubCrA; 1459 | } 1460 | else 1461 | { 1462 | COSTELLA_IMAGE_COLOR_PIXEL_ASSIGN( icpInTarget, icpIn ); 1463 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_RIGHT( icpIn ); 1464 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_DOWN( icpIn, sdRowStrideIn ); 1465 | 1466 | ubCbD = COSTELLA_IMAGE_COLOR_PIXEL_GET_G_CB( icpIn ); 1467 | ubCrD = COSTELLA_IMAGE_COLOR_PIXEL_GET_B_CR( icpIn ); 1468 | } 1469 | } 1470 | } 1471 | 1472 | 1473 | /* Combine the four pixels and divide by 16. 1474 | */ 1475 | 1476 | ubCb = (COSTELLA_UB) COSTELLA_SHIFT_RIGHT_FLOOR( 1477 | gaswCostellaImageChrominanceMult9Add8[ ubCbA ] + 1478 | gaswCostellaImageChrominanceMult3[ ubCbB ] + 1479 | gaswCostellaImageChrominanceMult3[ ubCbC ] + (COSTELLA_SW) ubCbD, 4 1480 | ); 1481 | ubCr = (COSTELLA_UB) COSTELLA_SHIFT_RIGHT_FLOOR( 1482 | gaswCostellaImageChrominanceMult9Add8[ ubCrA ] + 1483 | gaswCostellaImageChrominanceMult3[ ubCrB ] + 1484 | gaswCostellaImageChrominanceMult3[ ubCrC ] + (COSTELLA_SW) ubCrD, 4 1485 | ); 1486 | 1487 | 1488 | /* Store the values. 1489 | */ 1490 | 1491 | COSTELLA_IMAGE_COLOR_PIXEL_SET_G_CB( icpOut, ubCb ); 1492 | COSTELLA_IMAGE_COLOR_PIXEL_SET_B_CR( icpOut, ubCr ); 1493 | 1494 | if( bCopyY ) 1495 | { 1496 | ubY = COSTELLA_IMAGE_COLOR_PIXEL_GET_R_Y( icpInTarget ); 1497 | COSTELLA_IMAGE_COLOR_PIXEL_SET_R_Y( icpOut, ubY ); 1498 | } 1499 | 1500 | if( bCopyAlpha ) 1501 | { 1502 | ubA = COSTELLA_IMAGE_ALPHA_PIXEL_GET_A( iapIn ); 1503 | COSTELLA_IMAGE_ALPHA_PIXEL_SET_A( iapOut, ubA ); 1504 | } 1505 | 1506 | 1507 | /* If we in a right column, update the buffer position. 1508 | */ 1509 | 1510 | if( !bLeft ) 1511 | { 1512 | pubCbBuffer++; 1513 | pubCrBuffer++; 1514 | 1515 | pubCbBufferLeft++; 1516 | pubCrBufferLeft++; 1517 | 1518 | pubCbBufferRight++; 1519 | pubCrBufferRight++; 1520 | } 1521 | 1522 | 1523 | /* Move right. 1524 | */ 1525 | 1526 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_RIGHT( icpInTarget ); 1527 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_RIGHT( icpOut ); 1528 | 1529 | if( bCopyAlpha ) 1530 | { 1531 | COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_RIGHT( iapIn ); 1532 | COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_RIGHT( iapOut ); 1533 | } 1534 | } 1535 | 1536 | 1537 | /* Store the last buffer values. 1538 | */ 1539 | 1540 | if( bTop ) 1541 | { 1542 | if( bMissingLastColumn ) 1543 | { 1544 | pubCbBufferLeft++; 1545 | pubCrBufferLeft++; 1546 | } 1547 | 1548 | *pubCbBufferLeft = ubCbSavedLeft; 1549 | *pubCrBufferLeft = ubCrSavedLeft; 1550 | } 1551 | 1552 | 1553 | /* Walk down to the next row. 1554 | */ 1555 | 1556 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_DOWN( icpInStart, sdRowStrideIn ); 1557 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_DOWN( icpOutStart, sdRowStrideOut ); 1558 | 1559 | if( bCopyAlpha ) 1560 | { 1561 | COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_DOWN( iapInStart, sdAlphaRowStrideIn 1562 | ); 1563 | COSTELLA_IMAGE_ALPHA_PIXEL_MOVE_DOWN( iapOutStart, sdAlphaRowStrideOut 1564 | ); 1565 | } 1566 | } 1567 | 1568 | 1569 | /* Free buffers. 1570 | */ 1571 | 1572 | if( COSTELLA_FREE( aubCbBuffer ) || COSTELLA_FREE( aubCrBuffer ) ) 1573 | { 1574 | COSTELLA_ERROR( "Freeing" ) 1575 | COSTELLA_RETURN; 1576 | } 1577 | } 1578 | COSTELLA_END_FUNCTION 1579 | 1580 | 1581 | 1582 | /* CostellaImageChrominanceReplicateEq: 1583 | ** 1584 | ** Public interface for replicating the YCbCr data in a COSTELLA_IMAGE 1585 | ** into the other positions of each 2 x 2 block. 1586 | ** 1587 | ** pi: Pointer to the COSTELLA_IMAGE. It must be in the YCbCr colorspace, 1588 | ** and must have nonreplicated downsampled chrominance. On exit from the 1589 | ** function, it will still be in the YCbCr colorspace, and will have 1590 | ** replicated downsampled chrominance. 1591 | */ 1592 | 1593 | COSTELLA_FUNCTION( CostellaImageChrominanceReplicateEq, ( COSTELLA_IMAGE* 1594 | pi, COSTELLA_CALLBACK_FUNCTION pfProgress, COSTELLA_O* poPassback ) ) 1595 | { 1596 | COSTELLA_B bLastRow, bLastColumn; 1597 | COSTELLA_UB ubCb, ubCr; 1598 | COSTELLA_UD udWidth, udHeight, udColumn, udRow, udWidthMinusOne, 1599 | udHeightMinusOne; 1600 | COSTELLA_SD sdRowStride, sdDoubleRowStride; 1601 | COSTELLA_IMAGE_COLOR* pic; 1602 | COSTELLA_IMAGE_COLOR_PIXEL icp, icpStart; 1603 | 1604 | 1605 | /* Keep GCC happy. 1606 | */ 1607 | 1608 | icp = icpStart = gicpCostellaImageNull; 1609 | 1610 | 1611 | /* Check initialization and pointers. 1612 | */ 1613 | 1614 | #ifdef COSTELLA_DEBUG 1615 | { 1616 | if( !gbInitialized ) 1617 | { 1618 | COSTELLA_FUNDAMENTAL_ERROR( "Initialization" ); 1619 | COSTELLA_RETURN; 1620 | } 1621 | 1622 | if( !pi ) 1623 | { 1624 | COSTELLA_FUNDAMENTAL_ERROR( "Null image" ); 1625 | COSTELLA_RETURN; 1626 | } 1627 | } 1628 | #endif 1629 | 1630 | 1631 | /* Check that the image is color. 1632 | */ 1633 | 1634 | #ifdef COSTELLA_DEBUG 1635 | { 1636 | if( !pi->bColor ) 1637 | { 1638 | COSTELLA_FUNDAMENTAL_ERROR( "Image not color" ); 1639 | COSTELLA_RETURN; 1640 | } 1641 | } 1642 | #endif 1643 | 1644 | 1645 | /* Check that the image is in the YCbCr colorspace. 1646 | */ 1647 | 1648 | #ifdef COSTELLA_DEBUG 1649 | { 1650 | if( pi->bRgb ) 1651 | { 1652 | COSTELLA_FUNDAMENTAL_ERROR( "Image is RGB" ); 1653 | COSTELLA_RETURN; 1654 | } 1655 | } 1656 | #endif 1657 | 1658 | 1659 | /* Check that the image has downsampled chrominance data. 1660 | */ 1661 | 1662 | #ifdef COSTELLA_DEBUG 1663 | { 1664 | if( !pi->bDownsampledChrominance ) 1665 | { 1666 | COSTELLA_FUNDAMENTAL_ERROR( "Input image has downsampled data" ); 1667 | COSTELLA_RETURN; 1668 | } 1669 | } 1670 | #endif 1671 | 1672 | 1673 | /* Check that the image has nonreplicated downsampled chrominance data. 1674 | */ 1675 | 1676 | #ifdef COSTELLA_DEBUG 1677 | { 1678 | if( !pi->bNonreplicatedDownsampledChrominance ) 1679 | { 1680 | COSTELLA_FUNDAMENTAL_ERROR( "Input image already replicated" ); 1681 | COSTELLA_RETURN; 1682 | } 1683 | } 1684 | #endif 1685 | 1686 | 1687 | /* Set the image to now have replicated chrominance data. 1688 | */ 1689 | 1690 | pi->bNonreplicatedDownsampledChrominance = COSTELLA_FALSE; 1691 | 1692 | 1693 | /* Extract data. 1694 | */ 1695 | 1696 | udWidth = pi->udWidth; 1697 | udHeight = pi->udHeight; 1698 | 1699 | sdRowStride = pi->sdRowStride; 1700 | 1701 | pic = &pi->ic; 1702 | 1703 | 1704 | /* Compute the double row stride. 1705 | */ 1706 | 1707 | sdDoubleRowStride = sdRowStride << 1; 1708 | 1709 | 1710 | /* Compute convenient constants. 1711 | */ 1712 | 1713 | udWidthMinusOne = udWidth - 1; 1714 | udHeightMinusOne = udHeight - 1; 1715 | 1716 | 1717 | /* Start at the top-left corner. 1718 | */ 1719 | 1720 | COSTELLA_IMAGE_COLOR_PIXEL_SET_TOP_LEFT( icpStart, *pic, udWidth, 1721 | udHeight, sdRowStride ); 1722 | 1723 | 1724 | /* Walk through the downsampled rows of the image. 1725 | */ 1726 | 1727 | for( udRow = 0; udRow < udHeight; udRow += 2 ) 1728 | { 1729 | /* Progress callback. 1730 | */ 1731 | 1732 | if( pfProgress && COSTELLA_CALL( pfProgress( poPassback ) ) ) 1733 | { 1734 | COSTELLA_ERROR( "Progress callback" ) 1735 | COSTELLA_RETURN; 1736 | } 1737 | 1738 | 1739 | /* Check if we are in the last row. 1740 | */ 1741 | 1742 | bLastRow = udRow == udHeightMinusOne; 1743 | 1744 | 1745 | /* Start at the left of this row. 1746 | */ 1747 | 1748 | COSTELLA_IMAGE_COLOR_PIXEL_ASSIGN( icpStart, icp ); 1749 | 1750 | 1751 | /* Walk through the downsampled columns of the image. 1752 | */ 1753 | 1754 | for( udColumn = 0; udColumn < udWidth; udColumn += 2 ) 1755 | { 1756 | /* Check if we are in the last column. 1757 | */ 1758 | 1759 | bLastColumn = udColumn == udWidthMinusOne; 1760 | 1761 | 1762 | /* Extract the chrominance components for this block. 1763 | */ 1764 | 1765 | ubCb = COSTELLA_IMAGE_COLOR_PIXEL_GET_G_CB( icp ); 1766 | ubCr = COSTELLA_IMAGE_COLOR_PIXEL_GET_B_CR( icp ); 1767 | 1768 | 1769 | /* Check if we are in the last row. 1770 | */ 1771 | 1772 | if( bLastRow ) 1773 | { 1774 | /* In the last row. Check if we are in the last column. 1775 | */ 1776 | 1777 | if( bLastColumn ) 1778 | { 1779 | /* We are in the last row and the last column. Nothing needs to 1780 | ** be done. 1781 | */ 1782 | } 1783 | else 1784 | { 1785 | /* We are in the last row, but not the last column. Replicate the 1786 | ** values into the top-right pixel. Move right. 1787 | */ 1788 | 1789 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_RIGHT( icp ); 1790 | 1791 | 1792 | /* Store the chrominance values in the top-right pixel. 1793 | */ 1794 | 1795 | COSTELLA_IMAGE_COLOR_PIXEL_SET_G_CB( icp, ubCb ); 1796 | COSTELLA_IMAGE_COLOR_PIXEL_SET_B_CR( icp, ubCr ); 1797 | 1798 | 1799 | /* Move right for the next 2 x 2 block. 1800 | */ 1801 | 1802 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_RIGHT( icp ); 1803 | } 1804 | } 1805 | else 1806 | { 1807 | /* Not in the last row. Check if we are in the last column. 1808 | */ 1809 | 1810 | if( bLastColumn ) 1811 | { 1812 | /* We are in the last column, but not the last row. Replicate the 1813 | ** values into the bottom-left pixel. Move down. 1814 | */ 1815 | 1816 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_DOWN( icp, sdRowStride ); 1817 | 1818 | 1819 | /* Store the chrominance values in the bottom-left pixel. 1820 | */ 1821 | 1822 | COSTELLA_IMAGE_COLOR_PIXEL_SET_G_CB( icp, ubCb ); 1823 | COSTELLA_IMAGE_COLOR_PIXEL_SET_B_CR( icp, ubCr ); 1824 | } 1825 | else 1826 | { 1827 | /* In neither the last row nor the last column. Replicate the 1828 | ** chrominance values into the other three pixels in this block. 1829 | ** Move down. 1830 | */ 1831 | 1832 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_DOWN( icp, sdRowStride ); 1833 | 1834 | 1835 | /* Store the bottom-left pixel. 1836 | */ 1837 | 1838 | COSTELLA_IMAGE_COLOR_PIXEL_SET_G_CB( icp, ubCb ); 1839 | COSTELLA_IMAGE_COLOR_PIXEL_SET_B_CR( icp, ubCr ); 1840 | 1841 | 1842 | /* Move right. 1843 | */ 1844 | 1845 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_RIGHT( icp ); 1846 | 1847 | 1848 | /* Store the bottom-right pixel. 1849 | */ 1850 | 1851 | COSTELLA_IMAGE_COLOR_PIXEL_SET_G_CB( icp, ubCb ); 1852 | COSTELLA_IMAGE_COLOR_PIXEL_SET_B_CR( icp, ubCr ); 1853 | 1854 | 1855 | /* Move up. 1856 | */ 1857 | 1858 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_UP( icp, sdRowStride ); 1859 | 1860 | 1861 | /* Store the top-right pixel. 1862 | */ 1863 | 1864 | COSTELLA_IMAGE_COLOR_PIXEL_SET_G_CB( icp, ubCb ); 1865 | COSTELLA_IMAGE_COLOR_PIXEL_SET_B_CR( icp, ubCr ); 1866 | 1867 | 1868 | /* Move right for the next 2 x 2 block. 1869 | */ 1870 | 1871 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_RIGHT( icp ); 1872 | } 1873 | } 1874 | } 1875 | 1876 | 1877 | /* Walk down to the next row pair. 1878 | */ 1879 | 1880 | COSTELLA_IMAGE_COLOR_PIXEL_MOVE_DOWN_TWO( icpStart, sdDoubleRowStride ); 1881 | } 1882 | } 1883 | COSTELLA_END_FUNCTION 1884 | 1885 | 1886 | 1887 | /* Copyright (c) 2005-2007 John P. Costella. 1888 | ** 1889 | ** End of file. 1890 | */ 1891 | --------------------------------------------------------------------------------