Audacity 3.2.0
Typedefs | Functions
ImageManipulation.h File Reference
#include <memory>
#include <wx/defs.h>
Include dependency graph for ImageManipulation.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Typedefs

using teBmps = int
 

Functions

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

Typedef Documentation

◆ teBmps

using teBmps = int

Definition at line 48 of file ImageManipulation.h.

Function Documentation

◆ ChangeImageColour() [1/2]

THEME_API 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}
std::unique_ptr< wxImage > ChangeImageColour(wxImage *srcImage, wxColour &dstColour)

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]

THEME_API 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()

THEME_API 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()

THEME_API 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()

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

◆ GetSubImageWithAlpha()

THEME_API 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]

THEME_API 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}
THEME_API Theme theTheme
Definition: Theme.cpp:82
wxColour & Colour(int iIndex)
wxImage & Image(int iIndex)

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

Here is the call graph for this function:

◆ OverlayImage() [2/2]

THEME_API 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()

THEME_API 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: