Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
WrapBias2Ipl.cpp
1 // JW 2005
2 #include <Base/Common/W32Compat.hh>
3 #include "WrapBias2Ipl.hh"
4 #include <Base/Debug/Error.hh>
5 #include <Base/Debug/DebugSimple.hh>
6 #include <Base/Image/ImageIO.hh>
7 
8 #include <string>
9 
10 
11 #ifdef BIAS_HAVE_OPENCV
12 # include <cv.h>
13 # include <highgui.h>
14 #endif
15 
16 
17 #ifdef BIAS_HAVE_OPENCV
18 
19 using namespace std;
20 using namespace BIAS;
21 
22 WrapBias2Ipl::~WrapBias2Ipl(){
23  // do not destruct the BIAS image because it is reference.
24 
25  //destroy IplImage because we constructed it.
26  //if (p_imgIplDestroyable)
27  {
28  delete p_imgIpl;
29  p_imgIpl=NULL;
30  }
31 }
32 
33 
34 WrapBias2Ipl::WrapBias2Ipl()
35 :
36 p_imgBias(NULL)
37 //,p_imgBiasDestroyable(false)
38 ,p_imgIpl(NULL)
39 ,p_imgIplDestroyable(false)
40 {
41 }
42 
43 
45 :
46 p_imgBias(NULL)
47 //,p_imgBiasDestroyable(false)
48 ,p_imgIpl(NULL)
49 ,p_imgIplDestroyable(false)
50 {
51  int result=Bind(PtrImgBias) ;
52  // destry on exit because we allcoated
53  p_imgIplDestroyable=true;
54 
55  if (result!=0) {
56  BIASERR("Error on Bind in constructor. result="<<result);
57  };
58 }
59 
60 
61 
62 //JW
64 {
65  this->p_imgBias = p_src;
66  return CreateIplImageShared(p_src, this->p_imgIpl);
67 }
68 
69 
70 // JW p_dest has to be a *& because we need to change the pointer itself by reference.
71 int WrapBias2Ipl::CreateIplImageShared(const BIAS::ImageBase * p_src, IplImage* &p_dest)
72 {
73  if (p_src==NULL){
74  BIASERR("ImageBase ptr p_src is NULL.");
75  return -1;
76  };
77  if (p_dest==NULL) {
78  p_dest=new IplImage;
79  //if (p_imgIpl==p_dest) p_imgIplDestroyable = true;
80  };
81 
82  if (!p_src->IsInterleaved() || !((p_src->GetWidth() % 4) == 0) ) {
83  BIASERR("Only interleaved images with modulo 4 with are currently supported, sorry.");
84  return -1;
85  }
86 
87  // OpenCV supports only interleaved IPL_DATA_ORDER_PIXEL:
88  if(!p_src->IsInterleaved()) return -2;
89 
90  // OpenCV supports only size modulo 4 image width
91  // to have pixel boundaries on 32bit aligned memory
92  // we would need stride, otherwise
93  if ( p_src->GetWidth() % 4 != 0 ) {
94  BIASERR("Image width is not multiple of 4 :"<< p_src->GetWidth()
95  <<"x"<< p_src->GetHeight());
96  return -3;
97  }
98 
99  // OK
100  // initialize only the header without data area:
101  CvSize imgSize;
102  imgSize.width = p_src->GetWidth();
103  imgSize.height = p_src->GetHeight();
104  // pixel depth in bits
105  int depth=0;
106  switch (p_src->GetStorageType()) {
108  depth=IPL_DEPTH_8S; break;
110  depth=IPL_DEPTH_8U; break;
112  depth=IPL_DEPTH_32F; break;
114  depth=IPL_DEPTH_64F; break;
116  depth=IPL_DEPTH_16S; break;
118  depth=IPL_DEPTH_16U; break;
120  depth=IPL_DEPTH_32S; break;
121 
123  // unsupported (?)
124  BIASERR("you try to wrap a BIAS unsigned int Image with OpenCV. This format may be unsupported by OpenCV! (JW)");
125  depth=IPL_DEPTH_32S|IPL_DEPTH_SIGN;
126  default:
127  BIASERR("unsupported Storagetype in BIAS image for BIAs->ipl image wrapper. GetStorageType="<<p_src->GetStorageType() );
128  return -1;
129  }
130 
131  // fill header struct with useful values:
132  cvInitImageHeader( p_dest,
133  imgSize,
134  depth,
135  p_src->GetChannelCount(),
136  IPL_ORIGIN_TL, // origin top left
137  4 // alignment
138  );
139 
140  // share the data area: (pointer to aligned image data) do NOT copy
141  p_dest->imageData = (char*)(p_src->GetImageData());
142 
143 
144  // get the color model and channel seq. right:
145  switch (p_src->GetColorModel()){
147  // tested, works on Win32
148  strcpy( p_dest->colorModel, "RGB");
149  strcpy( p_dest->channelSeq, "RGB");
150  break;
152  // untested but should work because it's OpenCv native format.
153  strcpy( p_dest->colorModel, "RGB");
154  strcpy( p_dest->channelSeq, "BGR");
155  break;
157  // untested.
158  strcpy( p_dest->colorModel, "RGBA");
159  strcpy( p_dest->channelSeq, "BGRA");
160  break;
162  // untested.
163  strcpy( p_dest->colorModel, "RGBA");
164  strcpy( p_dest->channelSeq, "RGBA");
165  break;
166 
167  /* assume grey display for packed pseudo one channel formats */
174  // untested.
175  strcpy( p_dest->colorModel, "GREY");
176  strcpy( p_dest->channelSeq, "GREY");
177  break;
178  default:
179  BIASERR("unsupported color model for OpenCV wrapping. "
180  "ChannelSeq may be wrong. "
181  <<p_src->GetColorModel() );
182  return -2;
183  };
184 
185  return 0;
186 }
187 
188 
189 // JW
190 int WrapBias2Ipl::CreateBiasImageCopy(const IplImage * p_src, BIAS::ImageBase & dest)
191 {
192 #ifdef __clang__
193  BIASERR("IplImage image loading is not supported in llvm/clang built BIAS binaries.");
194 #else
195  if (p_src==NULL){
196  BIASERR("IplImage ptr p_src is NULL.");
197  return -1;
198  };
199 
200  bool recreate=true; // HACK: always recreate
201  // TODO: check sizes, depth etc. and set recreate
202  if (recreate)
203  {
204  if (!dest.IsEmpty())
205  dest.Release();
206 
207  // detremine storage type first because it is required in Init call.
208  // pixel depth for corerct casting/type of the void* underlying content
209  dest.StorageType_ = ImageBase::ST_invalid; //< default
210  switch (p_src->depth)
211  {
212  case IPL_DEPTH_8S:
214  break;
215  case IPL_DEPTH_8U:
217  break;
218  case IPL_DEPTH_32F:
220  break;
221  case IPL_DEPTH_64F:
223  break;
224  case IPL_DEPTH_16S:
226  break;
227  case IPL_DEPTH_16U:
229  break;
230  //case (int(IPL_DEPTH_32S|IPL_DEPTH_SIGN)):
231  // // unsupported (?)
232  // dest.StorageType_ = ImageBase::ST_unsignedint:
233  // BIASERR("you try to wrap an unsigned int Image with OpenCV to BIAs. This format may be unsupported by OpenCV! (JW)");
234  // break;
235  case IPL_DEPTH_32S:
237  break;
238  default:
239  BIASERR("unsupported Ipl Storagetype for Ipl->BIAS wrapper.");
240  return -1;
241  }
242  //initialize target image
243  unsigned offset =0;
244  if(p_src->width%2 != 0) offset =1;
245  dest.Init(p_src->width+offset,p_src->height ,p_src->nChannels,dest.GetStorageType(),true);
246 
247  // default
249 
250  // get the color model and channel seq. right:
251  if (string(p_src->colorModel)=="RGB"){
252 
253  if (string(p_src->channelSeq)=="RGB"){
255  } else if (string(p_src->channelSeq)=="BGR"){
257  } else {
258  BIASERR("unsupported channelSeq for for OpenCV wrapping of RGB color model");
259  }
260 
261  } else if (string(p_src->colorModel)=="RGBA"){
262 
263  if (string(p_src->channelSeq)=="RGBA"){
265  } else if (string(p_src->channelSeq)=="BGRA"){
267  } else {
268  BIASERR("unsupported channelSeq for for OpenCV wrapping of of RGBA color model");
269  }
270 
271  } else if ((string(p_src->colorModel)=="GREY") || (string(p_src->colorModel)=="GRAY")) {
273  } else {
274 
275  BIASERR("unsupported color model for OpenCV wrapping.");
276  return -2;
277  }
278  };
279 
280  BIASASSERT(p_src!=NULL);
281  BIASASSERT(p_src->origin == IPL_ORIGIN_TL); // we suport only toplleft origin image for now. JW
282  BIASASSERT(dest.IsInterleaved() );
283 
284  // share the data area: (pointer to aligned image data) do NOT copy
285  //dest.ReleaseImageDataPointer();
286  //dest.ImageData_ = p_src->imageData;
287  //dest.UpdateImageDataArrayFromImageData_();
288 
289  // copy nr. of Bytes - no matter of recreate or not
290  //const unsigned int nBytes = dest.GetPixelCount()*dest.GetDepth()*dest.GetChannelCount();
291  //memcpy( dest.GetImageData(), p_src->imageData, nBytes );
292  dest.CopyIn_NoInit( p_src->imageData );
293  //ImageIO::Save("test.png",dest);
294  //BIASASSERT(dest.GetImageData() == p_src->imageData ); //< only for shared memory
295  return 0;
296 #endif
297 }
298 
299 
300 
302  if ((p_imgBias!=NULL) && (p_imgIpl!=NULL))
303  {
304  if (p_imgBias->GetImageData() != p_imgIpl->imageData ) {
305  BIASERR("data pointers of bias image and wrapped OpenCV imaeg are inconsisten!!!");
306  return false;
307  } else if ((int)p_imgBias->GetWidth() != p_imgIpl->width ) {
308  BIASERR("width is inconsistent!");
309  return false;
310  } else if ((int)p_imgBias->GetHeight() != p_imgIpl->height ){
311  BIASERR("height is inconsistent!");
312  return false;
313  };
314  }
315  return true;
316 }
317 
318 
319 //static
320 void WrapBias2Ipl::ConvertIPL32to8(const IplImage* src32,
321  IplImage* dest8,
322  const float & scale )
323 {
324  BIASASSERT(src32!=NULL);
325  BIASASSERT(dest8!=NULL);
326  BIASASSERT(src32->width == dest8->width);
327  BIASASSERT(src32->height == dest8->height);
328  BIASASSERT(src32->nChannels==dest8->nChannels);
329  BIASASSERT(src32->depth==32);
330  BIASASSERT(src32->imageData!=NULL);
331  BIASASSERT(dest8->imageData!=NULL);
332  BIASASSERT(scale!=0);
333 
334  // src pointer,
335  // because imageData is a signed char*
336  float *pSS = reinterpret_cast<float *>(src32->imageData);
337 
338  // destination
339  unsigned char *pDD = reinterpret_cast<unsigned char*>(dest8->imageData);
340  BIASASSERT(pSS!=NULL);
341  BIASASSERT(pDD!=NULL);
342  const int nX = src32->width * src32->nChannels;
343  // for all pixels of all channels
344  for (int y=0; y<src32->height; y++) {
345  for (int x=0; x<nX; x++) {
346  // clipping: 0 <= scale*in <= 255
347  pDD[x] = (unsigned char)( max(0.0f, min(255.0f, scale*pSS[x])) );
348  }
349  // next line
350  pSS = reinterpret_cast<float *> (&src32->imageData[y*src32->widthStep]);
351  pDD = reinterpret_cast<unsigned char*>(&dest8->imageData[y*dest8->widthStep]);
352  }
353 }
354 
355 // static function:
356 int WrapBias2Ipl::WaitKey(const unsigned int & delay){
357  return cvWaitKey(delay);
358 }
359 
360 
361 int WrapBias2Ipl::Display(const bool & waitForKey,
362  const unsigned int & delayMsec,
363  const float & scale) const
364 {
365  // do not move to topleft because this may be a subsequejt call after teh user moved it himself
366  return Display( string( DEFAULT_WrapBias2Ipl_WINNAME ),true, false, waitForKey, delayMsec, scale);
367 }
368 
369 int WrapBias2Ipl::Display(const char * DestWin,
370  const bool & autoresize,
371  const bool & moveToTopLeft,
372  const bool & waitForKey,
373  const unsigned int & delayMsec,
374  const float & scale,
375  const bool & allowAlphaWindow
376  ) const
377 {
378  std::string name(DestWin);
379  return Display(name,
380  autoresize,
381  moveToTopLeft,
382  waitForKey,
383  delayMsec,
384  scale,
385  allowAlphaWindow
386  );
387 }
388 
389 
390 int WrapBias2Ipl::Display(const std::string & DestWin,
391  const bool & autoresize,
392  const bool & moveToTopLeft,
393  const bool & waitForKey,
394  const unsigned int & delayMsec,
395  const float & scale,
396  const bool & allowAlphaWindow
397  ) const
398 {
399  return Display(this->p_imgIpl, DestWin, autoresize, moveToTopLeft, waitForKey, delayMsec, scale, allowAlphaWindow);
400 }
401 
402 
403 
404 // jw this is the implementation of the static function:
405 int WrapBias2Ipl::Display(const IplImage* img,
406  const std::string & DestWin,
407  const bool & autoresize,
408  const bool & moveToTopLeft,
409  const bool & waitForKey,
410  const unsigned int & delayMsec,
411  const float & scale,
412  const bool & allowAlphaWindow
413  )
414 {
415  if (img==NULL) {
416  BIASERR("NULL img");
417  return -2;
418  };
419  if (img->width==0 || img->height==0) {
420  BIASERR("empty image of dim "<<img->width<<"x"<<img->height);
421  return -3;
422  };
423 
424  // create the display window:
425  int winflags=0;
426  if (autoresize) winflags = winflags | CV_WINDOW_AUTOSIZE;
427  cvNamedWindow(DestWin.c_str(), winflags);
428  if (moveToTopLeft) cvMoveWindow(DestWin.c_str(), 0,0);
429 
430  switch (img->depth) // bits
431  {
432  case 8:
433  if (strcmp(img->channelSeq, "BGR")==0)
434  {
435  // no swap required, is OpenCv native fmt
436  cvShowImage(DestWin.c_str(), img);
437  } else if (strcmp(img->channelSeq, "RGB")==0) {
438  // swap R-B
439  IplImage *p_swapped=NULL;
440  // TODO: keep a static copy here and check if sizes remain for higehr performance (avoid new/delete) (jw)
441  p_swapped = cvCreateImage( cvSize(img->width, img->height),
442  img->depth,
443  img->nChannels);
444  cvConvertImage( img, p_swapped, CV_CVTIMG_SWAP_RB);
445  cvShowImage(DestWin.c_str(), p_swapped);
446  cvReleaseImage(&p_swapped);
447  } else if ((strcmp(img->channelSeq, "GREY")==0) || (strcmp(img->channelSeq, "GRAY")==0)) {
448  cvShowImage(DestWin.c_str(), img);
449  } else if (strcmp(img->channelSeq, "RGBA")==0) {
450  if (allowAlphaWindow)
451  { // display extra alpha image?
452  // extract image with single alpha channel?
453  IplImage *p_alpha=cvCreateImage( cvSize(img->width, img->height),
454  8, // bits
455  1 // 1 alpha channel
456  );
457  for (int i=0; i<((p_alpha->width) * (p_alpha->height)); i++){
458  p_alpha->imageData[i] = img->imageData[4*i+3];
459  }
460  const string alphaWin = DestWin+"_alpha";
461  cvNamedWindow(alphaWin.c_str(), 1);
462  cvShowImage(alphaWin.c_str(), p_alpha); // Alpha luminace
463  cvReleaseImage(&p_alpha);
464  }
465 
466  // RGB(A) image
467  cvShowImage(DestWin.c_str(), img); // RGBA
468  } else {
469  BIASERR("Sorry, colorChannelSeq/colorModel unsupported. "<<endl
470  <<"bitdepth="<<img->depth<<" channelseq="<<img->channelSeq <<endl
471  <<"Please complete switch. Trying to display anyhow.");
472  cvShowImage(DestWin.c_str(), img);
473  }
474  break;
475  case 32:
476  {
477  // convert to 8 bit for display,
478  // asumme scaling from 0..1 to 0..255
479  IplImage *p_8bit=NULL;
480  p_8bit = cvCreateImage( cvSize(img->width, img->height),
481  8, // bits: 32 --> 8
482  img->nChannels);
483  // keep channel order. dest, src, count
484  // OpenCv ignores it but we need it for highgui
485  memcpy(p_8bit->channelSeq, img->channelSeq, 4);
486 
487  // convert the floats to 8 bit (with scaling and clipping):
488  ConvertIPL32to8(img, p_8bit, scale);
489 
490  // now we may need to additionally swap.
491  if (strcmp(p_8bit->channelSeq, "BGR")==0)
492  {
493  // no swap required, is OpenCv native fmt
494  cvShowImage(DestWin.c_str(), p_8bit);
495  } else if (strcmp(p_8bit->channelSeq, "RGB")==0) {
496  // swap R-B
497  IplImage *p_swapped=NULL;
498  // TODO: keep a static copy here and check if sizes remain for higehr performance (avoid new/delete) (jw)
499  p_swapped = cvCreateImage( cvSize(p_8bit->width, p_8bit->height),
500  p_8bit->depth,
501  p_8bit->nChannels);
502  cvConvertImage( p_8bit, p_swapped, CV_CVTIMG_SWAP_RB);
503  cvShowImage(DestWin.c_str(), p_swapped);
504  cvReleaseImage(&p_swapped);
505  } else if ((strcmp(p_8bit->channelSeq, "GREY")==0) || (strcmp(p_8bit->channelSeq, "GRAY")==0)) {
506  cvShowImage(DestWin.c_str(), p_8bit);
507  } else {
508  BIASERR("Sorry, colorChannelSeq/colorModel/depth unsupported. "<<endl
509  <<"bitdepth="<<img->depth<<" channelseq="<<img->channelSeq <<endl
510  <<"Please complete switch. Trying to display anyhow.");
511  cvShowImage(DestWin.c_str(), p_8bit);
512  }
513  }
514  break;
515  default:
516  BIASERR("Sorry, colorChannelSeq/colorModel/depth unsupported. "<<endl
517  <<"bitdepth="<<img->depth<<" channelseq="<<img->channelSeq <<endl
518  <<"Please complete switch. Trying to display anyhow.");
519  cvShowImage(DestWin.c_str(), img);
520  };
521 
522  if (waitForKey) {
523  return WrapBias2Ipl::WaitKey(delayMsec);
524  } else {
525  // always wait 1msec to trigger update of display.
527  return 0;
528  };
529 }
530 
531 
532 // static function wrappers (JW)
533 
535 {
536  cvDestroyAllWindows();
537 }
538 
539 void WrapBias2Ipl::DestroyWindow( const char* name )
540 {
541  cvDestroyWindow( name );
542 }
543 
544 void WrapBias2Ipl::DestroyWindow( const std::string & name )
545 {
546  DestroyWindow( name.c_str() );
547 }
548 
549 
550 void WrapBias2Ipl::ResizeWindow( const char* name,
551  const unsigned int width,
552  const unsigned int height )
553 {
554  cvResizeWindow( name, width, height );
555 }
556 
557 void WrapBias2Ipl::ResizeWindow( const std::string & name,
558  const unsigned int width,
559  const unsigned int height )
560 {
561  ResizeWindow( name.c_str(), width, height );
562 }
563 
564 
565 void WrapBias2Ipl::MoveWindow( const char* name, const int newX, const int newY )
566 {
567  cvMoveWindow( name, newX, newY );
568 }
569 
570 void WrapBias2Ipl::MoveWindow( const std::string & name, const int newX, const int newY )
571 {
572  MoveWindow( name.c_str(), newX, newY );
573 }
574 
575 
576 void WrapBias2Ipl::NamedWindow( const char* name, const int flags)
577 {
578  cvNamedWindow(name, flags);
579 }
580 
581 void WrapBias2Ipl::NamedWindow( const std::string & name, const int flags)
582 {
583  cvNamedWindow(name.c_str(), flags);
584 }
585 
586 
587 
588 #endif // BIAS_HAVE_OPENCV
589 
Bayer_GRBG, 1 channel RGB image Bayer tile.
Definition: ImageBase.hh:145
(16bit) unsigned integer image storage type
Definition: ImageBase.hh:114
static void MoveWindow(const char *name, const int newX, const int newY)
enum EStorageType StorageType_
the storage type in a pixel channel
Definition: ImageBase.hh:1056
gray values, 1 channel
Definition: ImageBase.hh:130
bool IsEmpty() const
check if ImageData_ points to allocated image buffer or not
Definition: ImageBase.hh:245
void CopyIn_NoInit(void *data)
Take some data and fill it into the Image.
Definition: ImageBase.cpp:827
bool IsInterleaved() const
Definition: ImageBase.hh:491
(8bit) signed char image storage type
Definition: ImageBase.hh:113
void SetColorModel(EColorModel Model)
Definition: ImageBase.hh:561
Bayer_RGGB, 1 channel RGB image Bayer tile.
Definition: ImageBase.hh:143
float image storage type
Definition: ImageBase.hh:118
static void DestroyAllWindows()
wrapper for CV destroiing all HighGUI windows JW
static void ResizeWindow(const char *name, const unsigned int width, const unsigned int height)
double image storage type
Definition: ImageBase.hh:119
static int CreateBiasImageCopy(const IplImage *p_src, BIAS::ImageBase &dest)
helper function to create a copy (!) BIAS image from a master Ipl image Data area is NOT shared but...
unsigned int GetWidth() const
Definition: ImageBase.hh:312
PGR XB3 in format 7 mode 3 delivers an image that consists of 3 channels with 8bbp (overal 24bpp)...
Definition: ImageBase.hh:152
invalid not set image storage type
Definition: ImageBase.hh:111
(16bit) signed integer image storage type
Definition: ImageBase.hh:115
color values, 3 channels, order: blue,green,red
Definition: ImageBase.hh:132
Bayer_BGGR, 1 channel RGB image Bayer tile.
Definition: ImageBase.hh:146
const void * GetImageData() const
Definition: ImageBase.hh:280
Bayer_GBRG, 1 channel RGB image Bayer tile.
Definition: ImageBase.hh:144
static void NamedWindow(const char *name, const int flags=1)
static void ConvertIPL32to8(const IplImage *src32, IplImage *dest8, const float &scale=DEFAULT_32to8_scale)
32 bit float to displayable 8 bit conversion Both images should be pre-initilaized to equal size and...
static int CreateIplImageShared(const BIAS::ImageBase *p_src, IplImage *&p_dest)
helper function to create a slave ipl image which shares the data area with the master ref...
unsigned int GetChannelCount() const
returns the number of Color channels, e.g.
Definition: ImageBase.hh:382
color values, 3 channels, order: red,green,blue
Definition: ImageBase.hh:131
unsigned int GetHeight() const
Definition: ImageBase.hh:319
RGBA, 4 channels, order: red,green,blue,alpha.
Definition: ImageBase.hh:141
void Release(const bool reset_storage_type=false)
Free the allocated data structures Hands off: Do !!NOT!! change the default of reset_storage_type: Im...
Definition: ImageBase.cpp:350
enum EColorModel GetColorModel() const
Definition: ImageBase.hh:407
const BIAS::ImageBase * p_imgBias
(32bit) signed integer image storage type
Definition: ImageBase.hh:117
void Init(unsigned int width, unsigned int height, unsigned int nChannels=1, enum EStorageType storageType=ST_unsignedchar, const bool interleaved=true)
Initialize image size and channels.
Definition: ImageBase.cpp:229
enum EStorageType GetStorageType() const
Definition: ImageBase.hh:414
(8bit) unsigned char image storage type
Definition: ImageBase.hh:112
static void DestroyWindow(const char *name)
This is the base class for images in BIAS.
Definition: ImageBase.hh:102
bool Consistent() const
static int Display(const IplImage *img, const std::string &DestWin, const bool &autoresize, const bool &moveToTopLeft, const bool &waitForKey, const unsigned int &delayMsec, const float &scale=DEFAULT_32to8_scale, const bool &allowAlphaWindow=ALLOW_ALPHA_WIN_DEFAULT)
Display img as simple popup window.
BGRA color values, 4 channels, order: blue,green,red,alpha.
Definition: ImageBase.hh:150
(32bit) unsigned integer image storage type
Definition: ImageBase.hh:116
static int WaitKey(const unsigned int &delay=0)
wrapper for cvWaitKey
int Bind(const BIAS::ImageBase *p_src)
create the internal IPL image which shares the data area with the src Bias image. ...