1 : /******************************************************************************
2 : * $Id: nitfwritejpeg.cpp 18142 2009-11-30 20:16:00Z warmerdam $
3 : *
4 : * Project: NITF Read/Write Translator
5 : * Purpose: GDALDataset/GDALRasterBand implementation on top of "nitflib".
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2002, Frank Warmerdam
10 : *
11 : * Portions Copyright (c) Her majesty the Queen in right of Canada as
12 : * represented by the Minister of National Defence, 2006.
13 : *
14 : * Permission is hereby granted, free of charge, to any person obtaining a
15 : * copy of this software and associated documentation files (the "Software"),
16 : * to deal in the Software without restriction, including without limitation
17 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 : * and/or sell copies of the Software, and to permit persons to whom the
19 : * Software is furnished to do so, subject to the following conditions:
20 : *
21 : * The above copyright notice and this permission notice shall be included
22 : * in all copies or substantial portions of the Software.
23 : *
24 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 : * DEALINGS IN THE SOFTWARE.
31 : ****************************************************************************/
32 :
33 : #ifdef JPEG_SUPPORTED
34 :
35 : #include "cpl_port.h"
36 : #include "gdal_pam.h"
37 :
38 : CPL_C_START
39 : #ifdef LIBJPEG_12_PATH
40 : # include LIBJPEG_12_PATH
41 : #else
42 : # include "jpeglib.h"
43 : #endif
44 : CPL_C_END
45 :
46 : /*
47 : * Do we want to do special processing suitable for when JSAMPLE is a
48 : * 16bit value?
49 : */
50 : #if defined(JPEG_LIB_MK1)
51 : # define JPEG_LIB_MK1_OR_12BIT 1
52 : #elif BITS_IN_JSAMPLE == 12
53 : # define JPEG_LIB_MK1_OR_12BIT 1
54 : #endif
55 :
56 : #if defined(JPEG_DUAL_MODE_8_12) && !defined(NITFWriteJPEGBlock)
57 : int
58 : NITFWriteJPEGBlock_12( GDALDataset *poSrcDS, FILE *fp,
59 : int nBlockXOff, int nBlockYOff,
60 : int nBlockXSize, int nBlockYSize,
61 : int bProgressive, int nQuality,
62 : GDALProgressFunc pfnProgress, void * pProgressData );
63 : #endif
64 :
65 : void jpeg_vsiio_src (j_decompress_ptr cinfo, FILE * infile);
66 : void jpeg_vsiio_dest (j_compress_ptr cinfo, FILE * outfile);
67 :
68 : /************************************************************************/
69 : /* NITFWriteJPEGBlock() */
70 : /************************************************************************/
71 :
72 : int
73 11 : NITFWriteJPEGBlock( GDALDataset *poSrcDS, FILE *fp,
74 : int nBlockXOff, int nBlockYOff,
75 : int nBlockXSize, int nBlockYSize,
76 : int bProgressive, int nQuality,
77 : GDALProgressFunc pfnProgress, void * pProgressData )
78 : {
79 11 : GDALDataType eDT = poSrcDS->GetRasterBand(1)->GetRasterDataType();
80 : #if defined(JPEG_DUAL_MODE_8_12) && !defined(NITFWriteJPEGBlock)
81 10 : if( eDT == GDT_UInt16 )
82 : {
83 : return NITFWriteJPEGBlock_12(poSrcDS, fp,
84 : nBlockXOff, nBlockYOff,
85 : nBlockXSize, nBlockYSize,
86 : bProgressive, nQuality,
87 1 : pfnProgress, pProgressData );
88 : }
89 : #endif
90 :
91 10 : int nBands = poSrcDS->GetRasterCount();
92 10 : int nXSize = poSrcDS->GetRasterXSize();
93 10 : int nYSize = poSrcDS->GetRasterYSize();
94 10 : int anBandList[3] = {1,2,3};
95 :
96 : /* -------------------------------------------------------------------- */
97 : /* Initialize JPG access to the file. */
98 : /* -------------------------------------------------------------------- */
99 : struct jpeg_compress_struct sCInfo;
100 : struct jpeg_error_mgr sJErr;
101 :
102 10 : sCInfo.err = jpeg_std_error( &sJErr );
103 10 : jpeg_create_compress( &sCInfo );
104 :
105 10 : jpeg_vsiio_dest( &sCInfo, fp );
106 :
107 10 : sCInfo.image_width = nBlockXSize;
108 10 : sCInfo.image_height = nBlockYSize;
109 10 : sCInfo.input_components = nBands;
110 :
111 10 : if( nBands == 1 )
112 : {
113 1 : sCInfo.in_color_space = JCS_GRAYSCALE;
114 : }
115 : else
116 : {
117 9 : sCInfo.in_color_space = JCS_RGB;
118 : }
119 :
120 10 : jpeg_set_defaults( &sCInfo );
121 :
122 : #if defined(JPEG_LIB_MK1_OR_12BIT)
123 1 : if( eDT == GDT_UInt16 )
124 : {
125 1 : sCInfo.data_precision = 12;
126 : }
127 : else
128 : {
129 0 : sCInfo.data_precision = 8;
130 : }
131 : #endif
132 :
133 : GDALDataType eWorkDT;
134 : #ifdef JPEG_LIB_MK1
135 : sCInfo.bits_in_jsample = sCInfo.data_precision;
136 : eWorkDT = GDT_UInt16; /* Always force to 16 bit for JPEG_LIB_MK1 */
137 : #else
138 10 : eWorkDT = eDT;
139 : #endif
140 :
141 10 : sCInfo.write_JFIF_header = FALSE;
142 10 : jpeg_set_quality( &sCInfo, nQuality, TRUE );
143 :
144 10 : if( bProgressive )
145 0 : jpeg_simple_progression( &sCInfo );
146 :
147 10 : jpeg_start_compress( &sCInfo, TRUE );
148 :
149 : /* -------------------------------------------------------------------- */
150 : /* Loop over image, copying image data. */
151 : /* -------------------------------------------------------------------- */
152 : GByte *pabyScanline;
153 10 : CPLErr eErr = CE_None;
154 10 : int nWorkDTSize = GDALGetDataTypeSize(eWorkDT) / 8;
155 :
156 10 : pabyScanline = (GByte *) CPLMalloc( nBands * nBlockXSize * nWorkDTSize );
157 :
158 10 : double nTotalPixels = (double)nXSize * nYSize;
159 :
160 10 : int nBlockXSizeToRead = nBlockXSize;
161 10 : if (nBlockXSize * nBlockXOff + nBlockXSize > nXSize)
162 : {
163 4 : nBlockXSizeToRead = nXSize - nBlockXSize * nBlockXOff;
164 : }
165 10 : int nBlockYSizeToRead = nBlockYSize;
166 10 : if (nBlockYSize * nBlockYOff + nBlockYSize > nYSize)
167 : {
168 4 : nBlockYSizeToRead = nYSize - nBlockYSize * nBlockYOff;
169 : }
170 :
171 10 : bool bClipWarn = false;
172 380 : for( int iLine = 0; iLine < nBlockYSize && eErr == CE_None; iLine++ )
173 : {
174 : JSAMPLE *ppSamples;
175 :
176 370 : if (iLine < nBlockYSizeToRead)
177 : {
178 : eErr = poSrcDS->RasterIO( GF_Read, nBlockXSize * nBlockXOff, iLine + nBlockYSize * nBlockYOff, nBlockXSizeToRead, 1,
179 : pabyScanline, nBlockXSizeToRead, 1, eWorkDT,
180 : nBands, anBandList,
181 314 : nBands*nWorkDTSize, nBands * nBlockXSize * nWorkDTSize, nWorkDTSize );
182 :
183 : #if !defined(JPEG_LIB_MK1_OR_12BIT)
184 : /* Repeat the last pixel till the end of the line */
185 : /* to minimize discontinuity */
186 250 : if (nBlockXSizeToRead < nBlockXSize)
187 : {
188 400 : for (int iBand = 0; iBand < nBands; iBand++)
189 : {
190 300 : GByte bVal = pabyScanline[nBands * (nBlockXSizeToRead - 1) + iBand];
191 4500 : for(int iX = nBlockXSizeToRead; iX < nBlockXSize; iX ++)
192 : {
193 4200 : pabyScanline[nBands * iX + iBand ] = bVal;
194 : }
195 : }
196 : }
197 : #endif
198 : }
199 :
200 : // clamp 16bit values to 12bit.
201 370 : if( eDT == GDT_UInt16 )
202 : {
203 64 : GUInt16 *panScanline = (GUInt16 *) pabyScanline;
204 : int iPixel;
205 :
206 4160 : for( iPixel = 0; iPixel < nXSize*nBands; iPixel++ )
207 : {
208 4096 : if( panScanline[iPixel] > 4095 )
209 : {
210 0 : panScanline[iPixel] = 4095;
211 0 : if( !bClipWarn )
212 : {
213 0 : bClipWarn = true;
214 : CPLError( CE_Warning, CPLE_AppDefined,
215 0 : "One or more pixels clipped to fit 12bit domain for jpeg output." );
216 : }
217 : }
218 : }
219 : }
220 :
221 370 : ppSamples = (JSAMPLE *) pabyScanline;
222 :
223 370 : if( eErr == CE_None )
224 370 : jpeg_write_scanlines( &sCInfo, &ppSamples, 1 );
225 :
226 : double nCurPixels = (double)nBlockYOff * nBlockYSize * nXSize +
227 370 : (double)nBlockXOff * nBlockYSize * nBlockXSize + (iLine + 1) * nBlockXSizeToRead;
228 370 : if( eErr == CE_None
229 : && !pfnProgress( nCurPixels / nTotalPixels, NULL, pProgressData ) )
230 : {
231 0 : eErr = CE_Failure;
232 : CPLError( CE_Failure, CPLE_UserInterrupt,
233 0 : "User terminated CreateCopy()" );
234 : }
235 : }
236 :
237 : /* -------------------------------------------------------------------- */
238 : /* Cleanup and close. */
239 : /* -------------------------------------------------------------------- */
240 10 : CPLFree( pabyScanline );
241 :
242 10 : if( eErr == CE_None )
243 10 : jpeg_finish_compress( &sCInfo );
244 10 : jpeg_destroy_compress( &sCInfo );
245 :
246 10 : return eErr == CE_None;
247 : }
248 : #endif /* def JPEG_SUPPORTED */
|