コード例 #1
0
BlenderWorldInfo::BlenderWorldInfo(struct Scene *blenderscene, struct World *blenderworld)
{
	if (blenderworld) {
		m_hasworld = true;

		// do we have mist?
		if ((blenderworld->mode) & WO_MIST) {
			m_hasmist = true;
			m_miststart = blenderworld->miststa;
			m_mistdistance = blenderworld->mistdist;
			copy_v3_v3(m_mistcolor, &blenderworld->horr);
		}
		else {
			m_hasmist = false;
			m_miststart = 0.0;
			m_mistdistance = 0.0;
			zero_v3(m_mistcolor);
		}

		copy_v3_v3(m_backgroundcolor, &blenderworld->horr);
		copy_v3_v3(m_ambientcolor, &blenderworld->ambr);

		if (BKE_scene_check_color_management_enabled(blenderscene)) {
			linearrgb_to_srgb_v3_v3(m_mistcolor, m_mistcolor);
			linearrgb_to_srgb_v3_v3(m_backgroundcolor, m_backgroundcolor);
			linearrgb_to_srgb_v3_v3(m_ambientcolor, m_ambientcolor);
		}
	}
	else {
		m_hasworld = false;
	}
}
コード例 #2
0
ファイル: math_color_inline.c プロジェクト: akonneker/blensor
MINLINE void linearrgb_to_srgb_uchar3(unsigned char srgb[3], const float linear[3])
{
	float srgb_f[3];

	linearrgb_to_srgb_v3_v3(srgb_f, linear);
	F3TOCHAR3(srgb_f, srgb);
}
コード例 #3
0
ファイル: paint_utils.c プロジェクト: sftd/blender
void paint_get_tex_pixel_col(MTex *mtex, float u, float v, float rgba[4], struct ImagePool *pool, int thread, bool convert_to_linear, struct ColorSpace *colorspace)
{
	float co[3] = {u, v, 0.0f};
	int hasrgb;
	float intensity;

	hasrgb = externtex(mtex, co, &intensity,
	                   rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool);
	if (!hasrgb) {
		rgba[0] = intensity;
		rgba[1] = intensity;
		rgba[2] = intensity;
		rgba[3] = 1.0f;
	}

	if (convert_to_linear)
		IMB_colormanagement_colorspace_to_scene_linear_v3(rgba, colorspace);

	linearrgb_to_srgb_v3_v3(rgba, rgba);

	CLAMP(rgba[0], 0.0f, 1.0f);
	CLAMP(rgba[1], 0.0f, 1.0f);
	CLAMP(rgba[2], 0.0f, 1.0f);
	CLAMP(rgba[3], 0.0f, 1.0f);
}
コード例 #4
0
/* matching ED_space_image_color_sample() */
int ED_space_node_color_sample(SpaceNode *snode, ARegion *ar, int mval[2], float r_col[3])
{
    void *lock;
    Image *ima;
    ImBuf *ibuf;
    float fx, fy, bufx, bufy;
    int ret = FALSE;

    if (STREQ(snode->tree_idname, ntreeType_Composite->idname) || (snode->flag & SNODE_BACKDRAW) == 0) {
        /* use viewer image for color sampling only if we're in compositor tree
         * with backdrop enabled
         */
        return FALSE;
    }

    ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
    ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
    if (!ibuf) {
        return FALSE;
    }

    /* map the mouse coords to the backdrop image space */
    bufx = ibuf->x * snode->zoom;
    bufy = ibuf->y * snode->zoom;
    fx = (bufx > 0.0f ? ((float)mval[0] - 0.5f * ar->winx - snode->xof) / bufx + 0.5f : 0.0f);
    fy = (bufy > 0.0f ? ((float)mval[1] - 0.5f * ar->winy - snode->yof) / bufy + 0.5f : 0.0f);

    if (fx >= 0.0f && fy >= 0.0f && fx < 1.0f && fy < 1.0f) {
        float *fp;
        unsigned char *cp;
        int x = (int)(fx * ibuf->x), y = (int)(fy * ibuf->y);

        CLAMP(x, 0, ibuf->x - 1);
        CLAMP(y, 0, ibuf->y - 1);

        if (ibuf->rect_float) {
            fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x));
            /* IB_PROFILE_NONE is default but infact its linear */
            linearrgb_to_srgb_v3_v3(r_col, fp);
            ret = TRUE;
        }
        else if (ibuf->rect) {
            cp = (unsigned char *)(ibuf->rect + y * ibuf->x + x);
            rgb_uchar_to_float(r_col, cp);
            ret = TRUE;
        }
    }

    BKE_image_release_ibuf(ima, ibuf, lock);

    return ret;
}
コード例 #5
0
ファイル: KX_WorldInfo.cpp プロジェクト: Ichthyostega/blender
void KX_WorldInfo::setAmbientColor(float r, float g, float b)
{
	m_ambientcolor[0] = r;
	m_ambientcolor[1] = g;
	m_ambientcolor[2] = b;

	if (m_do_color_management) {
		linearrgb_to_srgb_v3_v3(m_con_ambientcolor, m_ambientcolor);
	}
	else {
		copy_v3_v3(m_con_ambientcolor, m_ambientcolor);
	}
}
コード例 #6
0
ファイル: KX_WorldInfo.cpp プロジェクト: Ichthyostega/blender
void KX_WorldInfo::setBackColor(float r, float g, float b)
{
	m_backgroundcolor[0] = r;
	m_backgroundcolor[1] = g;
	m_backgroundcolor[2] = b;

	if (m_do_color_management) {
		linearrgb_to_srgb_v3_v3(m_con_backgroundcolor, m_backgroundcolor);
	}
	else {
		copy_v3_v3(m_con_backgroundcolor, m_backgroundcolor);
	}
}
コード例 #7
0
BlenderWorldInfo::BlenderWorldInfo(struct Scene *blenderscene, struct World* blenderworld)
{
	if (blenderworld)
	{
		m_hasworld = true;

		// do we have mist?
		if ((blenderworld->mode) & WO_MIST)
		{
			m_hasmist = true;
			m_miststart = blenderworld->miststa;
			m_mistdistance = blenderworld->mistdist;
			copy_v3_v3(m_mistcolor, &blenderworld->horr);
		}
		else
		{
			m_hasmist = false;
			m_miststart = 0.0;
			m_mistdistance = 0.0;
			zero_v3(m_mistcolor);
		}

		copy_v3_v3(m_backgroundcolor, &blenderworld->horr);
		copy_v3_v3(m_ambientcolor, &blenderworld->ambr);

		/* OCIO TODO */
		if(blenderscene->r.color_mgt_flag & R_COLOR_MANAGEMENT) {
			linearrgb_to_srgb_v3_v3(m_mistcolor, m_mistcolor);
			linearrgb_to_srgb_v3_v3(m_backgroundcolor, m_backgroundcolor);
			linearrgb_to_srgb_v3_v3(m_ambientcolor, m_ambientcolor);
		}
	}
	else
	{
		m_hasworld = false;
	}
}
コード例 #8
0
ファイル: drawmesh.c プロジェクト: Moguri/blender
static DMDrawOption draw_tface__set_draw_legacy(MTexPoly *mtexpoly, const bool has_mcol, int matnr)
{
	Material *ma = give_current_material(Gtexdraw.ob, matnr + 1);
	bool invalidtexture = false;

	if (ma && (ma->game.flag & GEMAT_INVISIBLE))
		return DM_DRAW_OPTION_SKIP;

	invalidtexture = set_draw_settings_cached(0, mtexpoly, ma, Gtexdraw);

	if (mtexpoly && invalidtexture) {
		glColor3ub(0xFF, 0x00, 0xFF);
		return DM_DRAW_OPTION_NO_MCOL; /* Don't set color */
	}
	else if (!has_mcol) {
		if (mtexpoly) {
			glColor3f(1.0, 1.0, 1.0);
		}
		else {
			if (ma) {
				if (ma->shade_flag & MA_OBCOLOR) {
					glColor3ubv(Gtexdraw.obcol);
				}
				else {
					float col[3];
					if (Gtexdraw.color_profile) linearrgb_to_srgb_v3_v3(col, &ma->r);
					else copy_v3_v3(col, &ma->r);

					glColor3fv(col);
				}
			}
			else {
				glColor3f(1.0, 1.0, 1.0);
			}
		}
		return DM_DRAW_OPTION_NORMAL; /* normal drawing (no mcols anyway, no need to turn off) */
	}
	else {
		return DM_DRAW_OPTION_NORMAL; /* Set color from mcol */
	}
}
コード例 #9
0
/* matching ED_space_image_color_sample() */
bool ED_space_clip_color_sample(SpaceClip *sc, ARegion *ar, int mval[2], float r_col[3])
{
	ImBuf *ibuf;
	float fx, fy, co[2];
	bool ret = false;

	ibuf = ED_space_clip_get_buffer(sc);
	if (!ibuf) {
		return false;
	}

	/* map the mouse coords to the backdrop image space */
	ED_clip_mouse_pos(sc, ar, mval, co);

	fx = co[0];
	fy = co[1];

	if (fx >= 0.0f && fy >= 0.0f && fx < 1.0f && fy < 1.0f) {
		float *fp;
		unsigned char *cp;
		int x = (int)(fx * ibuf->x), y = (int)(fy * ibuf->y);

		CLAMP(x, 0, ibuf->x - 1);
		CLAMP(y, 0, ibuf->y - 1);

		if (ibuf->rect_float) {
			fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x));
			linearrgb_to_srgb_v3_v3(r_col, fp);
			ret = true;
		}
		else if (ibuf->rect) {
			cp = (unsigned char *)(ibuf->rect + y * ibuf->x + x);
			rgb_uchar_to_float(r_col, cp);
			ret = true;
		}
	}

	return ret;
}
コード例 #10
0
ファイル: math_color_inline.c プロジェクト: akonneker/blensor
MINLINE void linearrgb_to_srgb_v4(float srgb[4], const float linear[4])
{
	linearrgb_to_srgb_v3_v3(srgb, linear);
	srgb[3] = linear[3];
}
コード例 #11
0
ファイル: divers.c プロジェクト: dfelinto/blender
/* float to byte pixels, output 4-channel RGBA */
void IMB_buffer_byte_from_float(uchar *rect_to,
                                const float *rect_from,
                                int channels_from,
                                float dither,
                                int profile_to,
                                int profile_from,
                                bool predivide,
                                int width,
                                int height,
                                int stride_to,
                                int stride_from)
{
  float tmp[4];
  int x, y;
  DitherContext *di = NULL;
  float inv_width = 1.0f / width;
  float inv_height = 1.0f / height;

  /* we need valid profiles */
  BLI_assert(profile_to != IB_PROFILE_NONE);
  BLI_assert(profile_from != IB_PROFILE_NONE);

  if (dither) {
    di = create_dither_context(dither);
  }

  for (y = 0; y < height; y++) {
    float t = y * inv_height;

    if (channels_from == 1) {
      /* single channel input */
      const float *from = rect_from + ((size_t)stride_from) * y;
      uchar *to = rect_to + ((size_t)stride_to) * y * 4;

      for (x = 0; x < width; x++, from++, to += 4) {
        to[0] = to[1] = to[2] = to[3] = unit_float_to_uchar_clamp(from[0]);
      }
    }
    else if (channels_from == 3) {
      /* RGB input */
      const float *from = rect_from + ((size_t)stride_from) * y * 3;
      uchar *to = rect_to + ((size_t)stride_to) * y * 4;

      if (profile_to == profile_from) {
        /* no color space conversion */
        for (x = 0; x < width; x++, from += 3, to += 4) {
          rgb_float_to_uchar(to, from);
          to[3] = 255;
        }
      }
      else if (profile_to == IB_PROFILE_SRGB) {
        /* convert from linear to sRGB */
        for (x = 0; x < width; x++, from += 3, to += 4) {
          linearrgb_to_srgb_v3_v3(tmp, from);
          rgb_float_to_uchar(to, tmp);
          to[3] = 255;
        }
      }
      else if (profile_to == IB_PROFILE_LINEAR_RGB) {
        /* convert from sRGB to linear */
        for (x = 0; x < width; x++, from += 3, to += 4) {
          srgb_to_linearrgb_v3_v3(tmp, from);
          rgb_float_to_uchar(to, tmp);
          to[3] = 255;
        }
      }
    }
    else if (channels_from == 4) {
      /* RGBA input */
      const float *from = rect_from + ((size_t)stride_from) * y * 4;
      uchar *to = rect_to + ((size_t)stride_to) * y * 4;

      if (profile_to == profile_from) {
        float straight[4];

        /* no color space conversion */
        if (dither && predivide) {
          for (x = 0; x < width; x++, from += 4, to += 4) {
            premul_to_straight_v4_v4(straight, from);
            float_to_byte_dither_v4(to, straight, di, (float)x * inv_width, t);
          }
        }
        else if (dither) {
          for (x = 0; x < width; x++, from += 4, to += 4) {
            float_to_byte_dither_v4(to, from, di, (float)x * inv_width, t);
          }
        }
        else if (predivide) {
          for (x = 0; x < width; x++, from += 4, to += 4) {
            premul_to_straight_v4_v4(straight, from);
            rgba_float_to_uchar(to, straight);
          }
        }
        else {
          for (x = 0; x < width; x++, from += 4, to += 4) {
            rgba_float_to_uchar(to, from);
          }
        }
      }
      else if (profile_to == IB_PROFILE_SRGB) {
        /* convert from linear to sRGB */
        unsigned short us[4];
        float straight[4];

        if (dither && predivide) {
          for (x = 0; x < width; x++, from += 4, to += 4) {
            premul_to_straight_v4_v4(straight, from);
            linearrgb_to_srgb_ushort4(us, from);
            ushort_to_byte_dither_v4(to, us, di, (float)x * inv_width, t);
          }
        }
        else if (dither) {
          for (x = 0; x < width; x++, from += 4, to += 4) {
            linearrgb_to_srgb_ushort4(us, from);
            ushort_to_byte_dither_v4(to, us, di, (float)x * inv_width, t);
          }
        }
        else if (predivide) {
          for (x = 0; x < width; x++, from += 4, to += 4) {
            premul_to_straight_v4_v4(straight, from);
            linearrgb_to_srgb_ushort4(us, from);
            ushort_to_byte_v4(to, us);
          }
        }
        else {
          for (x = 0; x < width; x++, from += 4, to += 4) {
            linearrgb_to_srgb_ushort4(us, from);
            ushort_to_byte_v4(to, us);
          }
        }
      }
      else if (profile_to == IB_PROFILE_LINEAR_RGB) {
        /* convert from sRGB to linear */
        if (dither && predivide) {
          for (x = 0; x < width; x++, from += 4, to += 4) {
            srgb_to_linearrgb_predivide_v4(tmp, from);
            float_to_byte_dither_v4(to, tmp, di, (float)x * inv_width, t);
          }
        }
        else if (dither) {
          for (x = 0; x < width; x++, from += 4, to += 4) {
            srgb_to_linearrgb_v4(tmp, from);
            float_to_byte_dither_v4(to, tmp, di, (float)x * inv_width, t);
          }
        }
        else if (predivide) {
          for (x = 0; x < width; x++, from += 4, to += 4) {
            srgb_to_linearrgb_predivide_v4(tmp, from);
            rgba_float_to_uchar(to, tmp);
          }
        }
        else {
          for (x = 0; x < width; x++, from += 4, to += 4) {
            srgb_to_linearrgb_v4(tmp, from);
            rgba_float_to_uchar(to, tmp);
          }
        }
      }
    }
  }

  if (dither) {
    clear_dither_context(di);
  }
}
コード例 #12
0
ファイル: divers.c プロジェクト: dfelinto/blender
/* float to float pixels, output 4-channel RGBA */
void IMB_buffer_float_from_float(float *rect_to,
                                 const float *rect_from,
                                 int channels_from,
                                 int profile_to,
                                 int profile_from,
                                 bool predivide,
                                 int width,
                                 int height,
                                 int stride_to,
                                 int stride_from)
{
  int x, y;

  /* we need valid profiles */
  BLI_assert(profile_to != IB_PROFILE_NONE);
  BLI_assert(profile_from != IB_PROFILE_NONE);

  if (channels_from == 1) {
    /* single channel input */
    for (y = 0; y < height; y++) {
      const float *from = rect_from + ((size_t)stride_from) * y;
      float *to = rect_to + ((size_t)stride_to) * y * 4;

      for (x = 0; x < width; x++, from++, to += 4) {
        to[0] = to[1] = to[2] = to[3] = from[0];
      }
    }
  }
  else if (channels_from == 3) {
    /* RGB input */
    for (y = 0; y < height; y++) {
      const float *from = rect_from + ((size_t)stride_from) * y * 3;
      float *to = rect_to + ((size_t)stride_to) * y * 4;

      if (profile_to == profile_from) {
        /* no color space conversion */
        for (x = 0; x < width; x++, from += 3, to += 4) {
          copy_v3_v3(to, from);
          to[3] = 1.0f;
        }
      }
      else if (profile_to == IB_PROFILE_LINEAR_RGB) {
        /* convert from sRGB to linear */
        for (x = 0; x < width; x++, from += 3, to += 4) {
          srgb_to_linearrgb_v3_v3(to, from);
          to[3] = 1.0f;
        }
      }
      else if (profile_to == IB_PROFILE_SRGB) {
        /* convert from linear to sRGB */
        for (x = 0; x < width; x++, from += 3, to += 4) {
          linearrgb_to_srgb_v3_v3(to, from);
          to[3] = 1.0f;
        }
      }
    }
  }
  else if (channels_from == 4) {
    /* RGBA input */
    for (y = 0; y < height; y++) {
      const float *from = rect_from + ((size_t)stride_from) * y * 4;
      float *to = rect_to + ((size_t)stride_to) * y * 4;

      if (profile_to == profile_from) {
        /* same profile, copy */
        memcpy(to, from, sizeof(float) * ((size_t)4) * width);
      }
      else if (profile_to == IB_PROFILE_LINEAR_RGB) {
        /* convert to sRGB to linear */
        if (predivide) {
          for (x = 0; x < width; x++, from += 4, to += 4) {
            srgb_to_linearrgb_predivide_v4(to, from);
          }
        }
        else {
          for (x = 0; x < width; x++, from += 4, to += 4) {
            srgb_to_linearrgb_v4(to, from);
          }
        }
      }
      else if (profile_to == IB_PROFILE_SRGB) {
        /* convert from linear to sRGB */
        if (predivide) {
          for (x = 0; x < width; x++, from += 4, to += 4) {
            linearrgb_to_srgb_predivide_v4(to, from);
          }
        }
        else {
          for (x = 0; x < width; x++, from += 4, to += 4) {
            linearrgb_to_srgb_v4(to, from);
          }
        }
      }
    }
  }
}
コード例 #13
0
ファイル: tiff.c プロジェクト: JasonWilkins/blender-wayland
int imb_savetiff(ImBuf *ibuf, const char *name, int flags)
{
	TIFF *image = NULL;
	uint16 samplesperpixel, bitspersample;
	size_t npixels;
	unsigned char *pixels = NULL;
	unsigned char *from = NULL, *to = NULL;
	unsigned short *pixels16 = NULL, *to16 = NULL;
	float *fromf = NULL;
	float xres, yres;
	int x, y, from_i, to_i, i;

	/* check for a valid number of bytes per pixel.  Like the PNG writer,
	 * the TIFF writer supports 1, 3 or 4 bytes per pixel, corresponding
	 * to gray, RGB, RGBA respectively. */
	samplesperpixel = (uint16)((ibuf->planes + 7) >> 3);
	if ((samplesperpixel > 4) || (samplesperpixel == 2)) {
		fprintf(stderr,
		        "imb_savetiff: unsupported number of bytes per "
		        "pixel: %d\n", samplesperpixel);
		return (0);
	}

	if ((ibuf->ftype & TIF_16BIT) && ibuf->rect_float)
		bitspersample = 16;
	else
		bitspersample = 8;

	/* open TIFF file for writing */
	if (flags & IB_mem) {
		/* bork at the creation of a TIFF in memory */
		fprintf(stderr,
		        "imb_savetiff: creation of in-memory TIFF files is "
		        "not yet supported.\n");
		return (0);
	}
	else {
		/* create image as a file */
#ifdef WIN32
		wchar_t *wname = alloc_utf16_from_8(name, 0);
		image = TIFFOpenW(wname, "w");
		free(wname);
#else
		image = TIFFOpen(name, "w");
#endif
	}
	if (image == NULL) {
		fprintf(stderr,
		        "imb_savetiff: could not open TIFF for writing.\n");
		return (0);
	}

	/* allocate array for pixel data */
	npixels = ibuf->x * ibuf->y;
	if (bitspersample == 16)
		pixels16 = (unsigned short *)_TIFFmalloc(npixels *
		                                         samplesperpixel * sizeof(unsigned short));
	else
		pixels = (unsigned char *)_TIFFmalloc(npixels *
		                                      samplesperpixel * sizeof(unsigned char));

	if (pixels == NULL && pixels16 == NULL) {
		fprintf(stderr,
		        "imb_savetiff: could not allocate pixels array.\n");
		TIFFClose(image);
		return (0);
	}

	/* setup pointers */
	if (bitspersample == 16) {
		fromf = ibuf->rect_float;
		to16   = pixels16;
	}
	else {
		from = (unsigned char *)ibuf->rect;
		to   = pixels;
	}

	/* setup samples per pixel */
	TIFFSetField(image, TIFFTAG_BITSPERSAMPLE, bitspersample);
	TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);

	if (samplesperpixel == 4) {
		unsigned short extraSampleTypes[1];

		if (bitspersample == 16)
			extraSampleTypes[0] = EXTRASAMPLE_ASSOCALPHA;
		else
			extraSampleTypes[0] = EXTRASAMPLE_UNASSALPHA;

		/* RGBA images */
		TIFFSetField(image, TIFFTAG_EXTRASAMPLES, 1,
		             extraSampleTypes);
		TIFFSetField(image, TIFFTAG_PHOTOMETRIC, 
		             PHOTOMETRIC_RGB);
	}
	else if (samplesperpixel == 3) {
		/* RGB images */
		TIFFSetField(image, TIFFTAG_PHOTOMETRIC,
		             PHOTOMETRIC_RGB);
	}
	else if (samplesperpixel == 1) {
		/* grayscale images, 1 channel */
		TIFFSetField(image, TIFFTAG_PHOTOMETRIC,
		             PHOTOMETRIC_MINISBLACK);
	}

	/* copy pixel data.  While copying, we flip the image vertically. */
	for (x = 0; x < ibuf->x; x++) {
		for (y = 0; y < ibuf->y; y++) {
			from_i = 4 * (y * ibuf->x + x);
			to_i   = samplesperpixel * ((ibuf->y - y - 1) * ibuf->x + x);

			if (pixels16) {
				/* convert from float source */
				float rgb[4];
				
				if (ibuf->float_colorspace) {
					/* float buffer was managed already, no need in color space conversion */
					copy_v3_v3(rgb, &fromf[from_i]);
				}
				else {
					/* standard linear-to-srgb conversion if float buffer wasn't managed */
					linearrgb_to_srgb_v3_v3(rgb, &fromf[from_i]);
				}

				rgb[3] = fromf[from_i + 3];

				for (i = 0; i < samplesperpixel; i++, to_i++)
					to16[to_i] = FTOUSHORT(rgb[i]);
			}
			else {
				for (i = 0; i < samplesperpixel; i++, to_i++, from_i++)
					to[to_i] = from[from_i];
			}
		}
	}

	/* write the actual TIFF file */
	TIFFSetField(image, TIFFTAG_IMAGEWIDTH,      ibuf->x);
	TIFFSetField(image, TIFFTAG_IMAGELENGTH,     ibuf->y);
	TIFFSetField(image, TIFFTAG_ROWSPERSTRIP,    ibuf->y);
	TIFFSetField(image, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE);
	TIFFSetField(image, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
	TIFFSetField(image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);


	if (ibuf->ppm[0] > 0.0 && ibuf->ppm[1] > 0.0) {
		xres = (float)(ibuf->ppm[0] * 0.0254);
		yres = (float)(ibuf->ppm[1] * 0.0254);
	}
	else {
		xres = yres = IMB_DPI_DEFAULT;
	}

	TIFFSetField(image, TIFFTAG_XRESOLUTION,     xres);
	TIFFSetField(image, TIFFTAG_YRESOLUTION,     yres);
	TIFFSetField(image, TIFFTAG_RESOLUTIONUNIT,  RESUNIT_INCH);
	if (TIFFWriteEncodedStrip(image, 0,
	                          (bitspersample == 16) ? (unsigned char *)pixels16 : pixels,
	                          ibuf->x * ibuf->y * samplesperpixel * bitspersample / 8) == -1)
	{
		fprintf(stderr,
		        "imb_savetiff: Could not write encoded TIFF.\n");
		TIFFClose(image);
		if (pixels) _TIFFfree(pixels);
		if (pixels16) _TIFFfree(pixels16);
		return (1);
	}

	/* close the TIFF file */
	TIFFClose(image);
	if (pixels) _TIFFfree(pixels);
	if (pixels16) _TIFFfree(pixels16);
	return (1);
}
コード例 #14
0
static void fill_bins(bNode* node, CompBuf* in, int* bins, int colorcor)
{
	float value[4];
	int ivalue=0;
	int x,y;

	/*fill bins */
	for(y=0; y<in->y; y++) {
		for(x=0; x<in->x; x++) {

			/* get the pixel */
			qd_getPixel(in, x, y, value);

			if(value[3] > 0.0) { /* don't count transparent pixels */
				switch(node->custom1) {
					case 1: { /* all colors */
						if(colorcor)
							linearrgb_to_srgb_v3_v3(&value[0],&value[0]);
						rgb_tobw(value[0],value[1],value[2], &value[0]);
						value[0]=value[0]*255; /* scale to 0-255 range */
						ivalue=(int)value[0];
						break;
					}
					case 2: { /* red channel */
						if(colorcor)
							value[0]=linearrgb_to_srgb(value[0]);
						value[0]=value[0]*255; /* scale to 0-255 range */
						ivalue=(int)value[0];
						break;
					}
					case 3:  { /* green channel */
						if(colorcor)
							value[1]=linearrgb_to_srgb(value[1]);
						value[1]=value[1]*255; /* scale to 0-255 range */
						ivalue=(int)value[1];
						break;
					}
					case 4: /*blue channel */
					{
						if(colorcor)
							value[2]=linearrgb_to_srgb(value[2]);
						value[2]=value[2]*255; /* scale to 0-255 range */
						ivalue=(int)value[2];
						break;
					}
					case 5: /* luminence */
					{
						if(colorcor)
							linearrgb_to_srgb_v3_v3(&value[0],&value[0]);
						rgb_to_yuv(value[0],value[1],value[2], &value[0], &value[1], &value[2]);
						value[0]=value[0]*255; /* scale to 0-255 range */
						ivalue=(int)value[0];
						break;
					}
				} /*end switch */

				/*clip*/
				if(ivalue<0) ivalue=0;
				if(ivalue>255) ivalue=255;

				/*put in the correct bin*/
				bins[ivalue]+=1;
			} /*end if alpha */
		}
	}	
}
コード例 #15
0
static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(quad), int x, int y, float UNUSED(u), float UNUSED(v), float *tvn, float *ttang)
{
	BakeShade *bs = handle;
	ShadeSample *ssamp = &bs->ssamp;
	ShadeResult shr;
	VlakRen *vlr = shi->vlr;

	shade_input_init_material(shi);

	if (bs->type == RE_BAKE_AO) {
		ambient_occlusion(shi);

		if (R.r.bake_flag & R_BAKE_NORMALIZE) {
			copy_v3_v3(shr.combined, shi->ao);
		}
		else {
			zero_v3(shr.combined);
			environment_lighting_apply(shi, &shr);
		}
	}
	else {
		if (bs->type == RE_BAKE_SHADOW) /* Why do shadows set the color anyhow?, ignore material color for baking */
			shi->r = shi->g = shi->b = 1.0f;

		shade_input_set_shade_texco(shi);
		
		/* only do AO for a full bake (and obviously AO bakes)
		 * AO for light bakes is a leftover and might not be needed */
		if (ELEM3(bs->type, RE_BAKE_ALL, RE_BAKE_AO, RE_BAKE_LIGHT))
			shade_samples_do_AO(ssamp);
		
		if (shi->mat->nodetree && shi->mat->use_nodes) {
			ntreeShaderExecTree(shi->mat->nodetree, shi, &shr);
			shi->mat = vlr->mat;  /* shi->mat is being set in nodetree */
		}
		else
			shade_material_loop(shi, &shr);

		if (bs->type == RE_BAKE_NORMALS) {
			float nor[3];

			copy_v3_v3(nor, shi->vn);

			if (R.r.bake_normal_space == R_BAKE_SPACE_CAMERA) {
				/* pass */
			}
			else if (R.r.bake_normal_space == R_BAKE_SPACE_TANGENT) {
				float mat[3][3], imat[3][3];

				/* bitangent */
				if (tvn && ttang) {
					copy_v3_v3(mat[0], ttang);
					cross_v3_v3v3(mat[1], tvn, ttang);
					mul_v3_fl(mat[1], ttang[3]);
					copy_v3_v3(mat[2], tvn);
				}
				else {
					copy_v3_v3(mat[0], shi->nmaptang);
					cross_v3_v3v3(mat[1], shi->nmapnorm, shi->nmaptang);
					mul_v3_fl(mat[1], shi->nmaptang[3]);
					copy_v3_v3(mat[2], shi->nmapnorm);
				}

				invert_m3_m3(imat, mat);
				mul_m3_v3(imat, nor);
			}
			else if (R.r.bake_normal_space == R_BAKE_SPACE_OBJECT)
				mul_mat3_m4_v3(ob->imat_ren, nor);  /* ob->imat_ren includes viewinv! */
			else if (R.r.bake_normal_space == R_BAKE_SPACE_WORLD)
				mul_mat3_m4_v3(R.viewinv, nor);

			normalize_v3(nor); /* in case object has scaling */

			/* The invert of the red channel is to make
			 * the normal map compliant with the outside world.
			 * It needs to be done because in Blender
			 * the normal used in the renderer points inward. It is generated
			 * this way in calc_vertexnormals(). Should this ever change
			 * this negate must be removed. */
			shr.combined[0] = (-nor[0]) / 2.0f + 0.5f;
			shr.combined[1] = nor[1]    / 2.0f + 0.5f;
			shr.combined[2] = nor[2]    / 2.0f + 0.5f;
		}
		else if (bs->type == RE_BAKE_TEXTURE) {
			copy_v3_v3(shr.combined, &shi->r);
			shr.alpha = shi->alpha;
		}
		else if (bs->type == RE_BAKE_SHADOW) {
			copy_v3_v3(shr.combined, shr.shad);
			shr.alpha = shi->alpha;
		}
		else if (bs->type == RE_BAKE_SPEC_COLOR) {
			copy_v3_v3(shr.combined, &shi->specr);
			shr.alpha = 1.0f;
		}
		else if (bs->type == RE_BAKE_SPEC_INTENSITY) {
			copy_v3_fl(shr.combined, shi->spec);
			shr.alpha = 1.0f;
		}
		else if (bs->type == RE_BAKE_MIRROR_COLOR) {
			copy_v3_v3(shr.combined, &shi->mirr);
			shr.alpha = 1.0f;
		}
		else if (bs->type == RE_BAKE_MIRROR_INTENSITY) {
			copy_v3_fl(shr.combined, shi->ray_mirror);
			shr.alpha = 1.0f;
		}
		else if (bs->type == RE_BAKE_ALPHA) {
			copy_v3_fl(shr.combined, shi->alpha);
			shr.alpha = 1.0f;
		}
		else if (bs->type == RE_BAKE_EMIT) {
			copy_v3_fl(shr.combined, shi->emit);
			shr.alpha = 1.0f;
		}
		else if (bs->type == RE_BAKE_VERTEX_COLORS) {
			copy_v3_v3(shr.combined, shi->vcol);
			shr.alpha = shi->vcol[3];
		}
	}
	
	if (bs->rect_float && !bs->vcol) {
		float *col = bs->rect_float + 4 * (bs->rectx * y + x);
		copy_v3_v3(col, shr.combined);
		if (bs->type == RE_BAKE_ALL || bs->type == RE_BAKE_TEXTURE || bs->type == RE_BAKE_VERTEX_COLORS) {
			col[3] = shr.alpha;
		}
		else {
			col[3] = 1.0;
		}
	}
	else {
		/* Target is char (LDR). */
		unsigned char col[4];

		if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE)) {
			float rgb[3];

			copy_v3_v3(rgb, shr.combined);
			if (R.scene_color_manage) {
				/* Vertex colors have no way to specify color space, so they
				 * default to sRGB. */
				if (!bs->vcol)
					IMB_colormanagement_scene_linear_to_colorspace_v3(rgb, bs->rect_colorspace);
				else
					linearrgb_to_srgb_v3_v3(rgb, rgb);
			}
			rgb_float_to_uchar(col, rgb);
		}
		else {
			rgb_float_to_uchar(col, shr.combined);
		}
		
		if (ELEM3(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE, RE_BAKE_VERTEX_COLORS)) {
			col[3] = FTOCHAR(shr.alpha);
		}
		else {
			col[3] = 255;
		}

		if (bs->vcol) {
			/* Vertex color baking. Vcol has no useful alpha channel (it exists
			 * but is used only for vertex painting). */
			bs->vcol->r = col[0];
			bs->vcol->g = col[1];
			bs->vcol->b = col[2];
		}
		else {
			unsigned char *imcol = (unsigned char *)(bs->rect + bs->rectx * y + x);
			copy_v4_v4_char((char *)imcol, (char *)col);
		}

	}
	
	if (bs->rect_mask) {
		bs->rect_mask[bs->rectx * y + x] = FILTER_MASK_USED;
	}

	if (bs->do_update) {
		*bs->do_update = true;
	}
}
コード例 #16
0
/* update rectangular section of the brush image */
static void brush_painter_imbuf_update(BrushPainter *painter, ImBuf *oldtexibuf,
                                       int origx, int origy, int w, int h, int xt, int yt)
{
    Scene *scene = painter->scene;
    Brush *brush = painter->brush;

    rctf tex_mapping = painter->tex_mapping;
    rctf mask_mapping = painter->mask_mapping;
    struct ImagePool *pool = painter->pool;

    bool use_masking = painter->cache.use_masking;
    bool use_color_correction = painter->cache.use_color_correction;
    bool use_float = painter->cache.use_float;
    bool is_texbrush = painter->cache.is_texbrush;
    bool is_maskbrush = painter->cache.is_maskbrush;
    bool use_texture_old = (oldtexibuf != NULL);

    int x, y, thread = 0;
    float brush_rgb[3];

    ImBuf *ibuf = painter->cache.ibuf;
    ImBuf *texibuf = painter->cache.texibuf;
    unsigned short *mask = painter->cache.mask;

    /* get brush color */
    if (brush->imagepaint_tool == PAINT_TOOL_DRAW) {
        copy_v3_v3(brush_rgb, brush->rgb);

        if (use_color_correction)
            srgb_to_linearrgb_v3_v3(brush_rgb, brush_rgb);
    }
    else {
        brush_rgb[0] = 1.0f;
        brush_rgb[1] = 1.0f;
        brush_rgb[2] = 1.0f;
    }

    /* fill pixes */
    for (y = origy; y < h; y++) {
        for (x = origx; x < w; x++) {
            /* sample texture and multiply with brush color */
            float texco[3], rgba[4];

            if (!use_texture_old) {
                if (is_texbrush) {
                    brush_imbuf_tex_co(&tex_mapping, x, y, texco);
                    BKE_brush_sample_tex_3D(scene, brush, texco, rgba, thread, pool);
                    /* TODO(sergey): Support texture paint color space. */
                    if (!use_float) {
                        linearrgb_to_srgb_v3_v3(rgba, rgba);
                    }
                    mul_v3_v3(rgba, brush_rgb);
                }
                else {
                    copy_v3_v3(rgba, brush_rgb);
                    rgba[3] = 1.0f;
                }

                if (is_maskbrush) {
                    brush_imbuf_tex_co(&mask_mapping, x, y, texco);
                    rgba[3] *= BKE_brush_sample_masktex(scene, brush, texco, thread, pool);
                }
            }

            if (use_float) {
                /* handle float pixel */
                float *bf = ibuf->rect_float + (y * ibuf->x + x) * 4;
                float *tf = texibuf->rect_float + (y * texibuf->x + x) * 4;

                /* read from old texture buffer */
                if (use_texture_old) {
                    float *otf = oldtexibuf->rect_float + ((y - origy + yt) * oldtexibuf->x + (x - origx + xt)) * 4;
                    copy_v4_v4(rgba, otf);
                }

                /* write to new texture buffer */
                copy_v4_v4(tf, rgba);

                /* if not using masking, multiply in the mask now */
                if (!use_masking) {
                    unsigned short *m = mask + (y * ibuf->x + x);
                    rgba[3] *= *m * (1.0f / 65535.0f);
                }

                /* output premultiplied float image, mf was already premultiplied */
                mul_v3_v3fl(bf, rgba, rgba[3]);
                bf[3] = rgba[3];
            }
            else {
                unsigned char crgba[4];

                /* handle byte pixel */
                unsigned char *b = (unsigned char *)ibuf->rect + (y * ibuf->x + x) * 4;
                unsigned char *t = (unsigned char *)texibuf->rect + (y * texibuf->x + x) * 4;

                /* read from old texture buffer */
                if (use_texture_old) {
                    unsigned char *ot = (unsigned char *)oldtexibuf->rect + ((y - origy + yt) * oldtexibuf->x + (x - origx + xt)) * 4;
                    crgba[0] = ot[0];
                    crgba[1] = ot[1];
                    crgba[2] = ot[2];
                    crgba[3] = ot[3];
                }
                else
                    rgba_float_to_uchar(crgba, rgba);

                /* write to new texture buffer */
                t[0] = crgba[0];
                t[1] = crgba[1];
                t[2] = crgba[2];
                t[3] = crgba[3];

                /* if not using masking, multiply in the mask now */
                if (!use_masking) {
                    unsigned short *m = mask + (y * ibuf->x + x);
                    crgba[3] = (crgba[3] * (*m)) / 65535;
                }

                /* write to brush image buffer */
                b[0] = crgba[0];
                b[1] = crgba[1];
                b[2] = crgba[2];
                b[3] = crgba[3];
            }
        }
    }
}
コード例 #17
0
ファイル: divers.c プロジェクト: BHCLL/blendocv
/* converts from linear float to sRGB byte for part of the texture, buffer will hold the changed part */
void IMB_partial_rect_from_float(struct ImBuf *ibuf,float *buffer, int x, int y, int w, int h)
{
	/* indices to source and destination image pixels */
	float *srcFloatPxl;
	unsigned char *dstBytePxl;
	/* buffer index will fill buffer */
	float *bufferIndex;

	/* convenience pointers to start of image buffers */
	float *init_srcFloatPxl = (float *)ibuf->rect_float;
	unsigned char *init_dstBytePxl = (unsigned char *) ibuf->rect;

	/* Dithering factor */
	float dither= ibuf->dither / 255.0f;
	/* respective attributes of image */
	short profile= ibuf->profile;
	int channels= ibuf->channels;
	
	int i, j;
	
	/*
		if called -only- from GPU_paint_update_image this test will never fail
		but leaving it here for better or worse
	*/
	if(init_srcFloatPxl==NULL || (buffer == NULL)){
		return;
	}
	if(init_dstBytePxl==NULL) {
		imb_addrectImBuf(ibuf);
		init_dstBytePxl = (unsigned char *) ibuf->rect;
	}
	if(channels==1) {
			for (j = 0; j < h; j++){
				bufferIndex = buffer + w*j*4;
				dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4;
				srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x);
				for(i = 0;  i < w; i++, dstBytePxl+=4, srcFloatPxl++, bufferIndex+=4) {
					dstBytePxl[1]= dstBytePxl[2]= dstBytePxl[3]= dstBytePxl[0] = FTOCHAR(srcFloatPxl[0]);
					bufferIndex[0] = bufferIndex[1] = bufferIndex[2] = bufferIndex[3] = srcFloatPxl[0];
				}
			}
	}
	else if (profile == IB_PROFILE_LINEAR_RGB) {
		if(channels == 3) {
			for (j = 0; j < h; j++){
				bufferIndex = buffer + w*j*4;
				dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4;
				srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*3;
				for(i = 0;  i < w; i++, dstBytePxl+=4, srcFloatPxl+=3, bufferIndex += 4) {
					linearrgb_to_srgb_v3_v3(bufferIndex, srcFloatPxl);
					F3TOCHAR4(bufferIndex, dstBytePxl);
					bufferIndex[3]= 1.0;
				}
			}
		}
		else if (channels == 4) {
			if (dither != 0.f) {
				for (j = 0; j < h; j++){
					bufferIndex = buffer + w*j*4;
					dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4;
					srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*4;
					for(i = 0;  i < w; i++, dstBytePxl+=4, srcFloatPxl+=4, bufferIndex+=4) {
						const float d = (BLI_frand()-0.5f)*dither;
						linearrgb_to_srgb_v3_v3(bufferIndex, srcFloatPxl);
						bufferIndex[3] = srcFloatPxl[3];
						add_v4_fl(bufferIndex, d);
						F4TOCHAR4(bufferIndex, dstBytePxl);
					}
				}
			} else {
				for (j = 0; j < h; j++){
					bufferIndex = buffer + w*j*4;
					dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4;
					srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*4;
					for(i = 0;  i < w; i++, dstBytePxl+=4, srcFloatPxl+=4, bufferIndex+=4) {
						linearrgb_to_srgb_v3_v3(bufferIndex, srcFloatPxl);
						bufferIndex[3]= srcFloatPxl[3];
						F4TOCHAR4(bufferIndex, dstBytePxl);
					}
				}
			}
		}
	}
	else if(ELEM(profile, IB_PROFILE_NONE, IB_PROFILE_SRGB)) {
		if(channels==3) {
			for (j = 0; j < h; j++){
				bufferIndex = buffer + w*j*4;
				dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4;
				srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*3;
				for(i = 0;  i < w; i++, dstBytePxl+=4, srcFloatPxl+=3, bufferIndex+=4) {
					copy_v3_v3(bufferIndex, srcFloatPxl);
					F3TOCHAR4(bufferIndex, dstBytePxl);
					bufferIndex[3] = 1.0;
				}
			}
		}
		else {
			if (dither != 0.f) {
				for (j = 0; j < h; j++){
					bufferIndex = buffer + w*j*4;
					dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4;
					srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*4;
					for(i = 0;  i < w; i++, dstBytePxl+=4, srcFloatPxl+=4, bufferIndex+=4) {
						const float d = (BLI_frand()-0.5f)*dither;
						copy_v4_v4(bufferIndex, srcFloatPxl);
						add_v4_fl(bufferIndex,d);
						F4TOCHAR4(bufferIndex, dstBytePxl);
					}
				}
			} else {
				for (j = 0; j < h; j++){
					bufferIndex = buffer + w*j*4;
					dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4;
					srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*4;
					for(i = 0;  i < w; i++, dstBytePxl+=4, srcFloatPxl+=4, bufferIndex+=4) {
						copy_v4_v4(bufferIndex, srcFloatPxl);
						F4TOCHAR4(bufferIndex, dstBytePxl);
					}
				}
			}
		}
	}
	/* ensure user flag is reset */
	ibuf->userflags &= ~IB_RECT_INVALID;
}
コード例 #18
0
ファイル: paint_utils.c プロジェクト: sftd/blender
/* used for both 3d view and image window */
void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_proj, bool use_palette)
{
	Scene *scene = CTX_data_scene(C);
	Paint *paint = BKE_paint_get_active_from_context(C);
	Palette *palette = BKE_paint_palette(paint);
	PaletteColor *color;
	Brush *br = BKE_paint_brush(BKE_paint_get_active_from_context(C));
	unsigned int col;
	const unsigned char *cp;

	CLAMP(x, 0, ar->winx);
	CLAMP(y, 0, ar->winy);
	
	if (use_palette) {
		if (!palette) {
			palette = BKE_palette_add(CTX_data_main(C), "Palette");
			BKE_paint_palette_set(paint, palette);
		}

		color = BKE_palette_color_add(palette);
	}


	if (CTX_wm_view3d(C) && texpaint_proj) {
		/* first try getting a colour directly from the mesh faces if possible */
		Object *ob = OBACT;
		bool sample_success = false;

		if (ob) {
			DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);

			ViewContext vc;
			const int mval[2] = {x, y};
			unsigned int faceindex;
			unsigned int totface = dm->getNumTessFaces(dm);
			MTFace *dm_mtface = dm->getTessFaceDataArray(dm, CD_MTFACE);

			DM_update_materials(dm, ob);

			if (dm_mtface) {
				view3d_set_viewcontext(C, &vc);

				view3d_operator_needs_opengl(C);

				if (imapaint_pick_face(&vc, mval, &faceindex, totface)) {
					Image *image = imapaint_face_image(dm, faceindex);

					ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL);
					if (ibuf && ibuf->rect) {
						float uv[2];
						float u, v;
						imapaint_pick_uv(scene, ob, faceindex, mval, uv);
						sample_success = true;

						u = fmodf(uv[0], 1.0f);
						v = fmodf(uv[1], 1.0f);

						if (u < 0.0f) u += 1.0f;
						if (v < 0.0f) v += 1.0f;

						u = u * ibuf->x - 0.5f;
						v = v * ibuf->y - 0.5f;

						if (ibuf->rect_float) {
							float rgba_f[4];
							bilinear_interpolation_color_wrap(ibuf, NULL, rgba_f, u, v);
							straight_to_premul_v4(rgba_f);
							if (use_palette) {
								linearrgb_to_srgb_v3_v3(color->rgb, rgba_f);
							}
							else {
								linearrgb_to_srgb_v3_v3(rgba_f, rgba_f);
								BKE_brush_color_set(scene, br, rgba_f);
							}
						}
						else {
							unsigned char rgba[4];
							bilinear_interpolation_color_wrap(ibuf, rgba, NULL, u, v);
							if (use_palette) {
								rgb_uchar_to_float(color->rgb, rgba);
							}
							else {
								float rgba_f[3];
								rgb_uchar_to_float(rgba_f, rgba);
								BKE_brush_color_set(scene, br, rgba_f);
							}
						}
					}

					BKE_image_release_ibuf(image, ibuf, NULL);
				}
			}
			dm->release(dm);
		}

		if (!sample_success) {
			glReadBuffer(GL_FRONT);
			glReadPixels(x + ar->winrct.xmin, y + ar->winrct.ymin, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
			glReadBuffer(GL_BACK);
		}
		else
			return;
	}
	else {
		glReadBuffer(GL_FRONT);
		glReadPixels(x + ar->winrct.xmin, y + ar->winrct.ymin, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
		glReadBuffer(GL_BACK);
	}
	cp = (unsigned char *)&col;
	
	if (use_palette) {
		rgb_uchar_to_float(color->rgb, cp);
	}
	else {
		float rgba_f[3];
		rgb_uchar_to_float(rgba_f, cp);
		BKE_brush_color_set(scene, br, rgba_f);
	}
}
コード例 #19
0
ファイル: interface_draw.c プロジェクト: Eibriel/kiriblender
void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, rcti *rect)
{
	CurveMapping *cumap;
	CurveMap *cuma;
	CurveMapPoint *cmp;
	float fx, fy, fac[2], zoomx, zoomy, offsx, offsy;
	GLint scissor[4];
	rcti scissor_new;
	int a;

	if (but->editcumap) {
		cumap = but->editcumap;
	}
	else {
		cumap = (CurveMapping *)but->poin;
	}

	cuma = &cumap->cm[cumap->cur];

	/* need scissor test, curve can draw outside of boundary */
	glGetIntegerv(GL_VIEWPORT, scissor);
	scissor_new.xmin = ar->winrct.xmin + rect->xmin;
	scissor_new.ymin = ar->winrct.ymin + rect->ymin;
	scissor_new.xmax = ar->winrct.xmin + rect->xmax;
	scissor_new.ymax = ar->winrct.ymin + rect->ymax;
	BLI_rcti_isect(&scissor_new, &ar->winrct, &scissor_new);
	glScissor(scissor_new.xmin,
	          scissor_new.ymin,
	          BLI_rcti_size_x(&scissor_new),
	          BLI_rcti_size_y(&scissor_new));

	/* calculate offset and zoom */
	zoomx = (BLI_rcti_size_x(rect) - 2.0f * but->aspect) / BLI_rctf_size_x(&cumap->curr);
	zoomy = (BLI_rcti_size_y(rect) - 2.0f * but->aspect) / BLI_rctf_size_y(&cumap->curr);
	offsx = cumap->curr.xmin - but->aspect / zoomx;
	offsy = cumap->curr.ymin - but->aspect / zoomy;
	
	/* backdrop */
	if (but->a1 == UI_GRAD_H) {
		/* magic trigger for curve backgrounds */
		rcti grid;
		float col[3] = {0.0f, 0.0f, 0.0f}; /* dummy arg */

		grid.xmin = rect->xmin + zoomx * (-offsx);
		grid.xmax = rect->xmax + zoomx * (-offsx);
		grid.ymin = rect->ymin + zoomy * (-offsy);
		grid.ymax = rect->ymax + zoomy * (-offsy);

		ui_draw_gradient(&grid, col, UI_GRAD_H, 1.0f);

		/* grid, hsv uses different grid */
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		glColor4ub(0, 0, 0, 48);
		ui_draw_but_curve_grid(rect, zoomx, zoomy, offsx, offsy, 0.1666666f);
		glDisable(GL_BLEND);
	}
	else {
		if (cumap->flag & CUMA_DO_CLIP) {
			gl_shaded_color((unsigned char *)wcol->inner, -20);
			glRectf(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
			glColor3ubv((unsigned char *)wcol->inner);
			glRectf(rect->xmin + zoomx * (cumap->clipr.xmin - offsx),
			        rect->ymin + zoomy * (cumap->clipr.ymin - offsy),
			        rect->xmin + zoomx * (cumap->clipr.xmax - offsx),
			        rect->ymin + zoomy * (cumap->clipr.ymax - offsy));
		}
		else {
			glColor3ubv((unsigned char *)wcol->inner);
			glRectf(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
		}

		/* grid, every 0.25 step */
		gl_shaded_color((unsigned char *)wcol->inner, -16);
		ui_draw_but_curve_grid(rect, zoomx, zoomy, offsx, offsy, 0.25f);
		/* grid, every 1.0 step */
		gl_shaded_color((unsigned char *)wcol->inner, -24);
		ui_draw_but_curve_grid(rect, zoomx, zoomy, offsx, offsy, 1.0f);
		/* axes */
		gl_shaded_color((unsigned char *)wcol->inner, -50);
		glBegin(GL_LINES);
		glVertex2f(rect->xmin, rect->ymin + zoomy * (-offsy));
		glVertex2f(rect->xmax, rect->ymin + zoomy * (-offsy));
		glVertex2f(rect->xmin + zoomx * (-offsx), rect->ymin);
		glVertex2f(rect->xmin + zoomx * (-offsx), rect->ymax);
		glEnd();
	}

	/* cfra option */
	/* XXX 2.48 */
#if 0
	if (cumap->flag & CUMA_DRAW_CFRA) {
		glColor3ub(0x60, 0xc0, 0x40);
		glBegin(GL_LINES);
		glVertex2f(rect->xmin + zoomx * (cumap->sample[0] - offsx), rect->ymin);
		glVertex2f(rect->xmin + zoomx * (cumap->sample[0] - offsx), rect->ymax);
		glEnd();
	}
#endif
	/* sample option */

	if (cumap->flag & CUMA_DRAW_SAMPLE) {
		if (but->a1 == UI_GRAD_H) {
			float tsample[3];
			float hsv[3];
			linearrgb_to_srgb_v3_v3(tsample, cumap->sample);
			rgb_to_hsv_v(tsample, hsv);
			glColor3ub(240, 240, 240);

			glBegin(GL_LINES);
			glVertex2f(rect->xmin + zoomx * (hsv[0] - offsx), rect->ymin);
			glVertex2f(rect->xmin + zoomx * (hsv[0] - offsx), rect->ymax);
			glEnd();
		}
		else if (cumap->cur == 3) {
			float lum = rgb_to_bw(cumap->sample);
			glColor3ub(240, 240, 240);
			
			glBegin(GL_LINES);
			glVertex2f(rect->xmin + zoomx * (lum - offsx), rect->ymin);
			glVertex2f(rect->xmin + zoomx * (lum - offsx), rect->ymax);
			glEnd();
		}
		else {
			if (cumap->cur == 0)
				glColor3ub(240, 100, 100);
			else if (cumap->cur == 1)
				glColor3ub(100, 240, 100);
			else
				glColor3ub(100, 100, 240);
			
			glBegin(GL_LINES);
			glVertex2f(rect->xmin + zoomx * (cumap->sample[cumap->cur] - offsx), rect->ymin);
			glVertex2f(rect->xmin + zoomx * (cumap->sample[cumap->cur] - offsx), rect->ymax);
			glEnd();
		}
	}

	/* the curve */
	glColor3ubv((unsigned char *)wcol->item);
	glEnable(GL_LINE_SMOOTH);
	glEnable(GL_BLEND);
	glBegin(GL_LINE_STRIP);
	
	if (cuma->table == NULL)
		curvemapping_changed(cumap, FALSE);
	cmp = cuma->table;
	
	/* first point */
	if ((cuma->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) {
		glVertex2f(rect->xmin, rect->ymin + zoomy * (cmp[0].y - offsy));
	}
	else {
		fx = rect->xmin + zoomx * (cmp[0].x - offsx + cuma->ext_in[0]);
		fy = rect->ymin + zoomy * (cmp[0].y - offsy + cuma->ext_in[1]);
		glVertex2f(fx, fy);
	}
	for (a = 0; a <= CM_TABLE; a++) {
		fx = rect->xmin + zoomx * (cmp[a].x - offsx);
		fy = rect->ymin + zoomy * (cmp[a].y - offsy);
		glVertex2f(fx, fy);
	}
	/* last point */
	if ((cuma->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) {
		glVertex2f(rect->xmax, rect->ymin + zoomy * (cmp[CM_TABLE].y - offsy));
	}
	else {
		fx = rect->xmin + zoomx * (cmp[CM_TABLE].x - offsx - cuma->ext_out[0]);
		fy = rect->ymin + zoomy * (cmp[CM_TABLE].y - offsy - cuma->ext_out[1]);
		glVertex2f(fx, fy);
	}
	glEnd();
	glDisable(GL_LINE_SMOOTH);
	glDisable(GL_BLEND);

	/* the points, use aspect to make them visible on edges */
	cmp = cuma->curve;
	glPointSize(3.0f);
	bglBegin(GL_POINTS);
	for (a = 0; a < cuma->totpoint; a++) {
		if (cmp[a].flag & CUMA_SELECT)
			UI_ThemeColor(TH_TEXT_HI);
		else
			UI_ThemeColor(TH_TEXT);
		fac[0] = rect->xmin + zoomx * (cmp[a].x - offsx);
		fac[1] = rect->ymin + zoomy * (cmp[a].y - offsy);
		bglVertex2fv(fac);
	}
	bglEnd();
	glPointSize(1.0f);
	
	/* restore scissortest */
	glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);

	/* outline */
	glColor3ubv((unsigned char *)wcol->outline);
	fdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
}
コード例 #20
0
ファイル: image_draw.c プロジェクト: BHCLL/blendocv
void draw_image_info(ARegion *ar, int color_manage, int channels, int x, int y, char *cp, float *fp, int *zp, float *zpf)
{
	char str[256];
	float dx= 6;
	/* text colors */
	/* XXX colored text not allowed in Blender UI */
	#if 0
	unsigned char red[3] = {255, 50, 50};
	unsigned char green[3] = {0, 255, 0};
	unsigned char blue[3] = {100, 100, 255};
	#else
	unsigned char red[3] = {255, 255, 255};
	unsigned char green[3] = {255, 255, 255};
	unsigned char blue[3] = {255, 255, 255};
	#endif
	float hue=0, sat=0, val=0, lum=0, u=0, v=0;
	float col[4], finalcol[4];

	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
	glEnable(GL_BLEND);

	/* noisy, high contrast make impossible to read if lower alpha is used. */
	glColor4ub(0, 0, 0, 190);
	glRecti(0.0, 0.0, ar->winrct.xmax - ar->winrct.xmin + 1, 20);
	glDisable(GL_BLEND);

	BLF_size(blf_mono_font, 11, 72);

	glColor3ub(255, 255, 255);
	sprintf(str, "X:%-4d  Y:%-4d |", x, y);
	// UI_DrawString(6, 6, str); // works ok but fixed width is nicer.
	BLF_position(blf_mono_font, dx, 6, 0);
	BLF_draw_ascii(blf_mono_font, str, sizeof(str));
	dx += BLF_width(blf_mono_font, str);

	if(zp) {
		glColor3ub(255, 255, 255);
		sprintf(str, " Z:%-.4f |", 0.5f+0.5f*(((float)*zp)/(float)0x7fffffff));
		BLF_position(blf_mono_font, dx, 6, 0);
		BLF_draw_ascii(blf_mono_font, str, sizeof(str));
		dx += BLF_width(blf_mono_font, str);
	}
	if(zpf) {
		glColor3ub(255, 255, 255);
		sprintf(str, " Z:%-.3f |", *zpf);
		BLF_position(blf_mono_font, dx, 6, 0);
		BLF_draw_ascii(blf_mono_font, str, sizeof(str));
		dx += BLF_width(blf_mono_font, str);
	}

	if(channels >= 3) {
		glColor3ubv(red);
		if (fp)
			sprintf(str, "  R:%-.4f", fp[0]);
		else if (cp)
			sprintf(str, "  R:%-3d", cp[0]);
		else
			sprintf(str, "  R:-");
		BLF_position(blf_mono_font, dx, 6, 0);
		BLF_draw_ascii(blf_mono_font, str, sizeof(str));
		dx += BLF_width(blf_mono_font, str);
		
		glColor3ubv(green);
		if (fp)
			sprintf(str, "  G:%-.4f", fp[1]);
		else if (cp)
			sprintf(str, "  G:%-3d", cp[1]);
		else
			sprintf(str, "  G:-");
		BLF_position(blf_mono_font, dx, 6, 0);
		BLF_draw_ascii(blf_mono_font, str, sizeof(str));
		dx += BLF_width(blf_mono_font, str);
		
		glColor3ubv(blue);
		if (fp)
			sprintf(str, "  B:%-.4f", fp[2]);
		else if (cp)
			sprintf(str, "  B:%-3d", cp[2]);
		else
			sprintf(str, "  B:-");
		BLF_position(blf_mono_font, dx, 6, 0);
		BLF_draw_ascii(blf_mono_font, str, sizeof(str));
		dx += BLF_width(blf_mono_font, str);
		
		if(channels == 4) {
			glColor3ub(255, 255, 255);
			if (fp)
				sprintf(str, "  A:%-.4f", fp[3]);
			else if (cp)
				sprintf(str, "  A:%-3d", cp[3]);
			else
				sprintf(str, "- ");
			BLF_position(blf_mono_font, dx, 6, 0);
			BLF_draw_ascii(blf_mono_font, str, sizeof(str));
			dx += BLF_width(blf_mono_font, str);
		}
	}
	
	/* color rectangle */
	if (channels==1) {
		if (fp)
			col[0] = col[1] = col[2] = fp[0];
		else if (cp)
			col[0] = col[1] = col[2] = (float)cp[0]/255.0f;
		else
			col[0] = col[1] = col[2] = 0.0f;
	}
	else if (channels==3) {
		if (fp)
			copy_v3_v3(col, fp);
		else if (cp) {
			col[0] = (float)cp[0]/255.0f;
			col[1] = (float)cp[1]/255.0f;
			col[2] = (float)cp[2]/255.0f;
		}
		else
			zero_v3(col);
	}
	else if (channels==4) {
		if (fp)
			copy_v4_v4(col, fp);
		else if (cp) {
			col[0] = (float)cp[0]/255.0f;
			col[1] = (float)cp[1]/255.0f;
			col[2] = (float)cp[2]/255.0f;
			col[3] = (float)cp[3]/255.0f;
		}
		else
			zero_v4(col);
	}
	if (color_manage) {
		linearrgb_to_srgb_v3_v3(finalcol, col);
		finalcol[3] = col[3];
	}
	else {
		copy_v4_v4(finalcol, col);
	}
	glDisable(GL_BLEND);
	glColor3fv(finalcol);
	dx += 5;
	glBegin(GL_QUADS);
	glVertex2f(dx, 3);
	glVertex2f(dx, 17);
	glVertex2f(dx+30, 17);
	glVertex2f(dx+30, 3);
	glEnd();
	dx += 35;

	glColor3ub(255, 255, 255);
	if(channels == 1) {
		if (fp) {
			rgb_to_hsv(fp[0], fp[0], fp[0], &hue, &sat, &val);
			rgb_to_yuv(fp[0], fp[0], fp[0], &lum, &u, &v);
		}
		else if (cp) {
			rgb_to_hsv((float)cp[0]/255.0f, (float)cp[0]/255.0f, (float)cp[0]/255.0f, &hue, &sat, &val);
			rgb_to_yuv((float)cp[0]/255.0f, (float)cp[0]/255.0f, (float)cp[0]/255.0f, &lum, &u, &v);
		}
		
		sprintf(str, "V:%-.4f", val);
		BLF_position(blf_mono_font, dx, 6, 0);
		BLF_draw_ascii(blf_mono_font, str, sizeof(str));
		dx += BLF_width(blf_mono_font, str);

		sprintf(str, "   L:%-.4f", lum);
		BLF_position(blf_mono_font, dx, 6, 0);
		BLF_draw_ascii(blf_mono_font, str, sizeof(str));
		dx += BLF_width(blf_mono_font, str);
	}
	else if(channels >= 3) {
		if (fp) {
			rgb_to_hsv(fp[0], fp[1], fp[2], &hue, &sat, &val);
			rgb_to_yuv(fp[0], fp[1], fp[2], &lum, &u, &v);
		}
		else if (cp) {
			rgb_to_hsv((float)cp[0]/255.0f, (float)cp[1]/255.0f, (float)cp[2]/255.0f, &hue, &sat, &val);
			rgb_to_yuv((float)cp[0]/255.0f, (float)cp[1]/255.0f, (float)cp[2]/255.0f, &lum, &u, &v);
		}

		sprintf(str, "H:%-.4f", hue);
		BLF_position(blf_mono_font, dx, 6, 0);
		BLF_draw_ascii(blf_mono_font, str, sizeof(str));
		dx += BLF_width(blf_mono_font, str);

		sprintf(str, "  S:%-.4f", sat);
		BLF_position(blf_mono_font, dx, 6, 0);
		BLF_draw_ascii(blf_mono_font, str, sizeof(str));
		dx += BLF_width(blf_mono_font, str);

		sprintf(str, "  V:%-.4f", val);
		BLF_position(blf_mono_font, dx, 6, 0);
		BLF_draw_ascii(blf_mono_font, str, sizeof(str));
		dx += BLF_width(blf_mono_font, str);

		sprintf(str, "   L:%-.4f", lum);
		BLF_position(blf_mono_font, dx, 6, 0);
		BLF_draw_ascii(blf_mono_font, str, sizeof(str));
		dx += BLF_width(blf_mono_font, str);
	}

	(void)dx;
}
コード例 #21
0
ファイル: interface_draw.c プロジェクト: mik0001/Blender
void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *rect)
{
	ColorBand *coba;
	CBData *cbd;
	float x1, y1, sizex, sizey;
	float v3[2], v1[2], v2[2], v1a[2], v2a[2];
	int a;
	float pos, colf[4]= {0,0,0,0}; /* initialize incase the colorband isnt valid */
		
	coba= (ColorBand *)(but->editcoba? but->editcoba: but->poin);
	if(coba==NULL) return;
	
	x1= rect->xmin;
	y1= rect->ymin;
	sizex= rect->xmax-x1;
	sizey= rect->ymax-y1;

	/* first background, to show tranparency */

	glColor4ub(UI_TRANSP_DARK, UI_TRANSP_DARK, UI_TRANSP_DARK, 255);
	glRectf(x1, y1, x1+sizex, y1+sizey);
	glEnable(GL_POLYGON_STIPPLE);
	glColor4ub(UI_TRANSP_LIGHT, UI_TRANSP_LIGHT, UI_TRANSP_LIGHT, 255);
	glPolygonStipple(checker_stipple_sml);
	glRectf(x1, y1, x1+sizex, y1+sizey);
	glDisable(GL_POLYGON_STIPPLE);

	glShadeModel(GL_FLAT);
	glEnable(GL_BLEND);
	
	cbd= coba->data;
	
	v1[0]= v2[0]= x1;
	v1[1]= y1;
	v2[1]= y1+sizey;
	
	glBegin(GL_QUAD_STRIP);
	
	glColor4fv( &cbd->r );
	glVertex2fv(v1); glVertex2fv(v2);
	
	for( a = 1; a <= sizex; a++ ) {
		pos = ((float)a) / (sizex-1);
		do_colorband( coba, pos, colf );
		if (but->block->color_profile != BLI_PR_NONE)
			linearrgb_to_srgb_v3_v3(colf, colf);
		
		v1[0]=v2[0]= x1 + a;
		
		glColor4fv( colf );
		glVertex2fv(v1); glVertex2fv(v2);
	}
	
	glEnd();
	glShadeModel(GL_FLAT);
	glDisable(GL_BLEND);
	
	/* outline */
	glColor4f(0.0, 0.0, 0.0, 1.0);
	fdrawbox(x1, y1, x1+sizex, y1+sizey);
	
	/* help lines */
	v1[0]= v2[0]=v3[0]= x1;
	v1[1]= y1;
	v1a[1]= y1+0.25f*sizey;
	v2[1]= y1+0.5f*sizey;
	v2a[1]= y1+0.75f*sizey;
	v3[1]= y1+sizey;
	
	
	cbd= coba->data;
	glBegin(GL_LINES);
	for(a=0; a<coba->tot; a++, cbd++) {
		v1[0]=v2[0]=v3[0]=v1a[0]=v2a[0]= x1+ cbd->pos*sizex;
		
		if(a==coba->cur) {
			glColor3ub(0, 0, 0);
			glVertex2fv(v1);
			glVertex2fv(v3);
			glEnd();
			
			setlinestyle(2);
			glBegin(GL_LINES);
			glColor3ub(255, 255, 255);
			glVertex2fv(v1);
			glVertex2fv(v3);
			glEnd();
			setlinestyle(0);
			glBegin(GL_LINES);
			
			/* glColor3ub(0, 0, 0);
			glVertex2fv(v1);
			glVertex2fv(v1a);
			glColor3ub(255, 255, 255);
			glVertex2fv(v1a);
			glVertex2fv(v2);
			glColor3ub(0, 0, 0);
			glVertex2fv(v2);
			glVertex2fv(v2a);
			glColor3ub(255, 255, 255);
			glVertex2fv(v2a);
			glVertex2fv(v3);
			*/
		}
		else {
			glColor3ub(0, 0, 0);
			glVertex2fv(v1);
			glVertex2fv(v2);
			
			glColor3ub(255, 255, 255);
			glVertex2fv(v2);
			glVertex2fv(v3);
		}	
	}
	glEnd();

}
コード例 #22
0
ファイル: jp2.c プロジェクト: OldBrunet/BGERTPS
static opj_image_t* ibuftoimage(ImBuf *ibuf, opj_cparameters_t *parameters) {
	
	unsigned char *rect;
	float *rect_float;
	
	int subsampling_dx = parameters->subsampling_dx;
	int subsampling_dy = parameters->subsampling_dy;
	

	int i, numcomps, w, h, prec;
	int x,y, y_row;
	OPJ_COLOR_SPACE color_space;
	opj_image_cmptparm_t cmptparm[4];	/* maximum of 4 components */
	opj_image_t * image = NULL;
	
	img_fol_t img_fol; /* only needed for cinema presets */
	memset(&img_fol,0,sizeof(img_fol_t));
	
	if (ibuf->ftype & JP2_CINE) {
		
		if (ibuf->x==4096 || ibuf->y==2160)
			parameters->cp_cinema= CINEMA4K_24;
		else {
			if (ibuf->ftype & JP2_CINE_48FPS) {
				parameters->cp_cinema= CINEMA2K_48;
			}
			else {
				parameters->cp_cinema= CINEMA2K_24;
			}
		}
		if (parameters->cp_cinema){
			img_fol.rates = (float*)MEM_mallocN(parameters->tcp_numlayers * sizeof(float), "jp2_rates");
			for(i=0; i< parameters->tcp_numlayers; i++){
				img_fol.rates[i] = parameters->tcp_rates[i];
			}
			cinema_parameters(parameters);
		}
		
		color_space= CLRSPC_SYCC;
		prec= 12;
		numcomps= 3;
	}
	else { 
		/* Get settings from the imbuf */
		color_space = (ibuf->ftype & JP2_YCC) ? CLRSPC_SYCC : CLRSPC_SRGB;
		
		if (ibuf->ftype & JP2_16BIT)		prec= 16;
		else if (ibuf->ftype & JP2_12BIT)	prec= 12;
		else 						prec= 8;
		
		/* 32bit images == alpha channel */
		/* grayscale not supported yet */
		numcomps= (ibuf->depth==32) ? 4 : 3;
	}
	
	w= ibuf->x;
	h= ibuf->y;
	
	
	/* initialize image components */
	memset(&cmptparm[0], 0, 4 * sizeof(opj_image_cmptparm_t));
	for(i = 0; i < numcomps; i++) {
		cmptparm[i].prec = prec;
		cmptparm[i].bpp = prec;
		cmptparm[i].sgnd = 0;
		cmptparm[i].dx = subsampling_dx;
		cmptparm[i].dy = subsampling_dy;
		cmptparm[i].w = w;
		cmptparm[i].h = h;
	}
	/* create the image */
	image = opj_image_create(numcomps, &cmptparm[0], color_space);
	if(!image) {
		printf("Error: opj_image_create() failed\n");
		return NULL;
	}

	/* set image offset and reference grid */
	image->x0 = parameters->image_offset_x0;
	image->y0 = parameters->image_offset_y0;
	image->x1 = parameters->image_offset_x0 + (w - 1) *	subsampling_dx + 1;
	image->y1 = parameters->image_offset_y0 + (h - 1) *	subsampling_dy + 1;
	
	/* set image data */
	rect = (unsigned char*) ibuf->rect;
	rect_float= ibuf->rect_float;
	
	if (rect_float && rect && prec==8) {
		/* No need to use the floating point buffer, just write the 8 bits from the char buffer */
		rect_float= NULL;
	}
	
	
	if (rect_float) {
		float rgb[3];
		
		switch (prec) {
		case 8: /* Convert blenders float color channels to 8,12 or 16bit ints */
			for(y=h-1; y>=0; y--) {
				y_row = y*w;
				for(x=0; x<w; x++, rect_float+=4) {
					i = y_row + x;
					
					if (ibuf->profile == IB_PROFILE_LINEAR_RGB)
						linearrgb_to_srgb_v3_v3(rgb, rect_float);
					else
						copy_v3_v3(rgb, rect_float);
				
					image->comps[0].data[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rgb[0]);
					image->comps[1].data[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rgb[1]);
					image->comps[2].data[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rgb[2]);
					if (numcomps>3)
						image->comps[3].data[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rect_float[3]);
				}
			}
			break;
			
		case 12:
			for(y=h-1; y>=0; y--) {
				y_row = y*w;
				for(x=0; x<w; x++, rect_float+=4) {
					i = y_row + x;
					
					if (ibuf->profile == IB_PROFILE_LINEAR_RGB)
						linearrgb_to_srgb_v3_v3(rgb, rect_float);
					else
						copy_v3_v3(rgb, rect_float);
				
					image->comps[0].data[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rgb[0]);
					image->comps[1].data[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rgb[1]);
					image->comps[2].data[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rgb[2]);
					if (numcomps>3)
						image->comps[3].data[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rect_float[3]);
				}
			}
			break;
		case 16:
			for(y=h-1; y>=0; y--) {
				y_row = y*w;
				for(x=0; x<w; x++, rect_float+=4) {
					i = y_row + x;
					
					if (ibuf->profile == IB_PROFILE_LINEAR_RGB)
						linearrgb_to_srgb_v3_v3(rgb, rect_float);
					else
						copy_v3_v3(rgb, rect_float);
				
					image->comps[0].data[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rgb[0]);
					image->comps[1].data[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rgb[1]);
					image->comps[2].data[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rgb[2]);
					if (numcomps>3)
						image->comps[3].data[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rect_float[3]);
				}
			}
			break;
		}
	} else {
		/* just use rect*/
		switch (prec) {
		case 8:
			for(y=h-1; y>=0; y--) {
				y_row = y*w;
				for(x=0; x<w; x++, rect+=4) {
					i = y_row + x;
				
					image->comps[0].data[i] = rect[0];
					image->comps[1].data[i] = rect[1];
					image->comps[2].data[i] = rect[2];
					if (numcomps>3)
						image->comps[3].data[i] = rect[3];
				}
			}
			break;
			
		case 12: /* Up Sampling, a bit pointless but best write the bit depth requested */
			for(y=h-1; y>=0; y--) {
				y_row = y*w;
				for(x=0; x<w; x++, rect+=4) {
					i = y_row + x;
				
					image->comps[0].data[i]= UPSAMPLE_8_TO_12(rect[0]);
					image->comps[1].data[i]= UPSAMPLE_8_TO_12(rect[1]);
					image->comps[2].data[i]= UPSAMPLE_8_TO_12(rect[2]);
					if (numcomps>3)
						image->comps[3].data[i]= UPSAMPLE_8_TO_12(rect[3]);
				}
			}
			break;
		case 16:
			for(y=h-1; y>=0; y--) {
				y_row = y*w;
				for(x=0; x<w; x++, rect+=4) {
					i = y_row + x;
				
					image->comps[0].data[i]= UPSAMPLE_8_TO_16(rect[0]);
					image->comps[1].data[i]= UPSAMPLE_8_TO_16(rect[1]);
					image->comps[2].data[i]= UPSAMPLE_8_TO_16(rect[2]);
					if (numcomps>3)
						image->comps[3].data[i]= UPSAMPLE_8_TO_16(rect[3]);
				}
			}
			break;
		}
	}
	
	/* Decide if MCT should be used */
	parameters->tcp_mct = image->numcomps == 3 ? 1 : 0;
	
	if(parameters->cp_cinema){
		cinema_setup_encoder(parameters,image,&img_fol);
	}
	
	if (img_fol.rates)
		MEM_freeN(img_fol.rates);
	
	return image;
}
コード例 #23
0
static void update_tface_color_layer(DerivedMesh *dm, bool use_mcol)
{
	const MPoly *mp = dm->getPolyArray(dm);
	const int mpoly_num = dm->getNumPolys(dm);
	MTexPoly *mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY);
	MLoopCol *finalCol;
	int i, j;
	MLoopCol *mloopcol = NULL;

	/* cache material values to avoid a lot of lookups */
	Material *ma = NULL;
	short mat_nr_prev = -1;
	enum {
		COPY_CALC,
		COPY_ORIG,
		COPY_PREV,
	} copy_mode = COPY_CALC;

	if (use_mcol) {
		mloopcol = dm->getLoopDataArray(dm, CD_PREVIEW_MLOOPCOL);
		if (!mloopcol)
			mloopcol = dm->getLoopDataArray(dm, CD_MLOOPCOL);
	}

	if (CustomData_has_layer(&dm->loopData, CD_TEXTURE_MLOOPCOL)) {
		finalCol = CustomData_get_layer(&dm->loopData, CD_TEXTURE_MLOOPCOL);
	}
	else {
		finalCol = MEM_mallocN(sizeof(MLoopCol) * dm->numLoopData, "add_tface_color_layer");
		CustomData_add_layer(&dm->loopData, CD_TEXTURE_MLOOPCOL, CD_ASSIGN, finalCol, dm->numLoopData);
	}

	for (i = mpoly_num; i--; mp++) {
		const short mat_nr = mp->mat_nr;

		if (UNLIKELY(mat_nr_prev != mat_nr)) {
			ma = give_current_material(Gtexdraw.ob, mat_nr + 1);
			copy_mode = COPY_CALC;
			mat_nr_prev = mat_nr;
		}

		/* avoid lookups  */
		if (copy_mode == COPY_ORIG) {
			memcpy(&finalCol[mp->loopstart], &mloopcol[mp->loopstart], sizeof(*finalCol) * mp->totloop);
		}
		else if (copy_mode == COPY_PREV) {
			int loop_index = mp->loopstart;
			const MLoopCol *lcol_prev = &finalCol[(mp - 1)->loopstart];
			for (j = 0; j < mp->totloop; j++, loop_index++) {
				finalCol[loop_index] = *lcol_prev;
			}
		}

		/* (copy_mode == COPY_CALC) */
		else if (ma && (ma->game.flag & GEMAT_INVISIBLE)) {
			if (mloopcol) {
				memcpy(&finalCol[mp->loopstart], &mloopcol[mp->loopstart], sizeof(*finalCol) * mp->totloop);
				copy_mode = COPY_ORIG;
			}
			else {
				memset(&finalCol[mp->loopstart], 0xff, sizeof(*finalCol) * mp->totloop);
				copy_mode = COPY_PREV;
			}
		}
		else if (mtexpoly && set_draw_settings_cached(0, mtexpoly, ma, Gtexdraw)) {
			int loop_index = mp->loopstart;
			for (j = 0; j < mp->totloop; j++, loop_index++) {
				finalCol[loop_index].r = 255;
				finalCol[loop_index].g = 0;
				finalCol[loop_index].b = 255;
			}
			copy_mode = COPY_PREV;
		}
		else if (ma && (ma->shade_flag & MA_OBCOLOR)) {
			int loop_index = mp->loopstart;
			for (j = 0; j < mp->totloop; j++, loop_index++) {
				copy_v3_v3_char((char *)&finalCol[loop_index].r, (char *)Gtexdraw.obcol);
			}
			copy_mode = COPY_PREV;
		}
		else {
			if (mloopcol) {
				memcpy(&finalCol[mp->loopstart], &mloopcol[mp->loopstart], sizeof(*finalCol) * mp->totloop);
				copy_mode = COPY_ORIG;
			}
			else if (mtexpoly) {
				memset(&finalCol[mp->loopstart], 0xff, sizeof(*finalCol) * mp->totloop);
				copy_mode = COPY_PREV;
			}
			else {
				float col[3];

				if (ma) {
					int loop_index = mp->loopstart;
					MLoopCol lcol;

					if (Gtexdraw.color_profile) linearrgb_to_srgb_v3_v3(col, &ma->r);
					else copy_v3_v3(col, &ma->r);
					rgb_float_to_uchar((unsigned char *)&lcol.r, col);
					lcol.a = 255;
					
					for (j = 0; j < mp->totloop; j++, loop_index++) {
						finalCol[loop_index] = lcol;
					}
				}
				else {
					memset(&finalCol[mp->loopstart], 0xff, sizeof(*finalCol) * mp->totloop);
				}
				copy_mode = COPY_PREV;
			}
		}
	}
}
コード例 #24
0
/* create imbuf with brush color */
static ImBuf *brush_painter_imbuf_new(BrushPainter *painter, int size)
{
    Scene *scene = painter->scene;
    Brush *brush = painter->brush;

    rctf tex_mapping = painter->tex_mapping;
    rctf mask_mapping = painter->mask_mapping;
    struct ImagePool *pool = painter->pool;

    bool use_masking = painter->cache.use_masking;
    bool use_color_correction = painter->cache.use_color_correction;
    bool use_float = painter->cache.use_float;
    bool is_texbrush = painter->cache.is_texbrush;
    bool is_maskbrush = painter->cache.is_maskbrush;

    float alpha = (use_masking) ? 1.0f : BKE_brush_alpha_get(scene, brush);
    int radius = BKE_brush_size_get(scene, brush);
    int xoff = -size * 0.5f + 0.5f;
    int yoff = -size * 0.5f + 0.5f;

    int x, y, thread = 0;
    float brush_rgb[3];

    /* allocate image buffer */
    ImBuf *ibuf = IMB_allocImBuf(size, size, 32, (use_float) ? IB_rectfloat : IB_rect);

    /* get brush color */
    if (brush->imagepaint_tool == PAINT_TOOL_DRAW) {
        copy_v3_v3(brush_rgb, brush->rgb);

        if (use_color_correction)
            srgb_to_linearrgb_v3_v3(brush_rgb, brush_rgb);
    }
    else {
        brush_rgb[0] = 1.0f;
        brush_rgb[1] = 1.0f;
        brush_rgb[2] = 1.0f;
    }

    /* fill image buffer */
    for (y = 0; y < size; y++) {
        for (x = 0; x < size; x++) {
            /* sample texture and multiply with brush color */
            float texco[3], rgba[4];

            if (is_texbrush) {
                brush_imbuf_tex_co(&tex_mapping, x, y, texco);
                BKE_brush_sample_tex_3D(scene, brush, texco, rgba, thread, pool);
                /* TODO(sergey): Support texture paint color space. */
                if (!use_float) {
                    linearrgb_to_srgb_v3_v3(rgba, rgba);
                }
                mul_v3_v3(rgba, brush_rgb);
            }
            else {
                copy_v3_v3(rgba, brush_rgb);
                rgba[3] = 1.0f;
            }

            if (is_maskbrush) {
                brush_imbuf_tex_co(&mask_mapping, x, y, texco);
                rgba[3] *= BKE_brush_sample_masktex(scene, brush, texco, thread, pool);
            }

            /* when not using masking, multiply in falloff and strength */
            if (!use_masking) {
                float xy[2] = {x + xoff, y + yoff};
                float len = len_v2(xy);

                rgba[3] *= alpha * BKE_brush_curve_strength_clamp(brush, len, radius);
            }

            if (use_float) {
                /* write to float pixel */
                float *dstf = ibuf->rect_float + (y * size + x) * 4;
                mul_v3_v3fl(dstf, rgba, rgba[3]); /* premultiply */
                dstf[3] = rgba[3];
            }
            else {
                /* write to byte pixel */
                unsigned char *dst = (unsigned char *)ibuf->rect + (y * size + x) * 4;

                rgb_float_to_uchar(dst, rgba);
                dst[3] = FTOCHAR(rgba[3]);
            }
        }
    }

    return ibuf;
}
コード例 #25
0
static void update_tface_color_layer(DerivedMesh *dm)
{
	MTFace *tface = DM_get_tessface_data_layer(dm, CD_MTFACE);
	MFace *mface = dm->getTessFaceArray(dm);
	MCol *finalCol;
	int i, j;
	MCol *mcol = dm->getTessFaceDataArray(dm, CD_PREVIEW_MCOL);
	if (!mcol)
		mcol = dm->getTessFaceDataArray(dm, CD_MCOL);

	if (CustomData_has_layer(&dm->faceData, CD_TEXTURE_MCOL)) {
		finalCol = CustomData_get_layer(&dm->faceData, CD_TEXTURE_MCOL);
	}
	else {
		finalCol = MEM_mallocN(sizeof(MCol) * 4 * dm->getNumTessFaces(dm), "add_tface_color_layer");

		CustomData_add_layer(&dm->faceData, CD_TEXTURE_MCOL, CD_ASSIGN, finalCol, dm->numTessFaceData);
	}

	for (i = 0; i < dm->getNumTessFaces(dm); i++) {
		Material *ma = give_current_material(Gtexdraw.ob, mface[i].mat_nr + 1);

		if (ma && (ma->game.flag & GEMAT_INVISIBLE)) {
			if (mcol)
				memcpy(&finalCol[i * 4], &mcol[i * 4], sizeof(MCol) * 4);
			else
				for (j = 0; j < 4; j++) {
					finalCol[i * 4 + j].b = 255;
					finalCol[i * 4 + j].g = 255;
					finalCol[i * 4 + j].r = 255;
				}
		}
		else if (tface && set_draw_settings_cached(0, tface, ma, Gtexdraw)) {
			for (j = 0; j < 4; j++) {
				finalCol[i * 4 + j].b = 255;
				finalCol[i * 4 + j].g = 0;
				finalCol[i * 4 + j].r = 255;
			}
		}
		else if (ma && (ma->shade_flag & MA_OBCOLOR)) {
			for (j = 0; j < 4; j++) {
				finalCol[i * 4 + j].b = Gtexdraw.obcol[0];
				finalCol[i * 4 + j].g = Gtexdraw.obcol[1];
				finalCol[i * 4 + j].r = Gtexdraw.obcol[2];
			}
		}
		else if (!mcol) {
			if (tface) {
				for (j = 0; j < 4; j++) {
					finalCol[i * 4 + j].b = 255;
					finalCol[i * 4 + j].g = 255;
					finalCol[i * 4 + j].r = 255;
				}
			}
			else {
				float col[3];

				if (ma) {
					if (Gtexdraw.color_profile) linearrgb_to_srgb_v3_v3(col, &ma->r);
					else copy_v3_v3(col, &ma->r);
					
					for (j = 0; j < 4; j++) {
						finalCol[i * 4 + j].b = FTOCHAR(col[0]);
						finalCol[i * 4 + j].g = FTOCHAR(col[1]);
						finalCol[i * 4 + j].r = FTOCHAR(col[2]);
					}
				}
				else
					for (j = 0; j < 4; j++) {
						finalCol[i * 4 + j].b = 255;
						finalCol[i * 4 + j].g = 255;
						finalCol[i * 4 + j].r = 255;
					}
			}
		}
		else {
			for (j = 0; j < 4; j++) {
				finalCol[i * 4 + j].r = mcol[i * 4 + j].r;
				finalCol[i * 4 + j].g = mcol[i * 4 + j].g;
				finalCol[i * 4 + j].b = mcol[i * 4 + j].b;
			}
		}
	}
}
コード例 #26
0
ファイル: colortools.c プロジェクト: nttputus/blensor
void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management)
{
	int x, y, c;
	unsigned int n, nl;
	double div, divl;
	float *rf = NULL;
	unsigned char *rc = NULL;
	unsigned int *bin_r, *bin_g, *bin_b, *bin_lum;
	int savedlines, saveline;
	float rgb[3], ycc[3], luma;
	int ycc_mode = -1;
	const short is_float = (ibuf->rect_float != NULL);

	if (ibuf->rect == NULL && ibuf->rect_float == NULL) return;

	if (scopes->ok == 1) return;

	if (scopes->hist.ymax == 0.f) scopes->hist.ymax = 1.f;

	/* hmmmm */
	if (!(ELEM(ibuf->channels, 3, 4))) return;

	scopes->hist.channels = 3;
	scopes->hist.x_resolution = 256;

	switch (scopes->wavefrm_mode) {
		case SCOPES_WAVEFRM_RGB:
			ycc_mode = -1;
			break;
		case SCOPES_WAVEFRM_LUMA:
		case SCOPES_WAVEFRM_YCC_JPEG:
			ycc_mode = BLI_YCC_JFIF_0_255;
			break;
		case SCOPES_WAVEFRM_YCC_601:
			ycc_mode = BLI_YCC_ITU_BT601;
			break;
		case SCOPES_WAVEFRM_YCC_709:
			ycc_mode = BLI_YCC_ITU_BT709;
			break;
	}

	/* temp table to count pix value for histo */
	bin_r = MEM_callocN(256 * sizeof(unsigned int), "temp historgram bins");
	bin_g = MEM_callocN(256 * sizeof(unsigned int), "temp historgram bins");
	bin_b = MEM_callocN(256 * sizeof(unsigned int), "temp historgram bins");
	bin_lum = MEM_callocN(256 * sizeof(unsigned int), "temp historgram bins");

	/* convert to number of lines with logarithmic scale */
	scopes->sample_lines = (scopes->accuracy * 0.01f) * (scopes->accuracy * 0.01f) * ibuf->y;
	
	if (scopes->sample_full)
		scopes->sample_lines = ibuf->y;

	/* scan the image */
	savedlines = 0;
	for (c = 0; c < 3; c++) {
		scopes->minmax[c][0] = 25500.0f;
		scopes->minmax[c][1] = -25500.0f;
	}
	
	scopes->waveform_tot = ibuf->x * scopes->sample_lines;
	
	if (scopes->waveform_1)
		MEM_freeN(scopes->waveform_1);
	if (scopes->waveform_2)
		MEM_freeN(scopes->waveform_2);
	if (scopes->waveform_3)
		MEM_freeN(scopes->waveform_3);
	if (scopes->vecscope)
		MEM_freeN(scopes->vecscope);
	
	scopes->waveform_1 = MEM_callocN(scopes->waveform_tot * 2 * sizeof(float), "waveform point channel 1");
	scopes->waveform_2 = MEM_callocN(scopes->waveform_tot * 2 * sizeof(float), "waveform point channel 2");
	scopes->waveform_3 = MEM_callocN(scopes->waveform_tot * 2 * sizeof(float), "waveform point channel 3");
	scopes->vecscope = MEM_callocN(scopes->waveform_tot * 2 * sizeof(float), "vectorscope point channel");
	
	if (is_float)
		rf = ibuf->rect_float;
	else
		rc = (unsigned char *)ibuf->rect;

	for (y = 0; y < ibuf->y; y++) {
		if (savedlines < scopes->sample_lines && y >= ((savedlines) * ibuf->y) / (scopes->sample_lines + 1)) {
			saveline = 1;
		}
		else {
			saveline = 0;
		}
		for (x = 0; x < ibuf->x; x++) {

			if (is_float) {
				if (use_color_management)
					linearrgb_to_srgb_v3_v3(rgb, rf);
				else
					copy_v3_v3(rgb, rf);
			}
			else {
				for (c = 0; c < 3; c++)
					rgb[c] = rc[c] * INV_255;
			}

			/* we still need luma for histogram */
			luma = rgb_to_luma(rgb);

			/* check for min max */
			if (ycc_mode == -1) {
				for (c = 0; c < 3; c++) {
					if (rgb[c] < scopes->minmax[c][0]) scopes->minmax[c][0] = rgb[c];
					if (rgb[c] > scopes->minmax[c][1]) scopes->minmax[c][1] = rgb[c];
				}
			}
			else {
				rgb_to_ycc(rgb[0], rgb[1], rgb[2], &ycc[0], &ycc[1], &ycc[2], ycc_mode);
				for (c = 0; c < 3; c++) {
					ycc[c] *= INV_255;
					if (ycc[c] < scopes->minmax[c][0]) scopes->minmax[c][0] = ycc[c];
					if (ycc[c] > scopes->minmax[c][1]) scopes->minmax[c][1] = ycc[c];
				}
			}
			/* increment count for histo*/
			bin_r[get_bin_float(rgb[0])] += 1;
			bin_g[get_bin_float(rgb[1])] += 1;
			bin_b[get_bin_float(rgb[2])] += 1;
			bin_lum[get_bin_float(luma)] += 1;

			/* save sample if needed */
			if (saveline) {
				const float fx = (float)x / (float)ibuf->x;
				const int idx = 2 * (ibuf->x * savedlines + x);
				save_sample_line(scopes, idx, fx, rgb, ycc);
			}

			rf += ibuf->channels;
			rc += ibuf->channels;
		}
		if (saveline)
			savedlines += 1;
	}

	/* convert hist data to float (proportional to max count) */
	n = 0;
	nl = 0;
	for (x = 0; x < 256; x++) {
		if (bin_r[x] > n)
			n = bin_r[x];
		if (bin_g[x] > n)
			n = bin_g[x];
		if (bin_b[x] > n)
			n = bin_b[x];
		if (bin_lum[x] > nl)
			nl = bin_lum[x];
	}
	div = 1.0 / (double)n;
	divl = 1.0 / (double)nl;
	for (x = 0; x < 256; x++) {
		scopes->hist.data_r[x] = bin_r[x] * div;
		scopes->hist.data_g[x] = bin_g[x] * div;
		scopes->hist.data_b[x] = bin_b[x] * div;
		scopes->hist.data_luma[x] = bin_lum[x] * divl;
	}
	MEM_freeN(bin_r);
	MEM_freeN(bin_g);
	MEM_freeN(bin_b);
	MEM_freeN(bin_lum);

	scopes->ok = 1;
}
コード例 #27
0
int imb_savetiff(ImBuf *ibuf, const char *name, int flags)
{
	TIFF *image = NULL;
	uint16 samplesperpixel, bitspersample;
	size_t npixels;
	unsigned char *pixels = NULL;
	unsigned char *from = NULL, *to = NULL;
	unsigned short *pixels16 = NULL, *to16 = NULL;
	float *fromf = NULL;
	int x, y, from_i, to_i, i;
	int extraSampleTypes[1] = { EXTRASAMPLE_ASSOCALPHA };
	

	/* check for a valid number of bytes per pixel.  Like the PNG writer,
	 * the TIFF writer supports 1, 3 or 4 bytes per pixel, corresponding
	 * to gray, RGB, RGBA respectively. */
	samplesperpixel = (uint16)((ibuf->depth + 7) >> 3);
	if((samplesperpixel > 4) || (samplesperpixel == 2)) {
		fprintf(stderr,
			"imb_savetiff: unsupported number of bytes per " 
			"pixel: %d\n", samplesperpixel);
		return (0);
	}

	if((ibuf->ftype & TIF_16BIT) && ibuf->rect_float)
		bitspersample = 16;
	else
		bitspersample = 8;

	/* open TIFF file for writing */
	if(flags & IB_mem) {
		/* bork at the creation of a TIFF in memory */
		fprintf(stderr,
			"imb_savetiff: creation of in-memory TIFF files is " 
			"not yet supported.\n");
		return (0);
	}
	else {
		/* create image as a file */
		image = TIFFOpen(name, "w");
	}
	if(image == NULL) {
		fprintf(stderr,
			"imb_savetiff: could not open TIFF for writing.\n");
		return (0);
	}

	/* allocate array for pixel data */
	npixels = ibuf->x * ibuf->y;
	if(bitspersample == 16)
		pixels16 = (unsigned short*)_TIFFmalloc(npixels *
			samplesperpixel * sizeof(unsigned short));
	else
		pixels = (unsigned char*)_TIFFmalloc(npixels *
			samplesperpixel * sizeof(unsigned char));

	if(pixels == NULL && pixels16 == NULL) {
		fprintf(stderr,
			"imb_savetiff: could not allocate pixels array.\n");
		TIFFClose(image);
		return (0);
	}

	/* setup pointers */
	if(bitspersample == 16) {
		fromf = ibuf->rect_float;
		to16   = pixels16;
	}
	else {
		from = (unsigned char*)ibuf->rect;
		to   = pixels;
	}

	/* setup samples per pixel */
	TIFFSetField(image, TIFFTAG_BITSPERSAMPLE, bitspersample);
	TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);

	if(samplesperpixel == 4) {
		/* RGBA images */
		TIFFSetField(image, TIFFTAG_EXTRASAMPLES, 1,
				extraSampleTypes);
		TIFFSetField(image, TIFFTAG_PHOTOMETRIC, 
				PHOTOMETRIC_RGB);
	}
	else if(samplesperpixel == 3) {
		/* RGB images */
		TIFFSetField(image, TIFFTAG_PHOTOMETRIC,
				PHOTOMETRIC_RGB);
	}
	else if(samplesperpixel == 1) {
		/* greyscale images, 1 channel */
		TIFFSetField(image, TIFFTAG_PHOTOMETRIC,
				PHOTOMETRIC_MINISBLACK);
	}

	/* copy pixel data.  While copying, we flip the image vertically. */
	for(x = 0; x < ibuf->x; x++) {
		for(y = 0; y < ibuf->y; y++) {
			from_i = 4*(y*ibuf->x+x);
			to_i   = samplesperpixel*((ibuf->y-y-1)*ibuf->x+x);

			if(pixels16) {
				/* convert from float source */
				float rgb[3];
				
				if (ibuf->profile == IB_PROFILE_LINEAR_RGB)
					linearrgb_to_srgb_v3_v3(rgb, &fromf[from_i]);
				else
					copy_v3_v3(rgb, &fromf[from_i]);

				to16[to_i+0] = FTOUSHORT(rgb[0]);
				to16[to_i+1] = FTOUSHORT(rgb[1]);
				to16[to_i+2] = FTOUSHORT(rgb[2]);
				to_i += 3; from_i+=3;
				
				if (samplesperpixel == 4) {
					to16[to_i+3] = FTOUSHORT(fromf[from_i+3]);
					/*to_i++; from_i++;*/ /*unused, set on each loop */
				}
			}
			else {
				for(i = 0; i < samplesperpixel; i++, to_i++, from_i++)
					to[to_i] = from[from_i];
			}
		}
	}

	/* write the actual TIFF file */
	TIFFSetField(image, TIFFTAG_IMAGEWIDTH,      ibuf->x);
	TIFFSetField(image, TIFFTAG_IMAGELENGTH,     ibuf->y);
	TIFFSetField(image, TIFFTAG_ROWSPERSTRIP,    ibuf->y);
	TIFFSetField(image, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE);
	TIFFSetField(image, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
	TIFFSetField(image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
	TIFFSetField(image, TIFFTAG_XRESOLUTION,     150.0);
	TIFFSetField(image, TIFFTAG_YRESOLUTION,     150.0);
	TIFFSetField(image, TIFFTAG_RESOLUTIONUNIT,  RESUNIT_INCH);
	if(TIFFWriteEncodedStrip(image, 0,
			(bitspersample == 16)? (unsigned char*)pixels16: pixels,
			ibuf->x*ibuf->y*samplesperpixel*bitspersample/8) == -1) {
		fprintf(stderr,
			"imb_savetiff: Could not write encoded TIFF.\n");
		TIFFClose(image);
		if(pixels) _TIFFfree(pixels);
		if(pixels16) _TIFFfree(pixels16);
		return (1);
	}

	/* close the TIFF file */
	TIFFClose(image);
	if(pixels) _TIFFfree(pixels);
	if(pixels16) _TIFFfree(pixels16);
	return (1);
}