private void RenderAlphaBar() { _boxA.Lock(); var buf = _boxA.Buffer; int w = _boxA.Width; int h = _boxA.Height; var info = new AlphaPixel( (w + 1) / 2, Utils.AlphaShades, _chn[0], _chn[1], _chn[2], 1f ); for (int i = 0; i < buf.Length; i += 4) { int idx = i / 4; info.alpha = 1f - (float)(idx / w) / (float)h; RenderAlphaPixel(info, buf, w, h, idx); } _boxA.Unlock(); }
private void RenderRightBar() { _boxZ.Lock(); var buf = _boxZ.Buffer; int w = _boxZ.Width; int h = _boxZ.Height; float[] axes = new float[3]; axes[_order[1]] = _chn[_order[1]]; axes[_order[2]] = _chn[_order[2]]; int a3 = _order[3]; for (int i = 0; i < buf.Length; i += 4) { axes[a3] = 1f - (float)((i / 4) / w) / (float)h; RenderOpaquePixel(axes[0], axes[1], axes[2], buf, w, h, i / 4); } _boxZ.Unlock(); }
private void RenderMainBox() { _boxXY.Lock(); var buf = _boxXY.Buffer; int w = _boxXY.Width; int h = _boxXY.Height; float[] axes = new float[3]; int a1 = _order[1]; int a2 = _order[2]; axes[_order[3]] = _chn[_order[3]]; for (int i = 0; i < buf.Length; i += 4) { axes[a1] = 1f - (float)((i / 4) % w) / (float)w; axes[a2] = 1f - (float)((i / 4) / w) / (float)h; RenderOpaquePixel(axes[0], axes[1], axes[2], buf, w, h, i / 4); } _boxXY.Unlock(); }
private void RenderSampleBox() { _boxSample.Lock(); var buf = _boxSample.Buffer; int w = _boxSample.Width; int h = _boxSample.Height; var info = new AlphaPixel( w / 8, Utils.AlphaShades, _chn[0], _chn[1], _chn[2], _chn[3] ); for (int idx = 0; idx < buf.Length / 4; idx++) { RenderAlphaPixel(info, buf, w, h, idx); } _boxSample.Unlock(); }
public void Draw() { if (_pal == null || this.Height <= 0) { return; } float[] shades = { Utils.AlphaShades[0] * 255f, Utils.AlphaShades[1] * 255f }; // Calculate the brightness of each color to determine its opposite luminance pole (black or white) uint[] colors = _pal.GetList(); _palPolarLum = new int[_palLen]; const int white = 0, black = 1; for (int i = 0; i < _palLen; i++) { uint clr = colors[i]; double a = (double)(clr & 0xff) / 255f; double r = (double)((clr >> 8) & 0xff) / 255f; double g = (double)((clr >> 16) & 0xff) / 255f; double b = (double)(clr >> 24) / 255f; /* * // If a cell is selected and it's not this cell, increase the brightness * if (CurrentCell >= 0 && i != CurrentCell) * { * r = 1 - ((1 - r) / 2); * g = 1 - ((1 - g) / 2); * b = 1 - ((1 - b) / 2); * } */ double lum = 0.2126 * r + 0.7152 * g + 0.0722 * b; lum += (1f - lum) * (1f - a); _palPolarLum[i] = lum >= 0.5f ? black : white; // Reverse pixel channel order colors[i] = Utils.ComposeBGRA(a, r, g, b); } _box.Lock(); var buf = _box.Buffer; int width = _box.Image.Size.Width; int height = _box.Image.Size.Height; float visRowsF = (float)VisibleRows; float cellW = (float)width / (float)_nCols; float cellH = (float)height / visRowsF; // Minus one because maximum value is the last index, not the size int nDigits = Utils.DigitCount(_palLen - 1); float numW = (float)(DigitImages.digitW * nDigits); float numH = (float)DigitImages.digitH; const float border = 1; int firstCellIdx = FirstVisibleCell; int idx = 0; for (int i = 0; i < height; i++) { int y = (int)((float)i / cellH); float subY = (float)i % cellH; int cellY = firstCellIdx + y * _nCols; for (int j = 0; j < width; j++) { int x = (int)((float)j / cellW); float subX = (float)j % cellW; int cell = cellY + x; if ((cell == CurrentCell || cell == _hoveredCell) && (subX < border || subX >= cellW - border || subY < border || subY >= cellH - border)) { if (_palPolarLum[cell] == white) { buf[idx++] = 0xff; buf[idx++] = 0xff; buf[idx++] = 0xff; } else { buf[idx++] = 0; buf[idx++] = 0; buf[idx++] = 0; } buf[idx++] = 0xff; continue; } // In most cases, no pixel blending occurs. // Therefore, we just use the quickest method (I think) to copy a pixel to a pixel buffer in C#. // Note that pixels are laid out as b.g.r.a in memory and x86 is little-endian, // meaning that we need to make sure colors[cell] (the input) is written as 0xaarrggbb before copying. Buffer.BlockCopy(colors, cell * 4, buf, idx, 4); // If the colour isn't fully opaque if (buf[idx + 3] != 0xff) { int tileX = ((j % 16) < 8) ? 1 : 0; int tileY = ((i % 16) < 8) ? 1 : 0; float sh = shades[tileX ^ tileY]; BlendPixel(buf, idx, sh, sh, sh, (float)(255 - buf[idx + 3]) / 255f); buf[idx + 3] = 0xff; } // If this pixel is in the top-left corner, blend it with its corresponding pixel inside the appropriate digit bitmap. // Plain English: this is the part where we draw the numbers. if (subY < numH && subX < numW) { // XOR 1 because we want the text colour to oppose the brightness level of the cell int clrVersion = _palPolarLum[cell] ^ 1; int numLine = (cell * 2 + clrVersion) * (int)numH; int numPixIdx = ((numLine + (int)subY) * (int)numW + (int)subX) * Utils.cLen; // If the current pixel inside the digit bitmap isn't fully transparent if (_palNumbers[numPixIdx + 3] != 0) { float dgAlpha = (float)_palNumbers[numPixIdx + 3] / 255f; BlendPixel(buf, idx, (float)_palNumbers[numPixIdx], (float)_palNumbers[numPixIdx + 1], (float)_palNumbers[numPixIdx + 2], dgAlpha); } } idx += 4; } } _box.Unlock(); }