예제 #1
0
파일: image.c 프로젝트: WST/gallerizer-cli
inline Pixel * pixelAt(Image *image, unsigned int x, unsigned int y) {
	if(x > image->width) {
		return pixelAt(image, x - 1, y);
	}
	if(y > image->height) {
		return pixelAt(image, x, y - 1);
	}
	return &(image->canvas[(y * image->width) + x]);
}
예제 #2
0
파일: layer.cpp 프로젝트: gotomypc/Drawpile
/**
 * @param x
 * @param y
 * @return invalid color if x or y is outside image boundaries
 */
QColor Layer::colorAt(int x, int y) const
{
	if(x<0 || y<0 || x>=_width || y>=_height)
		return QColor();

	return QColor::fromRgb(pixelAt(x, y));
}
예제 #3
0
void
Image::applyMaskMixForMaskInvert(const RectI& roi,
                                 const Image* maskImg,
                                 const Image* originalImg,
                                 float mix)
{
    PIX* dst_pixels = (PIX*)pixelAt(roi.x1, roi.y1);
    unsigned int dstRowElements = _bounds.width() * getComponentsCount();

    for ( int y = roi.y1; y < roi.y2; ++y,
          dst_pixels += (dstRowElements - (roi.x2 - roi.x1) * dstNComps) ) { // 1 row stride minus what was done at previous iteration
        for (int x = roi.x1; x < roi.x2; ++x,
             dst_pixels += dstNComps) {
            const PIX* src_pixels = originalImg ? (const PIX*)originalImg->pixelAt(x, y) : 0;
            float maskScale = 1.f;
            if (!masked) {
                // just mix
                float alpha = mix;
                if (src_pixels) {
                    for (int c = 0; c < dstNComps; ++c) {
                        if (c < srcNComps) {
                            float v = float(dst_pixels[c]) * alpha + (1.f - alpha) * float(src_pixels[c]);
                            dst_pixels[c] = clampIfInt<PIX>(v);
                        }
                    }
                } else {
                    for (int c = 0; c < dstNComps; ++c) {
                        float v = float(dst_pixels[c]) * alpha;
                        dst_pixels[c] = clampIfInt<PIX>(v);
                    }
                }
            } else {
                const PIX* maskPixels = maskImg ? (const PIX*)maskImg->pixelAt(x, y) : 0;
                // figure the scale factor from that pixel
                if (maskPixels == 0) {
                    maskScale = maskInvert ? 1.f : 0.f;
                } else {
                    maskScale = *maskPixels / float(maxValue);
                    if (maskInvert) {
                        maskScale = 1.f - maskScale;
                    }
                }
                float alpha = mix * maskScale;
                if (src_pixels) {
                    for (int c = 0; c < dstNComps; ++c) {
                        if (c < srcNComps) {
                            float v = float(dst_pixels[c]) * alpha + (1.f - alpha) * float(src_pixels[c]);
                            dst_pixels[c] = clampIfInt<PIX>(v);
                        }
                    }
                } else {
                    for (int c = 0; c < dstNComps; ++c) {
                        float v = float(dst_pixels[c]) * alpha;
                        dst_pixels[c] = clampIfInt<PIX>(v);
                    }
                }
            }
        }
    }
} // Image::applyMaskMixForMaskInvert
예제 #4
0
pixel3f *Image::createGaussian(float sigma)
{
	pixel3f *gaussian = new pixel3f[_width * _height]();
	
	// Precompute constants.
	float variance = sigma * sigma;
	float denomiator = 2 * M_PI * variance;

	// Radius of filter.
	int r = 2.0f * sigma;
	float *kernel = createGaussianKernel(r + 1, variance);
	
	// Seperable x component of Gaussian filter.
	for (int x = 0; x < _width; x++) {
		for (int y = 0; y < _height; y++) {
			float sum = 0;
			
			for (int i = -r; i <= r; i++) {
				sum += pixelAt(_pixels, x + i, y)->L * kernel[abs(i)];
			}
			
			// Do not divide by the regular denominator.
			pixelAt(_copy, x, y)->L = sum;
		}
	}
	
	// Seperable y component of Gaussian filter.
	for (int x = 0; x < _width; x++) {
		for (int y = 0; y < _height; y++) {
			float sum = 0;
			
			for (int j = -r; j <= r; j++) {
				sum += pixelAt(_copy, x, y + j)->L * kernel[abs(j)];
			}
			
			// Divided by the denominator squared only once rather than twice.
			pixelAt(gaussian, x, y)->L = sum / denomiator;
		}
	}
	
	// Free temporary data.
	delete[] kernel;
	
	return gaussian;
}
예제 #5
0
std::vector<Eigen::Vector3f> ImageReader::toVector(){
    std::vector<Eigen::Vector3f> output;
    for (int i = 0; i < getImageHeight(); i++) {
        for (int j = 0; j < getImageWidth(); j++) {
            QColor pixelColor = QColor(pixelAt(i,j));
            Eigen::Vector3f color = Eigen::Vector3f(float(pixelColor.red()), float(pixelColor.green()), float(pixelColor.blue()));
            output.push_back(color);
        }
    }
    return output;
}
예제 #6
0
파일: film.hpp 프로젝트: ennis/path-tracer
	void convertToRGB(uint32_t *outPixels) const {
		for (unsigned int x = 0; x < m_width; ++x) {
			for (unsigned int y = 0; y < m_height; ++y) {
				PixelSample &sample = pixelAt(x, y);
				if (sample.filterAccum != 0) {
					outPixels[x + y*m_width] = mapRGB(sample.accum / sample.filterAccum);
				} else {
					outPixels[x + y*m_width] = mapRGB(Vec());
				}
			}
		}
	}
예제 #7
0
파일: film.hpp 프로젝트: ennis/path-tracer
	void addSample(float x, float y, Vec const &value) 
	{
		int x1 = ceil2Int(x - m_filterWidth);
		int x2 = floor2Int(x + m_filterWidth);
		int y1 = ceil2Int(y - m_filterHeight);
		int y2 = ceil2Int(y + m_filterWidth);
		x1 = std::max(0, x1);
		x2 = std::min(x2, m_width);
		y1 = std::max(0, y1);
		y2 = std::min(y2, m_height);
		// update all pixels affected by the sample
		for (int ix = x1; ix < x2; ++ix) {
			for (int iy = y1; iy < y2; ++iy) {
				float filterVal = evalFilter(
					fabsf(static_cast<float>(ix) - x),
					fabsf(static_cast<float>(iy) - y));
				pixelAt(ix, iy).accum += filterVal * value;
				pixelAt(ix, iy).filterAccum += filterVal;
			}
		}
	}
예제 #8
0
/**
 * @param x
 * @param y
 * @return invalid color if x or y is outside image boundaries
 */
QColor Layer::colorAt(int x, int y, int dia) const
{
    if(x<0 || y<0 || x>=_width || y>=_height)
        return QColor();

    if(dia<=1) {
        quint32 c = pixelAt(x, y);
        if(qAlpha(c)==0)
            return QColor();

        return QColor::fromRgb(c);
    } else {
        Brush b(dia, 0.9);
        BrushStamp bs = makeGimpStyleBrushStamp(b, Point(x, y, 1));
        return getDabColor(bs);
    }
}
예제 #9
0
void ImageReader::findMinAndMax()
{
    int min = 10000000000;
    int max = -1;

    for (int i = 0; i < getImageHeight(); i++) {
        for (int j = 0; j < getImageWidth(); j++) {
            if (QColor(pixelAt(i,j)).red() > 150) {
                if (j > max) {
                    max = j;
                }
                if (j < min) {
                    min = j;
                }
            }
        }
    }

    assert(max > min);
    m_xMax = max;
    m_xMin = min;
}
예제 #10
0
void
Image::copyUnProcessedChannelsForPremult(const std::bitset<4> processChannels,
                                         const RectI& roi,
                                         const ImagePtr& originalImage)
{
    Q_UNUSED(processChannels); // silence warnings in release version
    assert( ( (doR == !processChannels[0]) || !(dstNComps >= 2) ) &&
            ( (doG == !processChannels[1]) || !(dstNComps >= 2) ) &&
            ( (doB == !processChannels[2]) || !(dstNComps >= 3) ) &&
            ( (doA == !processChannels[3]) || !(dstNComps == 1 || dstNComps == 4) ) );
    ReadAccess acc( originalImage.get() );
    int dstRowElements = dstNComps * _bounds.width();
    PIX* dst_pixels = (PIX*)pixelAt(roi.x1, roi.y1);
    assert(dst_pixels);
    assert(srcNComps == 1 || srcNComps == 4 || !originalPremult); // only A or RGBA can be premult
    assert(dstNComps == 1 || dstNComps == 4 || !premult); // only A or RGBA can be premult

    for ( int y = roi.y1; y < roi.y2; ++y, dst_pixels += (dstRowElements - (roi.x2 - roi.x1) * dstNComps) ) {
        for (int x = roi.x1; x < roi.x2; ++x, dst_pixels += dstNComps) {
            const PIX* src_pixels = originalImage ? (const PIX*)acc.pixelAt(x, y) : 0;
            PIX srcA = src_pixels ? maxValue : 0; /* be opaque for anything that doesn't contain alpha */
            if ( ( (srcNComps == 1) || (srcNComps == 4) ) && src_pixels ) {
#             ifdef DEBUG
                assert(src_pixels[srcNComps - 1] == src_pixels[srcNComps - 1]); // check for NaN
#             endif
                srcA = src_pixels[srcNComps - 1];
            }

#        ifdef NATRON_COPY_CHANNELS_UNPREMULT
            // Repremult R G and B if output is premult and alpha was modified.
            // We do not consider it a good thing, since the user explicitely deselected the channels, and expects
            // to get the values from input instead.
#           define DOCHANNEL(c)                                                    \
    if (srcNComps == 1 || !src_pixels || c >= srcNComps) {      \
        dst_pixels[c] = 0;                                      \
    } \
    else if (originalPremult) {                               \
        if (srcA == 0) {                                        \
            dst_pixels[c] = src_pixels[c];         /* don't try to unpremult, just copy */ \
        } \
        else if (premult) {                                   \
            if (doA) {                                          \
                dst_pixels[c] = src_pixels[c];         /* dst will have same alpha as src, just copy src */ \
            } \
            else {                                            \
                dst_pixels[c] = (src_pixels[c] / (float)srcA) * dstAorig;         /* dst keeps its alpha, unpremult src and repremult */ \
            }                                                   \
        } \
        else {                                                \
            dst_pixels[c] = (src_pixels[c] / (float)srcA) * maxValue;         /* dst is not premultiplied, unpremult src */ \
        }                                                       \
    } \
    else {                                                    \
        if (premult) {                                          \
            if (doA) {                                          \
                dst_pixels[c] = (src_pixels[c] / (float)maxValue) * srcA;         /* dst will have same alpha as src, just premult src with its alpha */ \
            } \
            else {                                            \
                dst_pixels[c] = (src_pixels[c] / (float)maxValue) * dstAorig;         /* dst keeps its alpha, premult src with dst's alpha */ \
            }                                                   \
        } \
        else {                                                \
            dst_pixels[c] = src_pixels[c];         /* neither src nor dst is not premultiplied */ \
        }                                                       \
    }

            PIX dstAorig = maxValue;
#         else // !NATRON_COPY_CHANNELS_UNPREMULT
               // Just copy the channels, after all if the user unchecked a channel,
               // we do not want to change the values behind his back.
               // Rather we display a warning in  the GUI.
#           define DOCHANNEL(c) dst_pixels[c] = (!src_pixels || c >= srcNComps) ? 0 : src_pixels[c];
#         endif // !NATRON_COPY_CHANNELS_UNPREMULT

            if ( (dstNComps == 1) || (dstNComps == 4) ) {
#             ifdef DEBUG
                assert(dst_pixels[dstNComps - 1] == dst_pixels[dstNComps - 1]); // check for NaN
#             endif
#             ifdef NATRON_COPY_CHANNELS_UNPREMULT
                dstAorig = dst_pixels[dstNComps - 1];
#             endif // NATRON_COPY_CHANNELS_UNPREMULT
            }
            if (doR) {
#             ifdef DEBUG
                assert(!src_pixels || src_pixels[0] == src_pixels[0]); // check for NaN
                assert(dst_pixels[0] == dst_pixels[0]); // check for NaN
#             endif
                DOCHANNEL(0);
#             ifdef DEBUG
                assert(dst_pixels[0] == dst_pixels[0]); // check for NaN
#             endif
            }
            if (doG) {
#             ifdef DEBUG
                assert(!src_pixels || src_pixels[1] == src_pixels[1]); // check for NaN
                assert(dst_pixels[1] == dst_pixels[1]); // check for NaN
#             endif
                DOCHANNEL(1);
#             ifdef DEBUG
                assert(dst_pixels[1] == dst_pixels[1]); // check for NaN
#             endif
            }
            if (doB) {
#             ifdef DEBUG
                assert(!src_pixels || src_pixels[2] == src_pixels[2]); // check for NaN
                assert(dst_pixels[2] == dst_pixels[2]); // check for NaN
#             endif
                DOCHANNEL(2);
#             ifdef DEBUG
                assert(dst_pixels[2] == dst_pixels[2]); // check for NaN
#             endif
            }
            if (doA) {
#             ifdef NATRON_COPY_CHANNELS_UNPREMULT
                if (premult) {
                    if (dstAorig != 0) {
                        // unpremult, then premult
                        if ( (dstNComps >= 2) && !doR ) {
                            dst_pixels[0] = (dst_pixels[0] / (float)dstAorig) * srcA;
#                         ifdef DEBUG
                            assert(dst_pixels[0] == dst_pixels[0]); // check for NaN
#                         endif
                        }
                        if ( (dstNComps >= 2) && !doG ) {
                            dst_pixels[1] = (dst_pixels[1] / (float)dstAorig) * srcA;
#                         ifdef DEBUG
                            assert(dst_pixels[1] == dst_pixels[1]); // check for NaN
#                         endif
                        }
                        if ( (dstNComps >= 2) && !doB ) {
                            dst_pixels[2] = (dst_pixels[2] / (float)dstAorig) * srcA;
#                         ifdef DEBUG
                            assert(dst_pixels[2] == dst_pixels[2]); // check for NaN
#                         endif
                        }
                    }
                }
#             endif // NATRON_COPY_CHANNELS_UNPREMULT
                if ( (dstNComps == 1) || (dstNComps == 4) ) {
                    dst_pixels[dstNComps - 1] = srcA;
#                 ifdef DEBUG
                    assert(dst_pixels[dstNComps - 1] == dst_pixels[dstNComps - 1]); // check for NaN
#                 endif
                }
            }
        }
    }
} // Image::copyUnProcessedChannelsForPremult
예제 #11
0
void
Image::copyUnProcessedChannelsForPremult(const bool premult,
                                         const bool originalPremult,
                                         const std::bitset<4> processChannels,
                                         const RectI& roi,
                                         const ImagePtr& originalImage)
{
    ReadAccess acc( originalImage.get() );
    int dstRowElements = dstNComps * _bounds.width();
    PIX* dst_pixels = (PIX*)pixelAt(roi.x1, roi.y1);

    assert(dst_pixels);
    const bool doR = !processChannels[0] && (dstNComps >= 2);
    const bool doG = !processChannels[1] && (dstNComps >= 2);
    const bool doB = !processChannels[2] && (dstNComps >= 3);
    const bool doA = !processChannels[3] && (dstNComps == 1 || dstNComps == 4);
    assert(srcNComps == 4 || !originalPremult); // only RGBA can be premult
    assert(dstNComps == 4 || !premult); // only RGBA can be premult
    Q_UNUSED(premult);
    Q_UNUSED(originalPremult);

    for ( int y = roi.y1; y < roi.y2; ++y, dst_pixels += (dstRowElements - (roi.x2 - roi.x1) * dstNComps) ) {
        for (int x = roi.x1; x < roi.x2; ++x, dst_pixels += dstNComps) {
            const PIX* src_pixels = originalImage ? (const PIX*)acc.pixelAt(x, y) : 0;
            PIX srcA = src_pixels ? maxValue : 0; /* be opaque for anything that doesn't contain alpha */
            if ( ( (srcNComps == 1) || (srcNComps == 4) ) && src_pixels ) {
#             ifdef DEBUG
                assert(src_pixels[srcNComps - 1] == src_pixels[srcNComps - 1]); // check for NaN
#             endif
                srcA = src_pixels[srcNComps - 1];
            }
#         ifdef NATRON_COPY_CHANNELS_UNPREMULT
            PIX dstAorig = maxValue;
#         endif
            if ( (dstNComps == 1) || (dstNComps == 4) ) {
#             ifdef DEBUG
                assert(dst_pixels[dstNComps - 1] == dst_pixels[dstNComps - 1]); // check for NaN
#             endif
#             ifdef NATRON_COPY_CHANNELS_UNPREMULT
                dstAorig = dst_pixels[dstNComps - 1];
#             endif
            }
            if (doR) {
#             ifdef DEBUG
                assert(!src_pixels || src_pixels[0] == src_pixels[0]); // check for NaN
                assert(dst_pixels[0] == dst_pixels[0]); // check for NaN
#             endif
                DOCHANNEL(0);
#             ifdef DEBUG
                assert(dst_pixels[0] == dst_pixels[0]); // check for NaN
#             endif
            }
            if (doG) {
#             ifdef DEBUG
                assert(!src_pixels || src_pixels[1] == src_pixels[1]); // check for NaN
                assert(dst_pixels[1] == dst_pixels[1]); // check for NaN
#             endif
                DOCHANNEL(1);
#             ifdef DEBUG
                assert(dst_pixels[1] == dst_pixels[1]); // check for NaN
#             endif
            }
            if (doB) {
#             ifdef DEBUG
                assert(!src_pixels || src_pixels[2] == src_pixels[2]); // check for NaN
                assert(dst_pixels[2] == dst_pixels[2]); // check for NaN
#             endif
                DOCHANNEL(2);
#             ifdef DEBUG
                assert(dst_pixels[2] == dst_pixels[2]); // check for NaN
#             endif
            }
            if (doA) {
#             ifdef NATRON_COPY_CHANNELS_UNPREMULT
                if (premult) {
                    if (dstAorig != 0) {
                        // unpremult, then premult
                        if ( (dstNComps >= 2) && !doR ) {
                            dst_pixels[0] = (dst_pixels[0] / (float)dstAorig) * srcA;
#                         ifdef DEBUG
                            assert(dst_pixels[0] == dst_pixels[0]); // check for NaN
#                         endif
                        }
                        if ( (dstNComps >= 2) && !doG ) {
                            dst_pixels[1] = (dst_pixels[1] / (float)dstAorig) * srcA;
#                         ifdef DEBUG
                            assert(dst_pixels[1] == dst_pixels[1]); // check for NaN
#                         endif
                        }
                        if ( (dstNComps >= 2) && !doB ) {
                            dst_pixels[2] = (dst_pixels[2] / (float)dstAorig) * srcA;
#                         ifdef DEBUG
                            assert(dst_pixels[2] == dst_pixels[2]); // check for NaN
#                         endif
                        }
                    }
                }
#              endif // NATRON_COPY_CHANNELS_UNPREMULT
                // coverity[dead_error_line]
                dst_pixels[dstNComps - 1] = srcA;
#              ifdef DEBUG
                assert(dst_pixels[dstNComps - 1] == dst_pixels[dstNComps - 1]); // check for NaN
#              endif
            }
        }
    }
} // Image::copyUnProcessedChannelsForPremult
예제 #12
0
파일: image.c 프로젝트: WST/gallerizer-cli
void gdResample(Image *dst, Image *src, int dstX, int dstY, int srcX, int srcY, int dstW, int dstH, int srcW, int srcH) {
	int x, y;
	double sy1, sy2, sx1, sx2;
	
	for (y = dstY; (y < dstY + dstH); y++) {
		sy1 = ((double) y - (double) dstY) * (double) srcH / (double) dstH;
		sy2 = ((double) (y + 1) - (double) dstY) * (double) srcH / (double) dstH;
		for (x = dstX; (x < dstX + dstW); x++) {
			double sx, sy;
			double spixels = 0;
			double red = 0.0, green = 0.0, blue = 0.0, alpha = 0.0;
			sx1 = ((double) x - (double) dstX) * (double) srcW / dstW;
			sx2 = ((double) (x + 1) - (double) dstX) * (double) srcW / dstW;
			sy = sy1;
			do {
				double yportion;
				if(floor (sy) == floor (sy1)) {
					yportion = 1.0 - (sy - floor (sy));
					if(yportion > sy2 - sy1) {
						yportion = sy2 - sy1;
					}
					sy = floor (sy);
				}
				else if(sy == floor (sy2)) {
					yportion = sy2 - floor (sy2);
				} else {
					yportion = 1.0;
				}
				sx = sx1;
				do {
					double xportion;
					double pcontribution;
					
					Pixel p;
					
					if(floor (sx) == floor (sx1)) {
						xportion = 1.0 - (sx - floor (sx));
						if(xportion > sx2 - sx1) {
							xportion = sx2 - sx1;
						}
						sx = floor (sx);
					}
					else if (sx == floor (sx2)) {
						xportion = sx2 - floor (sx2);
					} else {
						xportion = 1.0;
					}
					
					pcontribution = xportion * yportion;
					p = *pixelAt(src, floor(sx + srcX), floor(sy + srcY));
					red += p.red * pcontribution;
					green += p.green * pcontribution;
					blue += p.blue * pcontribution;
					spixels += xportion * yportion;
					
					sx += 1.0;
					
				} while (sx < sx2);
				
				sy += 1.0;
				
			} while (sy < sy2);
			
			if(spixels != 0.0) {
				red /= spixels;
				green /= spixels;
				blue /= spixels;
				alpha /= spixels;
			}
			
			if(red > 255.0) red = 255.0;
			if(green > 255.0) green = 255.0;
			if(blue > 255.0) blue = 255.0;
			
			Pixel *p = pixelAt(dst, x, y);
			p->red = red;
			p->green = green;
			p->blue = blue;
		}
	}
}
예제 #13
0
void Image::bilateral()
{
	// Gaussian kernel used to model geometric similarity.
	float *kernel = createGaussianKernel(RADIUS + 1, VARIANCE);
	
	for (int x = 0; x < _width; x++) {
		for (int y = 0; y < _height; y++) {
			pixel3f *center = pixelAt(_pixels, x, y);
			float numerator = 0;
			float denominator = 0;
			
			for (int i = -RADIUS; i <= RADIUS; i++) {
				pixel3f *neighbor = pixelAt(_pixels, x + i, y);
				
				// Compute euclidean distance between Lab colors to determine photometric similarity.
				float dL = center->L - neighbor->L;
				float da = center->a - center->a;
				float db = center->b - center->b;
				float distance = dL * dL + da * da + db * db;
				
				float photometric = expf(distance / PHOTOMETRIC);
				float similarity = photometric * kernel[abs(i)];
				
				// Denominator serves to normalize values.
				denominator += similarity;
				numerator += similarity * neighbor->L;
			}
			
			// Copy a and b data over as well to use for the y-filter pass.
			pixel3f *target = pixelAt(_copy, x, y);
			target->L = numerator / denominator;
			target->a = center->a;
			target->b = center->b;
		}
	}
	
	for (int x = 0; x < _width; x++) {
		for (int y = 0; y < _height; y++) {
			pixel3f *center = pixelAt(_copy, x, y);
			float numerator = 0;
			float denominator = 0;
			
			for (int j = -RADIUS; j <= RADIUS; j++) {
				pixel3f *neighbor = pixelAt(_copy, x, y + j);
				
				float dL = center->L - neighbor->L;
				float da = center->a - center->a;
				float db = center->b - center->b;
				float distance = dL * dL + da * da + db * db;
				
				float photometric = expf(distance / PHOTOMETRIC);
				float similarity = photometric * kernel[abs(j)];
				
				denominator += similarity;
				numerator += similarity * neighbor->L;
			}
			
			pixelAt(_pixels, x, y)->L = numerator / denominator;
		}
	}
	
	delete[] kernel;
}
예제 #14
0
 void getScreenBytes(unsigned char* bytes)
 {
     int c64bytes = getScreenBytesSize();
     memset(bytes, 0, c64bytes);
     int width = getWidth();
     int height = getHeight();
     
     for (int h = 0; h < height; h++)
     {
         for (int w = 0; w < width; w++)
         {
             //printf("src %d = %d\n", h*width+w, src[h*width+w]);
             
             int xblock = w / xBlockSize;
             int yblock = h / yBlockSize;
             
             Pixel* p = pixelAt(w, h);
             
             // determine bitmask based on the palette index
             // bgcolor = 0x00
             // fgcolor = 0x03
             // block color 0 = 0x01
             // block color 1 = 0x02
             unsigned char mask = 0;
             
             if (p->palette_index == bgcolor)
             {
                 mask = 0x00;
             }
             else if (p->palette_index == fgcolor)
             {
                 mask = 0x03;
             }
             else if (p->palette_index == getBlockColor(xblock, yblock, 0))
             {
                 mask = 0x01;
             }
             else if (p->palette_index == getBlockColor(xblock, yblock, 1))
             {
                 mask = 0x02;
             }
             else
             {
                 printf("this should not happen.");
             }
             
             // set bits in bitmap byte
             int screen_width = w*2;
             
             int row = h / 8;
             int c = screen_width / 8;
             int line = h & 7;
             int bit = 7 - (screen_width & 7);
             int byte = row*320 + c*8 + line;
             
             unsigned char b = bytes[byte];
             
             // raise 2 bits (fg color)
             bit--;
             if (bit < 0)
                 bit = 0;
             
             unsigned char shifted_mask = mask << bit;
             b = b | shifted_mask;
             bytes[byte] = b;
         }
     }
 }