# image convert words # : s16 [s] image/s16 convert ; "( image -- image/s16 )\tConvert image to 16 bit component depth (signed short int)." , # : s8 [s] image/s8 convert ; "( image -- image/s8 )\tConvert image to 8 bit component depth (signed char)." , # some other useful things : bitmap>image image-component-type image-from-bitmap ; "( bitmap -- image )\tConvert bitmap to default image encoding." , latestxt polyword >image : image>i420 ` i420 bitmap-from-image ; latestxt polyword >i420 : image>yv12 ` yv12 bitmap-from-image ; latestxt polyword >yv12 : image>rgb ` rgb bitmap-from-image ; latestxt polyword >rgb : image>gl-rgb ` gl-rgb bitmap-from-image ; : image>gl-rgba ` gl-rgba bitmap-from-image ; : image>gl-grey ` gl-grey bitmap-from-image ; # default : image>bitmap image>i420 ; "( image -- bitmap )\tConvert image to default bitmap encoding." , # bitmap conversion : bitmap-from-bitmap swap ` s16 image-from-bitmap swap bitmap-from-image ; " ( bitmap fourcc -- bitmap )" , # color space conversion using the generic matrix transform # this does NOT respect black level!! i.e. transform is linear, not affine. # FIXME: black level should be handled in bitmap<>image conversion # notes, the standard says, for gamma corrected (nonlinear) R'G'B': # Y = .299 R' + .587 G' + .114 B' # Cb = .564 (B' - Y') # Cr = .713 (R' - Y') # for more info see doc/colourspace.txt # in pf, the image/* type does not have an associated colourspace, however # there is an assumption about the colours of the planes, this is # R = 0 # G = 1 # B = 2 # and # Y = 0 # Cb (U) = 1 # Cr (V) = 2 # the latter corresponds to i420 fourcc YCbCr (YUV), # which is a standard used in yuv4mpeg and supported by most XVideo drivers load-matrix # using column vectors the matrix (( 0.257 0.504 0.098) (-0.296 -0.582 0.878) ( 0.878 -0.736 -0.142)) # transforms the column vector x into column vector y = Ax # in pf we use postfix: y^T = x^T A^T, which means we'll # express the transform using the transpose of this matrix: transpose >matrix constant M-rgb>YCbCr # the result is that multiplication from the right will transform # each row of RGB values in a matrix to their corresponding # 'internal' YCbCr values (with chroma centered around zero) # internal YCbCr values are computed from their 8 bit values as # Y [0..255] -> [0..1] # C [-128..127] -> [-1..1] # note that this is not a standard mapping, which is reflected # in the conversion matrix's C rows, which are scaled by 2 # we can easily compute the inverse # FIXME: add some more convenient matrix inverse words M-rgb>YCbCr matrix:inverse constant M-YCbCr>rgb # transformers : rgb>YCbCr M-rgb>YCbCr image:crotate ; : YCbCr>rgb [ M-YCbCr>rgb .5 * ]L image:crotate dup + ;