1 /* Swap image byte order.
2 *
3 * 5/6/15
4 * - from copy.c
5 * 27/1/16
6 * - don't swap coded images
7 */
8
9 /*
10
11 This file is part of VIPS.
12
13 VIPS is free software; you can redistribute it and/or modify
14 it under the terms of the GNU Lesser General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU Lesser General Public License for more details.
22
23 You should have received a copy of the GNU Lesser General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 02110-1301 USA
27
28 */
29
30 /*
31
32 These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
33
34 */
35
36 /*
37 #define VIPS_DEBUG
38 */
39
40 #ifdef HAVE_CONFIG_H
41 #include <config.h>
42 #endif /*HAVE_CONFIG_H*/
43 #include <vips/intl.h>
44
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <math.h>
49
50 #include <vips/vips.h>
51 #include <vips/internal.h>
52 #include <vips/debug.h>
53
54 #include "pconversion.h"
55
56 typedef struct _VipsByteswap {
57 VipsConversion parent_instance;
58
59 /* The input image.
60 */
61 VipsImage *in;
62
63 } VipsByteswap;
64
65 typedef VipsConversionClass VipsByteswapClass;
66
67 G_DEFINE_TYPE( VipsByteswap, vips_byteswap, VIPS_TYPE_CONVERSION );
68
69 /* Swap pairs of bytes.
70 */
71 static void
vips_byteswap_swap2(VipsPel * in,VipsPel * out,int width,VipsImage * im)72 vips_byteswap_swap2( VipsPel *in, VipsPel *out, int width, VipsImage *im )
73 {
74 guint16 *p = (guint16 *) in;
75 guint16 *q = (guint16 *) out;
76 int sz = (VIPS_IMAGE_SIZEOF_PEL( im ) * width) / 2;
77
78 int x;
79
80 for( x = 0; x < sz; x++ )
81 q[x] = GUINT16_SWAP_LE_BE( p[x] );
82 }
83
84 /* Swap 4- of bytes.
85 */
86 static void
vips_byteswap_swap4(VipsPel * in,VipsPel * out,int width,VipsImage * im)87 vips_byteswap_swap4( VipsPel *in, VipsPel *out, int width, VipsImage *im )
88 {
89 guint32 *p = (guint32 *) in;
90 guint32 *q = (guint32 *) out;
91 int sz = (VIPS_IMAGE_SIZEOF_PEL( im ) * width) / 4;
92
93 int x;
94
95 for( x = 0; x < sz; x++ )
96 q[x] = GUINT32_SWAP_LE_BE( p[x] );
97 }
98
99 /* Swap 8- of bytes.
100 */
101 static void
vips_byteswap_swap8(VipsPel * in,VipsPel * out,int width,VipsImage * im)102 vips_byteswap_swap8( VipsPel *in, VipsPel *out, int width, VipsImage *im )
103 {
104 guint64 *p = (guint64 *) in;
105 guint64 *q = (guint64 *) out;
106 int sz = (VIPS_IMAGE_SIZEOF_PEL( im ) * width) / 8;
107
108 int x;
109
110 for( x = 0; x < sz; x++ )
111 q[x] = GUINT64_SWAP_LE_BE( p[x] );
112 }
113
114 typedef void (*SwapFn)( VipsPel *in, VipsPel *out, int width, VipsImage *im );
115
116 static SwapFn vips_byteswap_swap_fn[] = {
117 NULL, /* VIPS_FORMAT_UCHAR = 0, */
118 NULL, /* VIPS_FORMAT_CHAR = 1, */
119 vips_byteswap_swap2, /* VIPS_FORMAT_USHORT = 2, */
120 vips_byteswap_swap2, /* VIPS_FORMAT_SHORT = 3, */
121 vips_byteswap_swap4, /* VIPS_FORMAT_UINT = 4, */
122 vips_byteswap_swap4, /* VIPS_FORMAT_INT = 5, */
123 vips_byteswap_swap4, /* VIPS_FORMAT_FLOAT = 6, */
124 vips_byteswap_swap4, /* VIPS_FORMAT_COMPLEX = 7, */
125 vips_byteswap_swap8, /* VIPS_FORMAT_DOUBLE = 8, */
126 vips_byteswap_swap8 /* VIPS_FORMAT_DPCOMPLEX = 9, */
127 };
128
129 /* Byteswap, turning bands into the x axis.
130 */
131 static int
vips_byteswap_gen(VipsRegion * or,void * seq,void * a,void * b,gboolean * stop)132 vips_byteswap_gen( VipsRegion *or,
133 void *seq, void *a, void *b, gboolean *stop )
134 {
135 VipsRegion *ir = (VipsRegion *) seq;
136 VipsImage *im = ir->im;
137 VipsRect *r = &or->valid;
138 SwapFn swap = vips_byteswap_swap_fn[im->BandFmt];
139
140 int y;
141
142 g_assert( swap );
143
144 if( vips_region_prepare( ir, r ) )
145 return( -1 );
146
147 for( y = 0; y < r->height; y++ ) {
148 VipsPel *p = VIPS_REGION_ADDR( ir, r->left, r->top + y );
149 VipsPel *q = VIPS_REGION_ADDR( or, r->left, r->top + y );
150
151 swap( p, q, r->width, im );
152 }
153
154 return( 0 );
155 }
156
157 static int
vips_byteswap_build(VipsObject * object)158 vips_byteswap_build( VipsObject *object )
159 {
160 VipsConversion *conversion = VIPS_CONVERSION( object );
161 VipsByteswap *byteswap = (VipsByteswap *) object;
162
163 if( VIPS_OBJECT_CLASS( vips_byteswap_parent_class )->build( object ) )
164 return( -1 );
165
166 /* Lots of images don't need swapping.
167 */
168 if( byteswap->in->Coding != VIPS_CODING_NONE ||
169 !vips_byteswap_swap_fn[byteswap->in->BandFmt] )
170 return( vips_image_write( byteswap->in, conversion->out ) );
171
172 if( vips_image_pio_input( byteswap->in ) )
173 return( -1 );
174
175 if( vips_image_pipelinev( conversion->out,
176 VIPS_DEMAND_STYLE_THINSTRIP, byteswap->in, NULL ) )
177 return( -1 );
178
179 if( vips_image_generate( conversion->out,
180 vips_start_one, vips_byteswap_gen, vips_stop_one,
181 byteswap->in, byteswap ) )
182 return( -1 );
183
184 return( 0 );
185 }
186
187 static void
vips_byteswap_class_init(VipsByteswapClass * class)188 vips_byteswap_class_init( VipsByteswapClass *class )
189 {
190 GObjectClass *gobject_class = G_OBJECT_CLASS( class );
191 VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class );
192 VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
193
194 VIPS_DEBUG_MSG( "vips_byteswap_class_init\n" );
195
196 gobject_class->set_property = vips_object_set_property;
197 gobject_class->get_property = vips_object_get_property;
198
199 vobject_class->nickname = "byteswap";
200 vobject_class->description = _( "byteswap an image" );
201 vobject_class->build = vips_byteswap_build;
202
203 operation_class->flags = VIPS_OPERATION_SEQUENTIAL;
204
205 VIPS_ARG_IMAGE( class, "in", 1,
206 _( "Input" ),
207 _( "Input image" ),
208 VIPS_ARGUMENT_REQUIRED_INPUT,
209 G_STRUCT_OFFSET( VipsByteswap, in ) );
210
211 }
212
213 static void
vips_byteswap_init(VipsByteswap * byteswap)214 vips_byteswap_init( VipsByteswap *byteswap )
215 {
216 }
217
218 /**
219 * vips_byteswap: (method)
220 * @in: input image
221 * @out: (out): output image
222 * @...: %NULL-terminated list of optional named arguments
223 *
224 * Swap the byte order in an image.
225 *
226 * See also: vips_rawload().
227 *
228 * Returns: 0 on success, -1 on error.
229 */
230 int
vips_byteswap(VipsImage * in,VipsImage ** out,...)231 vips_byteswap( VipsImage *in, VipsImage **out, ... )
232 {
233 va_list ap;
234 int result;
235
236 va_start( ap, out );
237 result = vips_call_split( "byteswap", ap, in, out );
238 va_end( ap );
239
240 return( result );
241 }
242
243 /* Convenience function: swap if @swap is %TRUE, otherwise copy.
244 */
245 int
vips__byteswap_bool(VipsImage * in,VipsImage ** out,gboolean swap)246 vips__byteswap_bool( VipsImage *in, VipsImage **out, gboolean swap )
247 {
248 if( swap )
249 return( vips_byteswap( in, out, NULL ) );
250 else
251 return( vips_copy( in, out, NULL ) );
252 }
253