Audacity  3.0.3
Functions
ImageManipulation.cpp File Reference
#include "ImageManipulation.h"
#include <wx/colour.h>
#include <wx/image.h>
#include "AllThemeResources.h"
#include "Theme.h"
Include dependency graph for ImageManipulation.cpp:

Go to the source code of this file.

Functions

std::unique_ptr< wxImage > ChangeImageColour (wxImage *srcImage, wxColour &dstColour)
 
std::unique_ptr< wxImage > ChangeImageColour (wxImage *srcImage, wxColour &srcColour, wxColour &dstColour)
 
std::unique_ptr< wxImage > OverlayImage (wxImage *background, wxImage *foreground, wxImage *mask, int xoff, int yoff)
 
std::unique_ptr< wxImage > OverlayImage (teBmps eBack, teBmps eForeground, int xoff, int yoff)
 The index of a bitmap resource in Theme Resources. More...
 
std::unique_ptr< wxImage > CreateBackground (int width, int height, wxColour colour)
 
std::unique_ptr< wxImage > CreateAquaBackground (int width, int height, int offset)
 
std::unique_ptr< wxImage > CreateSysBackground (int width, int height, int WXUNUSED(offset), wxColour colour)
 
void PasteSubImage (wxImage *background, wxImage *foreground, int xoff, int yoff)
 
wxImage GetSubImageWithAlpha (const wxImage &Src, const wxRect &rect)
 

Detailed Description

Provides Image Manipulation functions.

wxWidgets misses some important functions involving cutting and pasting bitmaps, and (in version 2.6.1) is patchy in support of alpha channel. This collection of functions fills that gap.

Definition in file ImageManipulation.cpp.

Function Documentation

◆ ChangeImageColour() [1/2]

std::unique_ptr<wxImage> ChangeImageColour ( wxImage *  srcImage,
wxColour &  dstColour 
)

This looks at the first pixel in the image, and shifts the entire image by the vector difference between that pixel and the dstColour. For better control, use ChangeImageColour(wxImage, wxColour*, wxColour*) below

Definition at line 37 of file ImageManipulation.cpp.

38 {
39  unsigned char *src = srcImage->GetData();
40  wxColour c;
41  c.Set(src[0], src[1], src[2]);
42  return ChangeImageColour(srcImage, c, dstColour);
43 }

References ChangeImageColour().

Referenced by ChangeImageColour(), and ThemeBase::RecolourBitmap().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ChangeImageColour() [2/2]

std::unique_ptr<wxImage> ChangeImageColour ( wxImage *  srcImage,
wxColour &  srcColour,
wxColour &  dstColour 
)

This will explicitly shift the image color from srcColour to dstColour.

Definition at line 47 of file ImageManipulation.cpp.

50 {
51  // This function takes a source image, which it assumes to
52  // be grayscale, and smoothly changes the overall color
53  // to the specified color, and returns the result as a
54  // NEW image. This works well for grayscale 3D images.
55  // Audacity uses this routines to make the buttons
56  // (skip-start, play, stop, record, skip-end) adapt to
57  // the color scheme of the user.
58 
59  unsigned char *src = srcImage->GetData();
60  int width = srcImage->GetWidth();
61  int height = srcImage->GetHeight();
62 
63  auto dstImage = std::make_unique<wxImage>(width, height);
64  unsigned char *dst = dstImage->GetData();
65 
66 
67  //Get the source color
68  int srcVal[3], srcOpp[3];
69  srcVal[0] = srcColour.Red();
70  srcVal[1] = srcColour.Green();
71  srcVal[2] = srcColour.Blue();
72 
73  int dstVal[3], dstOpp[3];
74  dstVal[0] = dstColour.Red();
75  dstVal[1] = dstColour.Green();
76  dstVal[2] = dstColour.Blue();
77 
78  int i;
79  for (i = 0; i < 3; i++) {
80  srcOpp[i] = 256 - srcVal[i]; // avoid zero!
81  dstOpp[i] = 255 - dstVal[i];
82  }
83 
84  int c = 0;
85  for (i = 0; i < width * height * 3; i++) {
86  int s = (int) *src;
87 
88  if (s >= srcVal[c])
89  *dst++ = dstVal[c] + dstOpp[c] * (s - srcVal[c]) / srcOpp[c];
90 
91  else
92  *dst++ = dstVal[c] * s / srcVal[c];
93  src++;
94  c = (c + 1) % 3;
95  }
96 
97  if (srcImage->HasAlpha()) {
98  // Preserve transparencies
99  dstImage->InitAlpha();
100  memcpy(dstImage->GetAlpha(), srcImage->GetAlpha(), width * height);
101  }
102 
103  return dstImage;
104 }

◆ CreateAquaBackground()

std::unique_ptr<wxImage> CreateAquaBackground ( int  width,
int  height,
int  offset 
)

Definition at line 289 of file ImageManipulation.cpp.

290 {
291  auto image = std::make_unique<wxImage>(width, height);
292  unsigned char *ip = image->GetData();
293  unsigned char val[4] = {231, 239, 255, 239};
294  unsigned char v;
295  int x, y;
296 
297  for(y=0; y<height; y++) {
298  v = val[(y+offset)%4];
299  for(x=0; x<width*3; x++)
300  *ip++ = v;
301  }
302 
303  return image;
304 }

Referenced by CreateSysBackground().

Here is the caller graph for this function:

◆ CreateBackground()

std::unique_ptr<wxImage> CreateBackground ( int  width,
int  height,
wxColour  colour 
)

Definition at line 266 of file ImageManipulation.cpp.

267 {
268  auto i = std::make_unique<wxImage>(width, height);
269  unsigned char *ip;
270  int srcVal[3];
271  int x;
272 
273  srcVal[0] = colour.Red();
274  srcVal[1] = colour.Green();
275  srcVal[2] = colour.Blue();
276 
277  ip = i->GetData();
278  for(x=0; x<width*height; x++) {
279  *ip++ = srcVal[0];
280  *ip++ = srcVal[1];
281  *ip++ = srcVal[2];
282  }
283 
284  return i;
285 }

Referenced by CreateSysBackground().

Here is the caller graph for this function:

◆ CreateSysBackground()

std::unique_ptr<wxImage> CreateSysBackground ( int  width,
int  height,
int   WXUNUSEDoffset,
wxColour  colour 
)

Definition at line 306 of file ImageManipulation.cpp.

312 {
313  #ifdef USE_AQUA_THEME
314  return CreateAquaBackground(width, height, offset);
315  #else
316  return CreateBackground(width, height, colour);
317  #endif
318 }

References CreateAquaBackground(), and CreateBackground().

Here is the call graph for this function:

◆ GetSubImageWithAlpha()

wxImage GetSubImageWithAlpha ( const wxImage &  Src,
const wxRect &  rect 
)

Gets a rectangle from within another image, INCLUDING the alpha channel

Bug:
in wxWidgets, wxImage::GetSubImage should do this itself.

Definition at line 381 of file ImageManipulation.cpp.

382 {
383  //First part of this code is lifted from wxImage::GetSubImage() source code.
384  wxImage image;
385 
386  wxCHECK_MSG( Src.Ok(), image, wxT("invalid image") );
387 
388  wxCHECK_MSG( (rect.GetLeft()>=0) && (rect.GetTop()>=0) && (
389  rect.GetRight()<=Src.GetWidth()) && (rect.GetBottom()<=Src.GetHeight()),
390  image, wxT("invalid subimage size") );
391 
392  int subwidth=rect.GetWidth();
393  const int subheight=rect.GetHeight();
394 
395  image.Create( subwidth, subheight, false );
396 
397  unsigned char *subdata = image.GetData(), *data=Src.GetData();
398 
399  wxCHECK_MSG( subdata, image, wxT("unable to create image") );
400 
401  // JKC: Quick hack - don't deal with masks - need to understand macro M_IMGDATA first.
402 // if (Src.M_IMGDATA->m_hasMask)
403 // image.SetMaskColour( Src.M_IMGDATA->m_maskRed, Src.M_IMGDATA->m_maskGreen, Src.M_IMGDATA->m_maskBlue );
404 
405  int subleft=3*rect.GetLeft();
406  int width=3*Src.GetWidth();
407  subwidth*=3;
408 
409  data+=rect.GetTop()*width+subleft;
410 
411  for (long j = 0; j < subheight; ++j)
412  {
413  memcpy( subdata, data, subwidth);
414  subdata+=subwidth;
415  data+=width;
416  }
417 
418  image.InitAlpha();
419  if( !Src.HasAlpha() )
420  return image;
421  // OK, so we've copied the RGB data.
422  // Now do the Alpha channel.
423  //wxASSERT( Src.HasAlpha() );
424 
425  subleft/=3;
426  width/=3;
427  subwidth/=3;
428 
429  data =Src.GetAlpha();
430  subdata =image.GetAlpha();
431 
432  data+=rect.GetTop()*width+subleft;
433 
434  for (long j = 0; j < subheight; ++j)
435  {
436  memcpy( subdata, data, subwidth);
437  subdata+=subwidth;
438  data+=width;
439  }
440  return image;
441 }

Referenced by ThemeBase::ReadImageCache().

Here is the caller graph for this function:

◆ OverlayImage() [1/2]

std::unique_ptr<wxImage> OverlayImage ( teBmps  eBack,
teBmps  eForeground,
int  xoff,
int  yoff 
)

The index of a bitmap resource in Theme Resources.

Takes a background image, foreground image, and mask (i.e. the alpha channel for the foreground), and returns a NEW image where the foreground has been overlaid onto the background using alpha-blending, at location (xoff, yoff).

Definition at line 177 of file ImageManipulation.cpp.

179 {
180  wxImage imgBack(theTheme.Image( eBack ));
181  wxImage imgFore(theTheme.Image( eForeground ));
182 
183 
184  // TMP: dmazzoni - just so the code runs even though not all of
185  // our images have transparency...
186  if (!imgFore.HasAlpha())
187  return std::make_unique<wxImage>(imgBack);
188 
189 
190  wxASSERT( imgFore.HasAlpha() );
191 
192  unsigned char *bg = imgBack.GetData();
193  unsigned char *fg = imgFore.GetData();
194  unsigned char *mk = imgFore.GetAlpha();
195 
196  int bgWidth = imgBack.GetWidth();
197  int bgHeight = imgBack.GetHeight();
198  int fgWidth = imgFore.GetWidth();
199  int fgHeight = imgFore.GetHeight();
200 
201 
202  //Now, determine the dimensions of the images to be masked together
203  //on top of the background. This should be equal to the area of the
204  //smaller of the foreground and the mask, as long as it is
205  //within the area of the background, given the offset.
206 
207  //Make sure the foreground size is no bigger than the mask
208  int wCutoff = fgWidth;
209  int hCutoff = fgHeight;
210 
211 
212  // If the masked foreground + offset is bigger than the background, masking
213  // should only occur within these bounds of the foreground image
214  wCutoff = (bgWidth - xoff > wCutoff) ? wCutoff : bgWidth - xoff;
215  hCutoff = (bgHeight - yoff > hCutoff) ? hCutoff : bgHeight - yoff;
216 
217  //Make a NEW image the size of the background
218  auto dstImage = std::make_unique<wxImage>(bgWidth, bgHeight);
219  unsigned char *dst = dstImage->GetData();
220  memcpy(dst, bg, bgWidth * bgHeight * 3);
221 
222  // If background image has tranparency, then we want to blend with the
223  // current background colour.
224  if( imgBack.HasAlpha() ){
225  unsigned char *pAlpha = imgBack.GetAlpha();
226  wxColour c = theTheme.Colour( clrMedium );
227  unsigned char onePixImage[3];
228  // GetData() guarantees RGB order [wxWidgets does the ocnversion]
229  onePixImage[ 0 ] = c.Red();
230  onePixImage[ 1 ] = c.Green();
231  onePixImage[ 2 ] = c.Blue();
232  for( int i=0;i< bgWidth*bgHeight;i++){
233  unsigned char * pPix = &dst[ 3*i];
234  float alpha = 1.0 - (pAlpha[i]/255.0);
235  pPix[0] = pPix[0] + alpha *( (int)onePixImage[0]-(int)pPix[0]);
236  pPix[1] = pPix[1] + alpha *( (int)onePixImage[1]-(int)pPix[1]);
237  pPix[2] = pPix[2] + alpha *( (int)onePixImage[2]-(int)pPix[2]);
238  }
239  }
240 
241  // Go through the foreground image bit by bit and mask it on to the
242  // background, at an offset of xoff,yoff.
243  // BUT...Don't go beyond the size of the background image,
244  // the foreground image, or the mask
245  int x, y;
246  for (y = 0; y < hCutoff; y++) {
247 
248  unsigned char *bkp = bg + 3 * ((y + yoff) * bgWidth + xoff);
249  unsigned char *dstp = dst + 3 * ((y + yoff) * bgWidth + xoff);
250 
251  for (x = 0; x < wCutoff; x++) {
252 
253  int value = mk[(y * fgWidth + x)];// Don't multiply by 3...
254  int opp = 255 - value;
255 
256  for (int c = 0; c < 3; c++)
257  dstp[x * 3 + c] =
258  ((bkp[x * 3 + c] * opp) +
259  (fg[3 * (y * fgWidth + x) + c] * value)) / 255;
260  }
261  }
262  return dstImage;
263 }

References ThemeBase::Colour(), ThemeBase::Image(), and theTheme.

Here is the call graph for this function:

◆ OverlayImage() [2/2]

std::unique_ptr<wxImage> OverlayImage ( wxImage *  background,
wxImage *  foreground,
wxImage *  mask,
int  xoff,
int  yoff 
)

Takes a background image, foreground image, and mask (i.e. the alpha channel for the foreground), and returns a NEW image where the foreground has been overlaid onto the background using alpha-blending, at location (xoff, yoff).

Definition at line 111 of file ImageManipulation.cpp.

113 {
114  unsigned char *bg = background->GetData();
115  unsigned char *fg = foreground->GetData();
116  unsigned char *mk = mask->GetData();
117 
118  int bgWidth = background->GetWidth();
119  int bgHeight = background->GetHeight();
120  int fgWidth = foreground->GetWidth();
121  int fgHeight = foreground->GetHeight();
122  int mkWidth = mask->GetWidth();
123  int mkHeight = mask->GetHeight();
124 
125 
126  //Now, determine the dimensions of the images to be masked together
127  //on top of the background. This should be equal to the area of the
128  //smaller of the foreground and the mask, as long as it is
129  //within the area of the background, given the offset.
130 
131  //Make sure the foreground size is no bigger than the mask
132  int wCutoff = (fgWidth < mkWidth) ? fgWidth : mkWidth;
133  int hCutoff = (fgHeight < mkHeight) ? fgHeight : mkHeight;
134 
135 
136  // If the masked foreground + offset is bigger than the background, masking
137  // should only occur within these bounds of the foreground image
138  wCutoff = (bgWidth - xoff > wCutoff) ? wCutoff : bgWidth - xoff;
139  hCutoff = (bgHeight - yoff > hCutoff) ? hCutoff : bgHeight - yoff;
140 
141 
142  //Make a NEW image the size of the background
143  auto dstImage = std::make_unique<wxImage>(bgWidth, bgHeight);
144  unsigned char *dst = dstImage->GetData();
145  memcpy(dst, bg, bgWidth * bgHeight * 3);
146 
147 
148  // Go through the foreground image bit by bit and mask it on to the
149  // background, at an offset of xoff,yoff.
150  // BUT...Don't go beyond the size of the background image,
151  // the foreground image, or the mask
152  int x, y;
153  for (y = 0; y < hCutoff; y++) {
154 
155  unsigned char *bkp = bg + 3 * ((y + yoff) * bgWidth + xoff);
156  unsigned char *dstp = dst + 3 * ((y + yoff) * bgWidth + xoff);
157 
158  for (x = 0; x < wCutoff; x++) {
159 
160  int value = mk[3 * (y * mkWidth + x)];
161  int opp = 255 - value;
162 
163  for (int c = 0; c < 3; c++)
164  dstp[x * 3 + c] =
165  ((bkp[x * 3 + c] * opp) +
166  (fg[3 * (y * fgWidth + x) + c] * value)) / 255;
167  }
168  }
169  return dstImage;
170 }

Referenced by ToolBar::MakeAlternateImages(), and ToolBar::MakeButton().

Here is the caller graph for this function:

◆ PasteSubImage()

void PasteSubImage ( wxImage *  background,
wxImage *  foreground,
int  xoff,
int  yoff 
)

Pastes one image into another including the alpha channel. Differs from OverlayImage in that: Happens in place to existing background image. Pastes image on top; no blending with existing background is done.

Definition at line 324 of file ImageManipulation.cpp.

325 {
326 
327  unsigned char *bg = background->GetData();
328  unsigned char *fg = foreground->GetData();
329  unsigned char *bgAlpha = background->HasAlpha() ? background->GetAlpha() : NULL;
330  unsigned char *fgAlpha = foreground->HasAlpha() ? foreground->GetAlpha() : NULL;
331  // For testing... Set as if no alpha in foreground....
332  // fgAlpha = NULL;
333 
334  int bgWidth = background->GetWidth();
335  int bgHeight = background->GetHeight();
336  int fgWidth = foreground->GetWidth();
337  int fgHeight = foreground->GetHeight();
338 
339  int wCutoff = fgWidth;
340  int hCutoff = fgHeight;
341 
342  // If the masked foreground + offset is bigger than the background, masking
343  // should only occur within these bounds of the foreground image
344  wCutoff = (bgWidth - xoff > wCutoff) ? wCutoff : bgWidth - xoff;
345  hCutoff = (bgHeight - yoff > hCutoff) ? hCutoff : bgHeight - yoff;
346 
347  // Go through the foreground image bit by bit and place it on to the
348  // background, at an offset of xoff,yoff.
349  // Don't go beyond the size of the background image,
350  // or the foreground image.
351  int y;
352  unsigned char *bkp;
353  unsigned char *fgp;
354  unsigned char *bgAlphap;
355  unsigned char *fgAlphap;
356  for (y = 0; y < hCutoff; y++) {
357  // RGB bytes
358  bkp = bg + 3 * ((y + yoff) * bgWidth + xoff);
359  fgp = fg + 3 * ( y * fgWidth);
360  memcpy( bkp, fgp, 3 * wCutoff );
361 
362  // Alpha bytes.
363  if( bgAlpha )
364  {
365  bgAlphap = bgAlpha + ((y+yoff) * bgWidth + xoff );
366  if( fgAlpha )
367  {
368  fgAlphap = fgAlpha + (y * fgWidth );
369  memcpy( bgAlphap, fgAlphap, wCutoff );
370  }
371  else
372  {
373  memset( bgAlphap, 255, wCutoff );
374  }
375  }
376  }
377 }

Referenced by ThemeBase::CreateOneImageCache().

Here is the caller graph for this function:
av_intfloat32::i
uint32_t i
Definition: ffmpeg-2.3.6-single-header.h:525
CreateBackground
std::unique_ptr< wxImage > CreateBackground(int width, int height, wxColour colour)
Definition: ImageManipulation.cpp:266
ThemeBase::Image
wxImage & Image(int iIndex)
Definition: Theme.cpp:1217
ChangeImageColour
std::unique_ptr< wxImage > ChangeImageColour(wxImage *srcImage, wxColour &dstColour)
Definition: ImageManipulation.cpp:37
theTheme
THEME_API Theme theTheme
Definition: Theme.cpp:79
CreateAquaBackground
std::unique_ptr< wxImage > CreateAquaBackground(int width, int height, int offset)
Definition: ImageManipulation.cpp:289
ThemeBase::Colour
wxColour & Colour(int iIndex)
Definition: Theme.cpp:1189