// // Passe 1 : Réduit la palette aux x couleurs de la palette du CPC. // Effectue également un traitement de l'erreur (tramage) si demandé. // Calcule le nombre de couleurs utilisées dans l'image, et // remplit le tableau coulTrouvee avec ces couleurs // static private void ConvertPasse1(DirectBitmap source, ImageCpc dest, Param prm) { int pct = Dither.SetMatDither(prm); RvbColor p = new RvbColor(0), choix, n1, n2; int indexChoix = 0; int incY = prm.trameTc ? 4 : 2; for (int yPix = 0; yPix < BitmapCpc.TailleY; yPix += incY) { int Tx = BitmapCpc.CalcTx(yPix); for (int xPix = 0; xPix < BitmapCpc.TailleX; xPix += Tx) { for (int yy = 0; yy < incY; yy += 2) { p = GetPixel(source, xPix, yy + yPix, Tx, prm, pct); // Recherche le point dans la couleur cpc la plus proche if (prm.cpcPlus) { choix = new RvbColor((byte)((p.r >> 4) * 17), (byte)((p.v >> 4) * 17), (byte)((p.b >> 4) * 17)); indexChoix = ((choix.v << 4) & 0xF00) + ((choix.b) & 0xF0) + ((choix.r) >> 4); } else { indexChoix = GetNumColorPixelCpc(prm, p); choix = BitmapCpc.RgbCPC[indexChoix]; } coulTrouvee[indexChoix, yPix >> 1]++; if (!prm.trameTc) { source.SetPixel(xPix, yy + yPix, prm.setPalCpc ? choix : p); } } if (prm.trameTc) { // Moyenne des 2 pixels RvbColor p0 = GetPixel(source, xPix, yPix, Tx, prm, pct); RvbColor p1 = GetPixel(source, xPix, yPix + 2, Tx, prm, pct); int r = (p0.r + p1.r); int v = (p0.v + p1.v); int b = (p0.b + p1.b); if (prm.cpcPlus) { n1 = new RvbColor((byte)((r >> 4) * 8), (byte)((v >> 4) * 8), (byte)((b >> 4) * 8)); n2 = new RvbColor((byte)((r >> 5) * 8), (byte)((v >> 5) * 8), (byte)((b >> 5) * 8)); } else { n1 = BitmapCpc.RgbCPC[(r > prm.cstR3 ? 6 : r > prm.cstR1 ? 3 : 0) + (v > prm.cstV3 ? 18 : v > prm.cstV1 ? 9 : 0) + (b > prm.cstB3 ? 2 : b > prm.cstB1 ? 1 : 0)]; n2 = BitmapCpc.RgbCPC[(r > prm.cstR4 ? 6 : r > prm.cstR2 ? 3 : 0) + (v > prm.cstV4 ? 18 : v > prm.cstV2 ? 9 : 0) + (b > prm.cstB4 ? 2 : b > prm.cstB2 ? 1 : 0)]; } source.SetPixel(xPix, yPix, (xPix & Tx) == 0 ? n1 : n2); source.SetPixel(xPix, yPix + 2, (xPix & Tx) == 0 ? n2 : n1); } } } }
static private RvbColor GetPixel(DirectBitmap source, int xPix, int yPix, int Tx, Param prm, int pct) { RvbColor p = new RvbColor(0); if (prm.lissage) { float r = 0, v = 0, b = 0; for (int i = 0; i < Tx; i++) { p = source.GetPixelColor(xPix + i, yPix); r += p.r; b += p.b; v += p.v; } p.r = (byte)(r / Tx); p.v = (byte)(v / Tx); p.b = (byte)(b / Tx); } else { p = source.GetPixelColor(xPix, yPix); } switch (prm.bitsRVB) { //12 bits (4 bits par composantes) case 12: p.r = (byte)((p.r >> 4) * 17); p.v = (byte)((p.v >> 4) * 17); p.b = (byte)((p.b >> 4) * 17); break; // 9 bits (3 bits par composantes) case 9: p.r = (byte)((p.r >> 5) * 36); p.v = (byte)((p.v >> 5) * 36); p.b = (byte)((p.b >> 5) * 36); break; // 6 bits (2 bits par composantes) case 6: p.r = (byte)((p.r >> 6) * 85); p.v = (byte)((p.v >> 6) * 85); p.b = (byte)((p.b >> 6) * 85); break; } int m1 = (prm.reductPal1 ? 0x11 : 0x00) | (prm.reductPal3 ? 0x22 : 0x00); int m2 = (prm.reductPal2 ? 0xEE : 0xFF) & (prm.reductPal4 ? 0xDD : 0xFF); p.r = MinMaxByte(((p.r | m1) & m2) * prm.pctRed / 100.0); p.v = MinMaxByte(((p.v | m1) & m2) * prm.pctGreen / 100.0); p.b = MinMaxByte(((p.b | m1) & m2) * prm.pctBlue / 100.0); if (p.r != 0 || p.v != 0 || p.b != 0) { float r = tblContrast[p.r]; float v = tblContrast[p.v]; float b = tblContrast[p.b]; if (prm.pctLumi != 100 || prm.pctSat != 100) { SetLumiSat(prm.pctLumi > 100 ? (100 + (prm.pctLumi - 100) * 2) / 100.0F : prm.pctLumi / 100.0F, prm.pctSat / 100.0F, ref r, ref v, ref b); } p.r = MinMaxByte(r); p.v = MinMaxByte(v); p.b = MinMaxByte(b); } // Appliquer la matrice de tramage if (pct > 0) { RvbColor choix = prm.cpcPlus ? new RvbColor((byte)((p.r >> 4) * 17), (byte)((p.v >> 4) * 17), (byte)((p.b >> 4) * 17)) : BitmapCpc.RgbCPC[GetNumColorPixelCpc(prm, p)]; Dither.DoDitherFull(source, xPix, yPix, Tx, p, choix, prm.diffErr); } return(p); }