예제 #1
0
//--------------------------------------------------------------------------
static unsigned int HSLtoRGB(
  bool bRealRgb,
  unsigned int H, 
  unsigned int S, 
  unsigned int L) 
{
  if (S == 0)
  {
    // achromatic
    return make_rgb(bRealRgb, L, L, L);
  }

  double h = (double)H*360/255;
  double s = (double)S / 255;
  double l = (double)L / 255;
  double rm1, rm2;

  if (l <= 0.5) 
    rm2 = l + l * s;
  else 
    rm2 = l + s - l * s;
  rm1 = 2.0 * l - rm2;

  return make_rgb(bRealRgb, 
             to_rgb(rm1, rm2, h + 120.0),
             to_rgb(rm1, rm2, h),
             to_rgb(rm1, rm2, h - 120.0) );
}
예제 #2
0
float modify_alpha(read_info *input_image, int ie_bug)
{
    /* IE6 makes colors with even slightest transparency completely transparent,
       thus to improve situation in IE, make colors that are less than ~10% transparent
       completely opaque */

    rgb_pixel **input_pixels = (rgb_pixel **)input_image->row_pointers;
    rgb_pixel *pP;
    int rows= input_image->height, cols = input_image->width;
    double gamma = input_image->gamma;
    float min_opaque_val, almost_opaque_val;

    if (ie_bug) {
        min_opaque_val = 238.0/256.0; /* rest of the code uses min_opaque_val rather than checking for ie_bug */
        almost_opaque_val = min_opaque_val * 169.0/256.0;

        verbose_printf("  Working around IE6 bug by making image less transparent...\n");
    } else {
        min_opaque_val = almost_opaque_val = 1;
    }

    for(int row = 0; row < rows; ++row) {
        pP = input_pixels[row];
        for(int col = 0; col < cols; ++col, ++pP) {
            f_pixel px = to_f(gamma, *pP);

#ifndef NDEBUG
            rgb_pixel rgbcheck = to_rgb(gamma, px);


            if (pP->a && (pP->r != rgbcheck.r || pP->g != rgbcheck.g || pP->b != rgbcheck.b || pP->a != rgbcheck.a)) {
                fprintf(stderr, "Conversion error: expected %d,%d,%d,%d got %d,%d,%d,%d\n",
                        pP->r,pP->g,pP->b,pP->a, rgbcheck.r,rgbcheck.g,rgbcheck.b,rgbcheck.a);
                return -1;
            }
#endif
            /* set all completely transparent colors to black */
            if (!pP->a) {
                *pP = (rgb_pixel){0,0,0,pP->a};
            }
            /* ie bug: to avoid visible step caused by forced opaqueness, linearily raise opaqueness of almost-opaque colors */
            else if (pP->a < 255 && px.a > almost_opaque_val) {
                assert((min_opaque_val-almost_opaque_val)>0);

                float al = almost_opaque_val + (px.a-almost_opaque_val) * (1-almost_opaque_val) / (min_opaque_val-almost_opaque_val);
                if (al > 1) al = 1;
                px.a = al;
                pP->a = to_rgb(gamma, px).a;
            }
        }
    }

    return min_opaque_val;
}
예제 #3
0
void set_palette(write_info *output_image, colormap *map)
{
    for (int x = 0; x < map->colors; ++x) {
        rgb_pixel px = to_rgb(output_image->gamma, map->palette[x].acolor);
        map->palette[x].acolor = to_f(output_image->gamma, px); /* saves rounding error introduced by to_rgb, which makes remapping & dithering more accurate */

        output_image->palette[x].red   = px.r;
        output_image->palette[x].green = px.g;
        output_image->palette[x].blue  = px.b;
        output_image->trans[x]         = px.a;
    }
}
예제 #4
0
파일: work.c 프로젝트: tlvb/vitium
#include "work.h"
#include <stdio.h>

void get_time(imagedata_t *img, const char *fn, logger_t *l) { /*{{{*/
	// this is a hack that is targeted to a
	// specific small set of jpeg images,
	// not expected, or more so, expected to
	// not work with arbitrary files
	log(l, "trying to open \"%s\"\n", fn);
	FILE *fd = fopen(fn, "rb");
	assert(fd);
	char dstr[20];
	fseek(fd, 188, SEEK_SET);
	fread(dstr, sizeof(char), 19, fd);
	fclose(fd);
	dstr[19] = '\0';
	// 2013:12:27 18:20:32
	// 0123456789012345678
	img->time.tm_year = atoi(dstr)-1900;
	img->time.tm_mon = atoi(dstr+5);
	img->time.tm_mday = atoi(dstr+8);
	img->time.tm_hour = atoi(dstr+11);
	img->time.tm_min = atoi(dstr+14);
	img->time.tm_sec = atoi(dstr+17);

	img->stamp = mktime(&img->time);

	log(l, "%s -> %s -> %04d-%02d-%02d %02d:%02d:%02d -> %Ld\n", fn, dstr,
		img->time.tm_year, img->time.tm_mon, img->time.tm_mday,
		img->time.tm_hour, img->time.tm_min, img->time.tm_sec,
		img->stamp
	);
} /*}}}*/
void scalepow2(bitmap_t *out, bitmap_t *in, unsigned int spow) { /*{{{*/
	unsigned int limit = 1<<spow;
	for (size_t ty=0; ty<out->height; ++ty) {
		for (size_t tx=0; tx<out->width; ++tx) {
			size_t tp = tx + ty*out->width;
			unsigned int ys = 0;
			unsigned int cbs = 0;
			unsigned int crs = 0;
			size_t ctr = 0;
			for (size_t y=0; y<limit; ++y) {
				size_t sy = ty*limit + y;
				if (sy >= in->height) { break; }
				for (size_t x=0; x<limit; ++x) {
					size_t sx = tx*limit + x;
					if (sx >= in->width) { break; }
					size_t sp = sx + sy*in->width;
					ys += in->data[sp].x[0];
					cbs += in->data[sp].x[1];
					crs += in->data[sp].x[2];
					++ctr;
				}
			}
			ctr = ctr==0?1:ctr;
			out->data[tp].x[0] = ys/ctr;
			out->data[tp].x[1] = cbs/ctr;
			out->data[tp].x[2] = crs/ctr;
		}
	}
} /*}}}*/
void init_threaddata(threaddata_t *td, const char *ofmt, const char *ifmt, int start, int stop) { /*{{{*/
	log_init(&td->common.l, stdout);
	log(&td->common.l, "- logger created\n");

	td->common.writerstr = calloc(strlen(ofmt)+32, sizeof(char));
	assert(td->common.writerstr != NULL);
	sprintf(td->common.writerstr, "pnmtojpeg -quality=100 > %s", ofmt);
	log(&td->common.l, "- output shape is '%s'\n", td->common.writerstr);

	td->common.readerfmt = ifmt;
	td->common.readerstr = calloc(strlen(ifmt)+16, sizeof(char));
	assert(td->common.readerstr != NULL);
	sprintf(td->common.readerstr, "jpegtopnm < %s", ifmt);
	log(&td->common.l, "- input shape is '%s'\n", td->common.readerstr);

	log(&td->common.l, "- initializing counter\n");
	counter_init(&td->counter, start, stop);

	log(&td->common.l, "- initializing buffer\n");
	buffer_init(&td->buffer, BUFFERSIZE, loader, unloader);

	//font_load_gz(&td->font, "data/sun12x22.psfu");
	font_load_gz(&td->font, "/usr/share/kbd/consolefonts/sun12x22.psfu.gz");
} /*}}}*/
void destroy_threaddata(threaddata_t *td) { /*{{{*/
	buffer_destroy(&td->buffer, &td->common);
	log(&td->common.l, "- destroying counter\n");
	counter_destroy(&td->counter);
	log(&td->common.l, "- destroying logger\n");
	log_destroy(&td->common.l);
	free(td->common.writerstr);
	free(td->common.readerstr);
} /*}}}*/
void *loader(unsigned int index, void* old, void* state, int *status) { /*{{{*/
	ioglobals_t *common = (ioglobals_t*) state;
	char *command = calloc(strlen(common->readerstr)+128, sizeof(char));
	char *fn = calloc(strlen(common->readerfmt)+128, sizeof(char));
	sprintf(command, common->readerstr, index);
	sprintf(fn, common->readerfmt, index);

	imagedata_t *imd = (imagedata_t*)old;
	if (imd == NULL) {
		imd = calloc(sizeof(imagedata_t), 1);
	}
	assert(imd != NULL);

	get_time(imd, fn, &common->l);
	log(&common->l, "reading file %u (%s) with command '%s'\n", index, fn, command);
	free(fn);

	FILE *pfd = popen(command, "r");
	if (!pfd) {
		perror(NULL);
	}
	assert(pfd != NULL);
	int flag = PPM_OK;
	imd->orig = ppm_fread(imd->orig, pfd, &flag);
	pclose(pfd);
	free(command);
	assert(flag == PPM_OK);
	assert(imd->orig != NULL);
	log(&common->l, "wxh: %u x %u\n", imd->orig->width, imd->orig->height);

	unsigned int values[NSC] = {0, 3};
	unsigned int powers[NSC] = {1, 8}; // index zero never used
	for (size_t i=0; i<NSC; ++i) {
		unsigned int additive = powers[i]-1;
		imd->tfsc[i] = bitmap_new(imd->tfsc[i], (imd->orig->width+additive)/powers[i], (imd->orig->height+additive)/powers[i]);
		assert(imd->tfsc[i] != NULL);
		log(&common->l, "index %u: created image %u/%u for colour transform and dimensions %u x %u\n", index, i, NSC, imd->tfsc[i]->width, imd->tfsc[i]->height);
	}
	to_ycbcr(imd->tfsc[0]->data, imd->orig->data, imd->orig->width*imd->orig->height);
	for (size_t i=1; i<NSC; ++i) {
		scalepow2(imd->tfsc[i], imd->tfsc[0], values[i]);
	}
	return imd;
} /*}}}*/
void unloader(void *data, unsigned int index, void *state, bool kill) { /*{{{*/
	ioglobals_t *common = (ioglobals_t*) state;
	if (!kill) {
		log(&common->l, "relinquishing index %u\n", index);
	}
	else {
		imagedata_t *imd = (imagedata_t*) data;
		bitmap_free(imd->orig);
		for (size_t i=0; i<NSC; ++i) {
			bitmap_free(imd->tfsc[i]);
		}
		free(data);
	}
} /*}}}*/
void saver(unsigned int index, bitmap_t *data, ioglobals_t *common) { /*{{{*/
	char *command = calloc(strlen(common->writerstr)+128, sizeof(char));
	to_rgb(data->data, data->data, data->width*data->height);
	sprintf(command, common->writerstr, index);
	log(&common->l, "writing file %u with command '%s'\n", index, command);
	FILE *pfd = popen(command, "w");
	if (!pfd) {
		perror(NULL);
	}
	assert(pfd);
	ppm_fwrite(pfd, data);
	pclose(pfd);
	free(command);
} /*}}}*/
예제 #5
0
void magick_wrapper::xyuv_from_yuv_image_444(const xyuv::yuv_image &yuv_image_444,
                                             const xyuv::conversion_matrix &conversion_matrix) {
    // Resize underlying image to the input image.
    // Warning, this call has been slightly buggy for some resolutions.
    // It's better construct the image correctly in the first place.
    if (image.rows() != yuv_image_444.image_h || image.columns() != yuv_image_444.image_w ) {
        image.resize(Magick::Geometry(yuv_image_444.image_w, yuv_image_444.image_h));
    }

    bool has_y = !yuv_image_444.y_plane.empty();
    bool has_u = !yuv_image_444.u_plane.empty();
    bool has_v = !yuv_image_444.v_plane.empty();
    bool has_a = !yuv_image_444.a_plane.empty();
    image.matte(has_a);

    // Create pixels with default values.
    // Note that this hides the lack of planes.
    rgb_color rgb;
    yuv_color yuv;

    Magick::PixelPacket *pixels = image.setPixels(0, 0, yuv_image_444.image_w, yuv_image_444.image_h);
    XYUV_ASSERT(pixels != nullptr);


    for (uint32_t y = 0; y < yuv_image_444.image_h; y++) {
        for (uint32_t x = 0; x < yuv_image_444.image_w; x++) {
            // Convert data.
            get_yuv_color(yuv, yuv_image_444, x, y);
            to_rgb(&rgb, yuv, conversion_matrix, has_y, has_u, has_v);

            // Wrap into ImageMagick ColorRGB
            Magick::ColorRGB magick_rgb;
            magick_rgb.red(rgb.r);
            magick_rgb.green(rgb.g);
            magick_rgb.blue(rgb.b);
            // Imagemagick stores alpha as 0.0 = opaque
            if (has_a) magick_rgb.alpha(1.0-rgb.a);

            // Assign pixel.
            pixels[y * image.columns() + x] = magick_rgb;
        }
    }

    // Commit changes to image.
    image.syncPixels();
}
예제 #6
0
void sort_palette(write_info *output_image, colormap *map)
{
    assert(map); assert(output_image);

    /*
    ** Step 3.5 [GRR]: remap the palette colors so that all entries with
    ** the maximal alpha value (i.e., fully opaque) are at the end and can
    ** therefore be omitted from the tRNS chunk.
    */

    verbose_printf("  eliminating opaque tRNS-chunk entries...");

    /* move transparent colors to the beginning to shrink trns chunk */
    int num_transparent=0;
    for(int i=0; i < map->colors; i++)
    {
        rgb_pixel px = to_rgb(output_image->gamma, map->palette[i].acolor);
        if (px.a != 255) {
            if (i != num_transparent) {
                colormap_item tmp = map->palette[num_transparent];
                map->palette[num_transparent] = map->palette[i];
                map->palette[i] = tmp;
                i--;
            }
            num_transparent++;
        }
    }

    verbose_printf("%d entr%s transparent\n", num_transparent, (num_transparent == 1)? "y" : "ies");

    /* colors sorted by popularity make pngs slightly more compressible
     * opaque and transparent are sorted separately
     */
    qsort(map->palette, num_transparent, sizeof(map->palette[0]), compare_popularity);
    qsort(map->palette+num_transparent, map->colors-num_transparent, sizeof(map->palette[0]), compare_popularity);

    output_image->num_palette = map->colors;
    output_image->num_trans = num_transparent;
}
예제 #7
0
 inline ColorSpace::Converter const &ColorSpace::to_rgb(WordType w, bool source_has_alpha,
                                                        bool target_has_alpha) const
 {
   return to_rgb(w, get_alpha_type(source_has_alpha, target_has_alpha));
 }