Xmipp  v3.23.11-Nereus
xmipp_image_convert.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors: Carlos Oscar coss@cnb.csic.es (2007)
4  * Joaquin Oton joton@cnb.csic.es (2010)
5  *
6  * Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21  * 02111-1307 USA
22  *
23  * All comments concerning this program package may be sent to the
24  * e-mail address 'xmipp@cnb.csic.es'
25  ***************************************************************************/
26 
27 #include "xmipp_image_convert.h"
28 #include "core/xmipp_funcs.h"
29 
31 {
32  init();
33 }
34 
36 {
38  save_metadata_stack = false;
39  keep_input_columns = true;
40  delete_output_stack = false;
41 
42  castMode = CW_CONVERT;
43  appendToStack = false;
44  // output extension
45  oext = "";
46  // output type
47  type = "auto";
48  // Set default write mode
49  writeMode = WRITE_OVERWRITE;
50  depth = "";
51  swap = false;
52 }
53 
54 
56 {
57  init();
58  CommentList &comments = defaultComments["-i"];
59  comments.addComment("++ Supported read formats are:");
60  comments.addComment("++ dm3 : Digital Micrograph 3");
61  comments.addComment("++ em : Electron Microscopy");
62  comments.addComment("++ jpg : JPEG");
63  comments.addComment("++ img : Imagic");
64  comments.addComment("++ inf,raw : RAW file with header INF file");
65  comments.addComment("++ mrc, map : CCP4");
66  comments.addComment("++ pif : Portable Image Format");
67  comments.addComment("++ ser : Tecnai Imaging and Analysis");
68  comments.addComment("++ spe : Princeton Instruments CCD camera");
69  comments.addComment("++ spi, xmp : Spider");
70  comments.addComment("++ tif : TIFF");
71  comments.addComment("++ raw#xDim,yDim,[zDim],offset,datatype,[r] : RAW image file without header file");
72  comments.addComment("++ where datatype can be: uint8,int8,uint16,int16,uint32,int32,long,float,double,");
73  comments.addComment("++ cint16,cint32,cfloat,cdouble,bool");
75 
76  addUsageLine("Convert among stacks, volumes and images, and change the file format.");
77  addUsageLine("+Conversion to a lower bit_depth automatically adjusts the gray level range. If it is between same bit ");
78  addUsageLine("+depths and different sign, then only a histogram shift is done. If parameter --depth is not passed, then ");
79  addUsageLine("+bit_depth is automatically chosen equal to or higher than input bit_depth. For stack output format, ");
80  addUsageLine("+a selection file with the images in the stack is optionally created, replicating the labels of the input sel file.");
81  addUsageLine("+If output file extension is not set when --oroot is used (neither setting --oext nor :ext), then input format is chosen.");
82  addKeywords("conversion, convert, image, stack, volume, format, extension ");
83  //Parameters
84  addParamsLine(" [--oext <extension=\"\">] : Output file format extension.");
85  addParamsLine(" where <extension>");
86  addParamsLine(" img : Imagic (Data types: uint8, int16, float* and cfloat).");
87  addParamsLine(" inf : RAW file with header INF file (Data types: (u)int8, (u)int16 and float*).");
88  addParamsLine(" raw : RAW file with header INF file (Data types: (u)int8, (u)int16 and float*).");
89  addParamsLine(" mrc : CCP4 (Data types: uint8, (u)int16, float* and cfloat).");
90  addParamsLine(" spi : Spider (Data types: float* and cfloat).");
91  addParamsLine(" xmp : Spider (Data types: float* and cfloat).");
92  addParamsLine(" tif : TIFF (Data types: uint8*, uint16, uint32 and float).");
93  addParamsLine(" jpg : JPEG (Data types: uint8*).");
94  addParamsLine(" custom <ext> : Custom extension name, the real format will be Spider.");
95  addParamsLine(" [--type <output_type=auto>] : Force output file type.");
96  addParamsLine(" where <output_type>");
97  addParamsLine(" auto: Autodetect output type according to output extension and whether --oroot is passed or not.");
98  addParamsLine(" img : Image");
99  addParamsLine(" vol : Volume");
100  addParamsLine(" stk : Stack ");
101  addParamsLine(" alias -t;");
102  addParamsLine("== Bit options == ");
103  addParamsLine(" [--depth+ <bit_depth=default>] : Image bit depth.");
104  addParamsLine(" where <bit_depth>");
105  addParamsLine(" default: Default selected value (*)");
106  addParamsLine(" uint8 : Equivalent to uchar");
107  addParamsLine(" int8 : Equivalent to char");
108  addParamsLine(" uint16: Equivalent to ushort");
109  addParamsLine(" int16 : Equivalent to short");
110  addParamsLine(" uint32");
111  addParamsLine(" int32");
112  addParamsLine(" long");
113  addParamsLine(" float");
114  addParamsLine(" double");
115  addParamsLine(" cint16 : Complex int16");
116  addParamsLine(" cint32 : Complex int32");
117  addParamsLine(" cfloat : Complex float");
118  addParamsLine(" cdouble: Complex double");
119  addParamsLine(" bool");
120  addParamsLine(" alias -d;");
121  addParamsLine(" [--swap <type=arch>] : Swap the endianness of the image file");
122  addParamsLine(" where <type>");
123  addParamsLine(" arch : Set the opposite endian of the architecture");
124  addParamsLine(" little : Set to little endian");
125  addParamsLine(" big : Set to big endian");
126 
127  addParamsLine(" [--range_adjust] : Adjust the histogram to fill the gray level range");
128  addParamsLine(" alias -r;");
129  addParamsLine("or --dont_convert : Do not apply any conversion to gray levels when writing");
130  addParamsLine(" : in a lower bit depth or changing the sign");
131  addParamsLine("== Stack options == ");
132  addParamsLine(" [--append] : Append the input to the output stack instead of overwriting it");
133  addParamsLine(" alias -a;");
134 
135  //Examples
136  addExampleLine("Put a selection file into a stack:",false);
137  addExampleLine("xmipp_image_convert -i list.sel -o images.stk");
138  addExampleLine("Convert a Spider volume to a MRC stack:",false);
139  addExampleLine("xmipp_image_convert -i spider.vol -o stack.mrcs -t stk");
140  addExampleLine("Create a stack of volumes with a Spider volume :",false);
141  addExampleLine("xmipp_image_convert -i spider.vol -o vol_stack.stk -t vol");
142  addExampleLine("Append a volume to a volume stack:",false);
143  addExampleLine("xmipp_image_convert -i spider.vol -o vol_stack.stk -a");
144  addExampleLine("Substitute a volume in a volume stack:",false);
145  addExampleLine("xmipp_image_convert -i spider.vol -o 3@vol_stack.stk");
146  addExampleLine("Save images in a stack as independent TIFF files in image directory with \"newimage\" basename in 8bit format:",false);
147  addExampleLine("xmipp_image_convert -i stackFile.stk -o tiffImages.sel --oroot images/newimage:tif -d uint8");
148  addExampleLine("Convert a selection file of 16bit TIFF images to 8bit and overwrites files and sel file:",false);
149  addExampleLine("xmipp_image_convert -i tiff16.sel -d uint8");
150  addExampleLine("Append a single image to a stack:",false);
151  addExampleLine("xmipp_image_convert -i img.spi -o stackFile.stk --append");
152  addExampleLine("Append a selection file to a stack:",false);
153  addExampleLine("xmipp_image_convert -i selFile.sel -o stackFile.stk --append");
154  addExampleLine("Replace a single image into a stack:",false);
155  addExampleLine("xmipp_image_convert -i img.spi -o 3@stackFile.stk");
156  addExampleLine("Convert a MRC stack to a MRC volume:",false);
157  addExampleLine("xmipp_image_convert -i stack.mrc -o volume.mrc -t vol");
158 }
159 
161 {
163 
164  //fn_out = (checkParam("-o"))? getParam("-o") : "";
165  castMode = (checkParam("--range_adjust"))? CW_ADJUST: \
166  (checkParam("--dont_convert"))? CW_CAST: CW_CONVERT;
167 
168  appendToStack = checkParam("--append");
169 
170  // output extension
171  oext = checkParam("--oext") ? getParam("--oext") : "";
172  if ( oext == "custom" )
173  oext = getParam("--oext",1);
174 
175  // Check output type
176  type = getParam("--type");
177 
178  if (checkParam("--depth"))
179  {
180  auto depthTemp = (String)getParam("--depth");
181  if (depthTemp != "default")
182  depth = "%" + depthTemp;
183  }
184 
185  if ( (swap = checkParam("--swap")) )
186  {
187  String swapType = getParam("--swap");
188 
189  if (swapType != "arch")
190  {
191  bool setLE = swapType == "little";
192  swap = IsLittleEndian()^setLE;
193  }
194  }
195 }
196 
198 {
199  if (type == "auto")
200  {
201  if (oroot.empty())
202  {
203  /* It is stack if extension is stack compatible, or if --oroot is not passed
204  * and there are more than one image. Same for volumes.
205  * Firstly, we must check extensions, then stack and volume sizes.*/
206  if (( mdInSize > 1 || zdimOut > 1 ) && fn_out.hasStackExtension())
207  type = "stk";
208  else if (( mdInSize > 1 || zdimOut > 1 ) && fn_out.hasVolumeExtension()) // if it is volume
209  type = "vol";
210  else if (mdInSize > 1 || appendToStack) // If --append we suppose output is stack
211  type = "stk";
212  else if (zdimOut > 1) // if it is volume
213  type = "vol";
214  else
215  type = "img";
216  }
217  else
218  type = "img";
219  }
220 
221  // Set write mode
222  if (single_image && fn_out.isInStack()) // Replace a single image in a stack
223  {
224  type = "img";
225  writeMode = WRITE_REPLACE;
226  }
227  else if (type == "stk" && appendToStack)
228  writeMode = WRITE_APPEND;
229  else
230  {
231  writeMode = WRITE_OVERWRITE;
232  delete_output_stack = true;
233  }
234 
236  {
237  FileName fn_stack_plain = fn_out.removeFileFormat();
238  fn_stack_plain.deleteFile();
239  delete_output_stack = false;
240  }
241 
242  create_empty_stackfile = (create_empty_stackfile && !appendToStack);
243 
244  convMode = MD2MD;
245 
246  if (!single_image && type == "vol")
247  {
248  convMode = MD2VOL;
249 
250  if (zdimOut != 1)
252  "Only 2D images can be converted into volumes");
253  imOut = new ImageGeneric(datatypeOut);
255  k = 0;
256  }
257  else if (single_image)
258  {
259  // If --append is set, or fn_out is in a stack, then it is supposed not to convert VOL2MD
260  if ( zdimOut > 1 && !(type == "vol" || fn_out.isInStack() || appendToStack))
261  {
262  convMode = VOL2MD;
263  single_image = false;
264 
265  MetaData * md = getInputMd();
266  md->clear();
267 
268  FileName fnTemp;
269 
270  /* Fill mdIn to allow XmippMetaDataProgram create the fnImgOut,
271  but not used to read input images. Input volume is read here. */
272  for (k = 1; k <= zdimOut; k++)
273  {
274  fnTemp.compose(k, fn_in);
275  size_t id = md->addObject();
276  md->setValue(MDL_IMAGE, fnTemp, id);
277  md->setValue(MDL_ENABLED, 1, id);
278  }
279  imIn.read(fn_in, DATA, ALL_IMAGES, true);
280  imOut = new ImageGeneric(datatypeOut);
281  k = 0; // Reset to zero to select the slices when working with volumes
282  if (!fn_out.empty())
283  {
284  if (depth.empty())
285  depth = "%"+datatype2Str(datatypeOut);
287  }
288  }
289  }
290  else if (create_empty_stackfile)
291  {
292  if (depth.empty())
293  depth = "%"+datatype2Str(datatypeOut);
294 
295  FileName first_image;
296  getInputMd()->getValue(image_label, first_image, 1);
297  imIn.read(first_image, DATA, FIRST_IMAGE, true);
299  }
300  create_empty_stackfile = false;
301 }//function preprocess
302 
303 void ProgConvImg::processImage(const FileName &fnImg, const FileName &fnImgOut, const MDRow &rowIn, MDRow &rowOut)
304 {
305  switch(convMode)
306  {
307  case MD2MD:
308  {
309  FileName tempName, _fnImgOut;
310  if (fnImg == fnImgOut)
311  {
312  tempName.initUniqueName("tempConvert_XXXXXX");
313  _fnImgOut = tempName + ":" + fnImgOut.getExtension();
314  }
315  else
316  _fnImgOut= fnImgOut;
317 
318  imIn.read(fnImg, DATA, ALL_IMAGES, true);
319  imIn.write(_fnImgOut+depth, ALL_IMAGES, type == "stk", writeMode, castMode, swap);
320 
321  if ((fnImg == fnImgOut) && (rename(tempName.c_str(),fnImgOut.c_str())!=0))
322  REPORT_ERROR(ERR_IO, formatString("ProgConvImg:: Error renaming the file from %s to %s.",tempName.c_str(), fnImgOut.c_str()));
323 
324  break;
325  }
326  case MD2VOL:
327  {
328  imIn.read(fnImg,DATA, ALL_IMAGES,true);
329  imOut->data->setSlice(k++,imIn.data);
330  break;
331  }
332  case VOL2MD:
333  {
334  imIn.data->getSlice(k++,imOut->data);
335  imOut->write(fnImgOut+depth, ALL_IMAGES, type == "stk", writeMode, castMode, swap);
336  break;
337  }
338  }
339 }//function processImage
340 
342 {
343  switch(convMode)
344  {
345  case MD2VOL:
346  if (swap)
347  imOut->image->swapOnWrite();
348  imOut->write();
349  single_image = true;
351  break;
352  default:
353  break;
354  }
355 
357 }
358 
360 {
363  {
364  if (!oext.empty())
365  std::cout << "Output Extension: " << oext << std::endl;
366  }
367 }
368 
std::string datatype2Str(DataType datatype)
bool delete_output_stack
Delete previous output stack file prior to process images.
void write(const FileName &name="", size_t select_img=ALL_IMAGES, bool isStack=false, int mode=WRITE_OVERWRITE, CastWriteMode castMode=CW_CAST, int _swapWrite=0)
virtual size_t addObject()=0
size_t mdInSize
Number of input elements.
bool IsLittleEndian(void)
virtual void clear()
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
FileName removeFileFormat() const
void setSlice(int k, const MultidimArray< T1 > &v, size_t n=0)
void compose(const String &str, const size_t no, const String &ext="")
bool single_image
Input is a single image.
Input/Output general error.
Definition: xmipp_error.h:134
void initUniqueName(const char *templateStr="xmippTemp_XXXXXX", const String &fnDir="")
virtual bool getValue(MDObject &mdValueOut, size_t id) const =0
Is this image enabled? (int [-1 or 1])
void addKeywords(const char *keywords)
String getExtension() const
void getSlice(int k, MultidimArray< T > &M, char axis='Z', bool reverse=false, size_t n=0) const
FileName fn_in
Filenames of input and output Metadata.
const char * getParam(const char *param, int arg=0)
void swapOnWrite()
void progress_bar(long rlen)
void mapFile2Write(int Xdim, int Ydim, int Zdim, const FileName &_filename, bool createTempFile=false, size_t select_img=APPEND_IMAGE, bool isStack=false, int mode=WRITE_OVERWRITE, int _swapWrite=0)
void addExampleLine(const char *example, bool verbatim=true)
void createEmptyFile(const FileName &filename, int xdim, int ydim, int Zdim, size_t select_img, bool isStack, int mode, int _swapWrite, const MDRowVec *md)
MDLabel image_label
MDLabel to be used to read/write images, usually will be MDL_IMAGE.
ImageBase * image
void deleteFile() const
MDRowVec MDMainHeader
bool setValue(const MDLabel label, const T &valueIn, size_t id)
void show() const override
bool save_metadata_stack
Save the associated output metadata when output file is a stack.
std::string String
Definition: xmipp_strings.h:34
void processImage(const FileName &fnImg, const FileName &fnImgOut, const MDRow &rowIn, MDRow &rowOut)
#define ALL_IMAGES
String formatString(const char *format,...)
bool keep_input_columns
Keep input metadata columns.
bool checkParam(const char *param)
#define FIRST_IMAGE
Incorrect MultidimArray dimensions.
Definition: xmipp_error.h:173
bool each_image_produces_an_output
Indicate that an output is produced for each image in the input.
bool hasVolumeExtension() const
void addComment(const String &comment, int visible=0, bool wikiVerbatim=false)
void addUsageLine(const char *line, bool verbatim=false)
bool hasStackExtension() const
int read(const FileName &name, DataMode datamode=DATA, size_t select_img=ALL_IMAGES, bool mapData=false)
MultidimArrayGeneric * data
Name of an image (std::string)
void addParamsLine(const String &line)
bool isInStack() const
FileName oext
Output extension and root.
std::map< String, CommentList > defaultComments
Definition: xmipp_program.h:83