示例#1
0
int
CreateCompositeImage(CompositeParameters &params, const char *outName)
{
    // Try to read in all of the inputs.
    bool noError = true;
    int i;
    for(i = 0; i < params.nViewports && noError; ++i)
    {
        params.viewports[i]->file = new ImageObject;
        noError = params.viewports[i]->file->Read(
            params.viewports[i]->imageName);
    }
    if(!noError)
    {
        fprintf(stderr, "The following files could not be read:\n");
        for(i = 0; i < params.nViewports; ++i)
            fprintf(stderr, "\t%s\n", params.viewports[i]->imageName);
        return -3;
    }

    int startViewport = 0;
    ImageObject *output = 0;
    int width, height;
    if(strcmp(params.backgroundFile, params.viewports[0]->imageName) == 0)
    {
        startViewport = 1;
        width = params.viewports[0]->file->Width();
        height = params.viewports[0]->file->Height();
        output = params.viewports[0]->file;
    }
    else
    {
        width = params.outputSize[0];
        height = params.outputSize[1];
        output = new ImageObject(width, height);

        // Set the image's background color.
        unsigned char *cptr = output->Pixel(0,0);
        unsigned int sz = width * height;
        for(unsigned int s = 0; s < sz; ++s)
        {
            *cptr++ = params.outputBackground[0];
            *cptr++ = params.outputBackground[1];
            *cptr++ = params.outputBackground[2];
        }
    }

    // Calculate some shadow parameters based on the image size.
    int offx = int(params.shadowOffsetX * width);
    int offy = int(params.shadowOffsetY * height);
    if (offx > offy)
        offy = offx;
    else
        offx = offy;
    int blurRad = int(params.shadowBlurRadius * width);

    // Now that we have all of the images in memory and we've decided
    // which one is the background image, we should begin compositing.
    for(i = startViewport; i < params.nViewports; ++i)
    {
        int start_x = int(params.viewports[i]->coordinates[0] * width);
        int start_y = int(height - params.viewports[i]->coordinates[1] * height);

        int img_w = params.viewports[i]->file->Width();
        int img_h = params.viewports[i]->file->Height();

        if(params.viewports[i]->hasDropShadow)
        {
            ImageObject *mask = CreateDropShadowMask(params.viewports[i], 
                offx, offy, blurRad);

            if(mask != 0)
            {
                // Now that we have a drop shadow mask, let's use it to blend
                // the destination pixels with black. Values in the mask that
                // are white should be more black in the destination image.
                // Of course, we should limit the amount of black that we can
                // make a shadow.
                for(int masky = 0; masky < mask->Height(); ++masky)
                {
                    int real_y = start_y - img_h + masky;
                    for(int maskx = 0; maskx < mask->Width(); ++maskx)
                    {
                        int real_x = start_x + maskx;
                        if(real_x >= 0 && real_x < width &&
                           real_y >= 0 && real_y < height)
                        {
                            unsigned char *mask_value = mask->Pixel(maskx, masky);
                            unsigned char *dest = output->Pixel(real_x, real_y);
                            float t = (float(*mask_value) / 255.f) * 0.5;
                            float r = float(dest[0]);
                            float g = float(dest[1]);
                            float b = float(dest[2]);
                            float new_r = (1. - t) * r + t * 0.2;
                            float new_g = (1. - t) * g + t * 0.2;
                            float new_b = (1. - t) * b + t * 0.2;
                            dest[0] = (unsigned char)((int)(new_r));
                            dest[1] = (unsigned char)((int)(new_g));
                            dest[2] = (unsigned char)((int)(new_b));
                        }
                    }
                }
                delete mask;
            }
        }

        // Now that we've drawn a drop shadow, if needed, draw the image.
        if(params.viewports[i]->opaqueMode == M_OPAQUE)
        {
            for(int y = 0; y < img_h; ++y)
            {
                int real_y = start_y - img_h + y;
                for(int x = 0; x < img_w; ++x)
                {
                    int real_x = start_x + x;
                    if(real_x >= 0 && real_x < width &&
                       real_y >= 0 && real_y < height)
                    {
                        unsigned char *src = params.viewports[i]->file->Pixel(x, y);
                        unsigned char *dest = output->Pixel(real_x, real_y);

                        *dest++ = *src++;
                        *dest++ = *src++;
                        *dest = *src;
                    }
                }
            }
        }
        else if(params.viewports[i]->opaqueMode == M_TRANSPARENT)
        {
            for(int y = 0; y < img_h; ++y)
            {
                int real_y = start_y - img_h + y;
                for(int x = 0; x < img_w; ++x)
                {
                    int real_x = start_x + x;
                    if(real_x >= 0 && real_x < width &&
                       real_y >= 0 && real_y < height)
                    {
                        unsigned char *src = params.viewports[i]->file->Pixel(x, y);
                        unsigned char *dest = output->Pixel(real_x, real_y);

                        float dest_r = float(dest[0]);
                        float dest_g = float(dest[1]);
                        float dest_b = float(dest[2]);
                        float src_r = float(src[0]);
                        float src_g = float(src[1]);
                        float src_b = float(src[2]);

                        float t = params.viewports[i]->opacity;
                        float r = (1. - t) * dest_r + t * src_r;
                        float g = (1. - t) * dest_g + t * src_g;
                        float b = (1. - t) * dest_b + t * src_b;

                        *dest++ = (unsigned char)((int)r);
                        *dest++ = (unsigned char)((int)g);
                        *dest++ = (unsigned char)((int)b);
                    }
                }
            }
        }
        else if(params.viewports[i]->opaqueMode == M_COLORREPLACE)
        {
            unsigned char rr, rg, rb;
            rr = params.viewports[i]->transparentColor[0];
            rg = params.viewports[i]->transparentColor[1];
            rb = params.viewports[i]->transparentColor[2];

            for(int y = 0; y < img_h; ++y)
            {
                int real_y = start_y - img_h + y;
                for(int x = 0; x < img_w; ++x)
                {
                    int real_x = start_x + x;
                    if(real_x >= 0 && real_x < width &&
                       real_y >= 0 && real_y < height)
                    {
                        unsigned char *src = params.viewports[i]->file->Pixel(x, y);
                        unsigned char *dest = output->Pixel(real_x, real_y);

                        if(src[0] != rr || src[1] != rg || src[2] != rb)
                        {
                            *dest++ = *src++;
                            *dest++ = *src++;
                            *dest = *src;
                        }
                    }
                }
            }
        }
    }

    // Write the output image.
    output->Write(outName);

    if(startViewport == 0)
        delete output;

    return 0;
}