예제 #1
0
        // internal helpers

        //-------------------------------------------------
        //  adjust_palette_entry - adjust a palette
        //  entry for brightness
        //-------------------------------------------------
        rgb_t adjust_palette_entry(rgb_t entry, float brightness, float contrast, uint8_t [] gamma_map)
        {
            int r = rgb_t.clamp((int)((float)(gamma_map[entry.r()]) * contrast + brightness));
            int g = rgb_t.clamp((int)((float)(gamma_map[entry.g()]) * contrast + brightness));
            int b = rgb_t.clamp((int)((float)(gamma_map[entry.b()]) * contrast + brightness));
            int a = entry.a();

            return(new rgb_t((uint8_t)a, (uint8_t)r, (uint8_t)g, (uint8_t)b));
        }
예제 #2
0
        // utilities
        public void normalize_range(uint32_t start, uint32_t end, int lum_min = 0, int lum_max = 255)
        {
            // clamp within range
            // start = std::max(start, 0U); ==> reduces to start = start
            end = std.min(end, m_numcolors - 1);

            // find the minimum and maximum brightness of all the colors in the range
            int32_t ymin = 1000 * 255;
            int32_t ymax = 0;

            for (uint32_t index = start; index <= end; index++)
            {
                rgb_t    rgb = m_entry_color[index];
                uint32_t y   = (uint32_t)(299 * rgb.r() + 587 * rgb.g() + 114 * rgb.b());
                ymin = (int32_t)std.min((uint32_t)ymin, y);
                ymax = (int32_t)std.max((uint32_t)ymax, y);
            }

            // determine target minimum/maximum
            int32_t tmin = (lum_min < 0) ? ((ymin + 500) / 1000) : lum_min;
            int32_t tmax = (lum_max < 0) ? ((ymax + 500) / 1000) : lum_max;

            // now normalize the palette
            for (uint32_t index = start; index <= end; index++)
            {
                rgb_t   rgb    = m_entry_color[index];
                int32_t y      = 299 * rgb.r() + 587 * rgb.g() + 114 * rgb.b();
                int32_t u      = ((int32_t)rgb.b() - y / 1000) * 492 / 1000;
                int32_t v      = ((int32_t)rgb.r() - y / 1000) * 877 / 1000;
                int32_t target = tmin + ((y - ymin) * (tmax - tmin + 1)) / (ymax - ymin);
                uint8_t r      = rgb_t.clamp(target + 1140 * v / 1000);
                uint8_t g      = rgb_t.clamp(target - 395 * u / 1000 - 581 * v / 1000);
                uint8_t b      = rgb_t.clamp(target + 2032 * u / 1000);
                entry_set_color(index, new rgb_t(r, g, b));
            }
        }
예제 #3
0
        /*-------------------------------------------------
        *   resample_argb_bitmap_bilinear - perform texture
        *   sampling via a bilinear filter
        *  -------------------------------------------------*/
        static void resample_argb_bitmap_bilinear(PointerU32 dest, u32 drowpixels, u32 dwidth, u32 dheight, PointerU32 source, u32 srowpixels, u32 swidth, u32 sheight, render_color color, u32 dx, u32 dy)  //static void resample_argb_bitmap_bilinear(u32 *dest, u32 drowpixels, u32 dwidth, u32 dheight, const u32 *source, u32 srowpixels, u32 swidth, u32 sheight, const render_color &color, u32 dx, u32 dy)
        {
            u32 maxx = swidth << 12;
            u32 maxy = sheight << 12;
            u32 r;
            u32 g;
            u32 b;
            u32 a;
            u32 x;
            u32 y;

            /* precompute premultiplied R/G/B/A factors */
            r = (u32)(color.r * color.a * 256.0f);
            g = (u32)(color.g * color.a * 256.0f);
            b = (u32)(color.b * color.a * 256.0f);
            a = (u32)(color.a * 256.0f);

            /* loop over the target vertically */
            for (y = 0; y < dheight; y++)
            {
                u32 starty = y * dy;

                /* loop over the target horizontally */
                for (x = 0; x < dwidth; x++)
                {
                    u32   startx = x * dx;
                    rgb_t pix0;
                    rgb_t pix1;
                    rgb_t pix2;
                    rgb_t pix3;
                    u32   sumr;
                    u32   sumg;
                    u32   sumb;
                    u32   suma;
                    u32   nextx;
                    u32   nexty;
                    u32   curx;
                    u32   cury;
                    u32   factor;

                    /* adjust start to the center; note that this math will tend to produce */
                    /* negative results on the first pixel, which is why we clamp below */
                    curx = startx + dx / 2 - 0x800;
                    cury = starty + dy / 2 - 0x800;

                    /* compute the neighboring pixel */
                    nextx = curx + 0x1000;
                    nexty = cury + 0x1000;

                    /* fetch the four relevant pixels */
                    pix0 = pix1 = pix2 = pix3 = new rgb_t(0);
                    if ((int)cury >= 0 && cury < maxy && (int)curx >= 0 && curx < maxx)
                    {
                        pix0 = new rgb_t(source[(cury >> 12) * srowpixels + (curx >> 12)]);  //pix0 = source[(cury >> 12) * srowpixels + (curx >> 12)];
                    }
                    if ((int)cury >= 0 && cury < maxy && (int)nextx >= 0 && nextx < maxx)
                    {
                        pix1 = new rgb_t(source[(cury >> 12) * srowpixels + (nextx >> 12)]);  //pix1 = source[(cury >> 12) * srowpixels + (nextx >> 12)];
                    }
                    if ((int)nexty >= 0 && nexty < maxy && (int)curx >= 0 && curx < maxx)
                    {
                        pix2 = new rgb_t(source[(nexty >> 12) * srowpixels + (curx >> 12)]);  //pix2 = source[(nexty >> 12) * srowpixels + (curx >> 12)];
                    }
                    if ((int)nexty >= 0 && nexty < maxy && (int)nextx >= 0 && nextx < maxx)
                    {
                        pix3 = new rgb_t(source[(nexty >> 12) * srowpixels + (nextx >> 12)]);  //pix3 = source[(nexty >> 12) * srowpixels + (nextx >> 12)];
                    }
                    /* compute the x/y scaling factors */
                    curx &= 0xfff;
                    cury &= 0xfff;

                    /* contributions from pixel 0 (top,left) */
                    factor = (0x1000 - curx) * (0x1000 - cury);
                    sumr   = factor * pix0.r();
                    sumg   = factor * pix0.g();
                    sumb   = factor * pix0.b();
                    suma   = factor * pix0.a();

                    /* contributions from pixel 1 (top,right) */
                    factor = curx * (0x1000 - cury);
                    sumr  += factor * pix1.r();
                    sumg  += factor * pix1.g();
                    sumb  += factor * pix1.b();
                    suma  += factor * pix1.a();

                    /* contributions from pixel 2 (bottom,left) */
                    factor = (0x1000 - curx) * cury;
                    sumr  += factor * pix2.r();
                    sumg  += factor * pix2.g();
                    sumb  += factor * pix2.b();
                    suma  += factor * pix2.a();

                    /* contributions from pixel 3 (bottom,right) */
                    factor = curx * cury;
                    sumr  += factor * pix3.r();
                    sumg  += factor * pix3.g();
                    sumb  += factor * pix3.b();
                    suma  += factor * pix3.a();

                    /* apply scaling */
                    suma = (suma >> 24) * a / 256;
                    sumr = (sumr >> 24) * r / 256;
                    sumg = (sumg >> 24) * g / 256;
                    sumb = (sumb >> 24) * b / 256;

                    /* if we're translucent, add in the destination pixel contribution */
                    if (a < 256)
                    {
                        rgb_t dpix = new rgb_t(dest[y * drowpixels + x]);  //rgb_t dpix = dest[y * drowpixels + x];
                        suma += dpix.a() * (256 - a);
                        sumr += dpix.r() * (256 - a);
                        sumg += dpix.g() * (256 - a);
                        sumb += dpix.b() * (256 - a);
                    }

                    /* store the target pixel, dividing the RGBA values by the overall scale factor */
                    dest[y * drowpixels + x] = new rgb_t((u8)suma, (u8)sumr, (u8)sumg, (u8)sumb);  //dest[y * drowpixels + x] = rgb_t(suma, sumr, sumg, sumb);
                }
            }
        }
예제 #4
0
        /*-------------------------------------------------
        *   resample_argb_bitmap_average - resample a texture
        *   by performing a true weighted average over
        *   all contributing pixels
        *  -------------------------------------------------*/
        static void resample_argb_bitmap_average(PointerU32 dest, u32 drowpixels, u32 dwidth, u32 dheight, PointerU32 source, u32 srowpixels, u32 swidth, u32 sheight, render_color color, u32 dx, u32 dy)  //static void resample_argb_bitmap_average(u32 *dest, u32 drowpixels, u32 dwidth, u32 dheight, const u32 *source, u32 srowpixels, u32 swidth, u32 sheight, const render_color &color, u32 dx, u32 dy)
        {
            u64 sumscale = (u64)dx * (u64)dy;
            u32 r;
            u32 g;
            u32 b;
            u32 a;
            u32 x;
            u32 y;

            /* precompute premultiplied R/G/B/A factors */
            r = (u32)(color.r * color.a * 256.0f);
            g = (u32)(color.g * color.a * 256.0f);
            b = (u32)(color.b * color.a * 256.0f);
            a = (u32)(color.a * 256.0f);

            /* loop over the target vertically */
            for (y = 0; y < dheight; y++)
            {
                u32 starty = y * dy;

                /* loop over the target horizontally */
                for (x = 0; x < dwidth; x++)
                {
                    u64 sumr   = 0;
                    u64 sumg   = 0;
                    u64 sumb   = 0;
                    u64 suma   = 0;
                    u32 startx = x * dx;
                    u32 xchunk;
                    u32 ychunk;
                    u32 curx;
                    u32 cury;

                    u32 yremaining = dy;

                    /* accumulate all source pixels that contribute to this pixel */
                    for (cury = starty; yremaining != 0; cury += ychunk)
                    {
                        u32 xremaining = dx;

                        /* determine the Y contribution, clamping to the amount remaining */
                        ychunk = 0x1000 - (cury & 0xfff);
                        if (ychunk > yremaining)
                        {
                            ychunk = yremaining;
                        }
                        yremaining -= ychunk;

                        /* loop over all source pixels in the X direction */
                        for (curx = startx; xremaining != 0; curx += xchunk)
                        {
                            u32 factor;

                            /* determine the X contribution, clamping to the amount remaining */
                            xchunk = 0x1000 - (curx & 0xfff);
                            if (xchunk > xremaining)
                            {
                                xchunk = xremaining;
                            }
                            xremaining -= xchunk;

                            /* total contribution = x * y */
                            factor = xchunk * ychunk;

                            /* fetch the source pixel */
                            rgb_t pix = new rgb_t(source[(cury >> 12) * srowpixels + (curx >> 12)]);  //rgb_t pix = source[(cury >> 12) * srowpixels + (curx >> 12)];

                            /* accumulate the RGBA values */
                            sumr += factor * pix.r();
                            sumg += factor * pix.g();
                            sumb += factor * pix.b();
                            suma += factor * pix.a();
                        }
                    }

                    /* apply scaling */
                    suma = (suma / sumscale) * a / 256;
                    sumr = (sumr / sumscale) * r / 256;
                    sumg = (sumg / sumscale) * g / 256;
                    sumb = (sumb / sumscale) * b / 256;

                    /* if we're translucent, add in the destination pixel contribution */
                    if (a < 256)
                    {
                        rgb_t dpix = new rgb_t(dest[y * drowpixels + x]);  //rgb_t dpix = dest[y * drowpixels + x];
                        suma += dpix.a() * (256 - a);
                        sumr += dpix.r() * (256 - a);
                        sumg += dpix.g() * (256 - a);
                        sumb += dpix.b() * (256 - a);
                    }

                    /* store the target pixel, dividing the RGBA values by the overall scale factor */
                    dest[y * drowpixels + x] = new rgb_t((u8)suma, (u8)sumr, (u8)sumg, (u8)sumb);  //dest[y * drowpixels + x] = rgb_t(suma, sumr, sumg, sumb);
                }
            }
        }