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).
| 109 | /// overlaid onto the background using alpha-blending, |
| 110 | /// at location (xoff, yoff). |
| 111 | std::unique_ptr<wxImage> OverlayImage(wxImage * background, wxImage * foreground, |
| 112 | wxImage * mask, int xoff, int yoff) |
| 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 | } |
no test coverage detected