/** * Apply the Scale effect on a bitmap. * This function is simply a common interface for ::scale2x(), ::scale3x() and ::scale4x(). * \param scale Scale factor. 2, 3 or 4. * \param void_dst Pointer at the first pixel of the destination bitmap. * \param dst_slice Size in bytes of a destination bitmap row. * \param void_src Pointer at the first pixel of the source bitmap. * \param src_slice Size in bytes of a source bitmap row. * \param pixel Bytes per pixel of the source and destination bitmap. * \param width Horizontal size in pixels of the source bitmap. * \param height Vertical size in pixels of the source bitmap. */ void scale(unsigned scale, void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height) { switch (scale) { case 2 : scale2x(void_dst, dst_slice, void_src, src_slice, pixel, width, height); break; case 3 : scale3x(void_dst, dst_slice, void_src, src_slice, pixel, width, height); break; case 4 : scale4x(void_dst, dst_slice, void_src, src_slice, pixel, width, height); break; } }
/** * Apply the Scale effect on a bitmap. * This function is simply a common interface for ::scale2x(), ::scale3x() and ::scale4x(). * \param scale Scale factor. 2, 203 (fox 2x3), 204 (for 2x4), 3 or 4. * \param void_dst Pointer at the first pixel of the destination bitmap. * \param dst_slice Size in bytes of a destination bitmap row. * \param void_src Pointer at the first pixel of the source bitmap. * \param src_slice Size in bytes of a source bitmap row. * \param pixel Bytes per pixel of the source and destination bitmap. * \param width Horizontal size in pixels of the source bitmap. * \param height Vertical size in pixels of the source bitmap. */ void scale(unsigned scale, void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned width, unsigned height) { switch (scale) { case 202 : case 2 : scale2x(void_dst, dst_slice, void_src, src_slice, width, height); break; case 203 : scale2x3(void_dst, dst_slice, void_src, src_slice, 4, width, height); break; case 204 : scale2x4(void_dst, dst_slice, void_src, src_slice, 4, width, height); break; case 303 : case 3 : scale3x(void_dst, dst_slice, void_src, src_slice, width, height); break; case 404 : case 4 : scale4x(void_dst, dst_slice, void_src, src_slice, width, height); break; } }
void drawPNG() { double h = gHeight; double w = gWidth; glClearColor(0.0, 0.0, 0.0, 0.0); double max; if (gHeight > gWidth) { max = gHeight; } else { max = gWidth; } /* * This is for pressing the key '1'. It renders the png image as it is. * It can be blown up to whatever size the user desires, and the pixels/pixel * size will be scaled accordingly with no algorithm attempted to depixel the * png image. * */ if (gDrawMode == 1) { glClearColor(0.0, 0.0, 0.0, 0.0); double pointSize = int(yRes/h) + 1.0; glPointSize(pointSize); glBegin(GL_POINTS); glVertex3f(0.95,-0.95,0); for(int y=0; y<h; y++) { for (int x = 0; x < gWidth; x ++) { int index = 4 * x + (4 * w * y); glColor4d(int(gData[index]) / 256.0, int(gData[index+1]) / 256.0, int(gData[index+2]) / 256.0, int(gData[index+3]) / 256.0) ; glVertex3f(-1 + (pointSize / xRes) + 2*(x)/max, -1 + (pointSize / yRes)+ 2*y/max, 0); } } glEnd(); } /* * This is for pressing the key '2'. It renders the png image using the EPX algorithm. Basically, * we break down each pixel into a 2x2 (so 4 pixels). If two same-color pixels of the original * png image are adjacent to a pixel of the original png image such that the three pixels form * a 90 degree angle, then the corresponding pixel in the blown up 2x2 is that color as well. So, * for example, let's say that pixel A and pixel B are the same color white such that pixel A * is adjacently above pixel C and pixel B is adjacently to the right of pixel C. We then blow up * pixel C into a 2x2 set of pixels. Since pixels A and B are above and right of pixel C, we would * then render the top right pixel of the 2x2 with the same color, white. This is essentially the * EPX algorithm. * */ else if (gDrawMode == 2) { glClearColor(0.0, 0.0, 0.0, 0.0); double pointSize = round(0.5 * yRes/h + 0.5); glPointSize(pointSize); glBegin(GL_POINTS); glVertex3f(0.95,-0.95,0); for(int y=0; y<h; y++) { for (int x = 0; x < gWidth; x ++) { int index = 4 * x + (4 * w * y); glColor4d(int(gData[index]) / 256.0, int(gData[index+1]) / 256.0, int(gData[index+2]) / 256.0, int(gData[index+3]) / 256.0) ; int upIndex = getUpNeighbor(x,y, gWidth, gHeight); int downIndex = getDownNeighbor(x,y, gWidth, gHeight); int leftIndex = getLeftNeighbor(x,y, gWidth, gHeight); int rightIndex = getRightNeighbor(x,y, gWidth, gHeight); // this is for the corner cases if ((upIndex == -1 && leftIndex == -1) || (upIndex == -1 && rightIndex == -1) || (downIndex == -1 && leftIndex == -1) || (downIndex == -1 && rightIndex == -1)) { // bottom-left pixel of the 2x2 glVertex3f(-1 + (pointSize / xRes) + 2*(x)/max, -1 + (pointSize / yRes)+ 2*y/max, 0); // bottom-right pixel of the 2x2 glVertex3f(-1 + (pointSize / xRes) + 2*(x)/max + 2*pointSize/xRes, -1 + (pointSize / yRes)+ 2*y/max , 0); // top-left pixel of the 2x2 glVertex3f(-1 + (pointSize / xRes) + 2*(x)/max, -1 + (pointSize / yRes)+ 2*y/max + 2*pointSize/yRes, 0); // top-right pixel of the 2x2 glVertex3f(-1 + (pointSize / xRes) + 2*(x)/max + 2*pointSize/xRes, -1 + (pointSize / yRes)+ 2*y/max + 2*pointSize/yRes, 0); } else { Vec3 up, down, left, right; up.x = gData[upIndex]; up.y = gData[upIndex+1]; up.z = gData[upIndex+2]; down.x = gData[downIndex]; down.y = gData[downIndex+1]; down.z = gData[downIndex+2]; right.x = gData[rightIndex]; right.y = gData[rightIndex+1]; right.z = gData[rightIndex+2]; left.x = gData[leftIndex]; left.y = gData[leftIndex+1]; left.z = gData[leftIndex+2]; bool upLeft = (up == left); bool upRight = (up == right); bool downLeft = (down == left); bool downRight = (down == right); //std::cout << upLeft << std::endl; //std::cout << upRight << std::endl; //std::cout << downLeft << std::endl; //std::cout << downRight << std::endl; if (downLeft) { glColor4d(down.x / 256.0, down.y / 256.0, down.z / 256.0, int(gData[downIndex+3]) / 256.0); } // bottom-left pixel of the 2x2 glVertex3f(-1 + (pointSize / xRes) + 2*(x)/max, -1 + (pointSize / yRes)+ 2*y/max, 0); glColor4d(int(gData[index]) / 256.0, int(gData[index+1]) / 256.0, int(gData[index+2]) / 256.0, int(gData[index+3]) / 256.0); if (downRight) { glColor4d(down.x / 256.0, down.y / 256.0, down.z / 256.0, int(gData[downIndex+3]) / 256.0); } // bottom-right pixel of the 2x2 glVertex3f(-1 + (pointSize / xRes) + 2*(x)/max + 2*pointSize/xRes, -1 + (pointSize / yRes)+ 2*y/max , 0); glColor4d(int(gData[index]) / 256.0, int(gData[index+1]) / 256.0, int(gData[index+2]) / 256.0, int(gData[index+3]) / 256.0); if (upLeft) { glColor4d(up.x / 256.0, up.y / 256.0, up.z / 256.0, int(gData[upIndex+3]) / 256.0); } // top-left pixel of the 2x2 glVertex3f(-1 + (pointSize / xRes) + 2*(x)/max, -1 + (pointSize / yRes)+ 2*y/max + 2*pointSize/yRes, 0); glColor4d(int(gData[index]) / 256.0, int(gData[index+1]) / 256.0, int(gData[index+2]) / 256.0, int(gData[index+3]) / 256.0); if (upRight) { glColor4d(up.x / 256.0, up.y / 256.0, up.z / 256.0, int(gData[downIndex+3]) / 256.0); } // top-right pixel of the 2x2 glVertex3f(-1 + (pointSize / xRes) + 2*(x)/max + 2*pointSize/xRes, -1 + (pointSize / yRes)+ 2*y/max + 2*pointSize/yRes, 0); glColor4d(int(gData[index]) / 256.0, int(gData[index+1]) / 256.0, int(gData[index+2]) / 256.0, int(gData[index+3]) / 256.0); } } } glEnd(); } // glDrawPixels, no EPX, just regular image else if (gDrawMode == 3) { glClearColor(0.0, 0.0, 0.0, 0.0); glColor3f(0.0f, 0.0f, 0.0f); //GLubyte color[2][2][4]; GLubyte color[gHeight][gWidth][4]; for(int y = 0; y < gHeight; y++) { for (int x = 0; x < gWidth; x ++) { int index = 4 * x + (4 * w * y); color[y][x][0] = int(gData[index]); color[y][x][1] = int(gData[index+1]); color[y][x][2] = int(gData[index+2]); color[y][x][3] = int(gData[index+3]); //std::cout << "X: " << x/3 << " Y: " << y << " rgb: " << int(gData[index]) << " " << int(gData[index + 1]) << " " << int(gData[index+2]) << std::endl; //glColor3d(int(gData[index]) / 256.0, int(gData[index+1]) / 256.0, int(gData[index+2]) / 256.0); //glVertex3f(-1 + (pointSize / xRes) + 2*(x/3)/max, -1 + (pointSize / yRes)+ 2*y/max, 0); } } //GLfloat scaleX = 1.0f * xRes / 2; //GLfloat scaleY = 1.0f * yRes / 2; //std::cout << scaleX << " " << scaleY << std::endl; //glPixelZoom(scaleX/15.99, scaleY/15.99); glPixelZoom(floor(xRes/max), floor(yRes/max)); //glPixelZoom(5,5); glRasterPos2d(-1.0, -1.0); glClear(GL_COLOR_BUFFER_BIT); glDrawPixels( gWidth, gHeight, GL_RGBA, GL_UNSIGNED_BYTE, color ); glFlush(); } /* EPX algorithm with gldrawPixels */ else if (gDrawMode == 4) { epx(gHeight, gWidth, h, w, xRes, yRes, max, gData); } /* scale2x algorithm with gldrawPixels */ else if (gDrawMode == 5) { scale2x(gHeight, gWidth, h, w, xRes, yRes, max, gData); } /* scale3x algorithm with gldrawPixels */ else if (gDrawMode == 6) { scale3x(gHeight, gWidth, h, w, xRes, yRes, max, gData); } /* scale4x algorithm with gldrawPixels */ else if (gDrawMode == 7) { scale4x(gHeight, gWidth, h, w, xRes, yRes, max, gData); } /* eagle algorithm with gldrawPixels */ else if (gDrawMode == 8) { eagle(gHeight, gWidth, h, w, xRes, yRes, max, gData); } /* bilinear interpolation! */ else if (gDrawMode == 9) { bilinear2x(gHeight, gWidth, h, w, xRes, yRes, max, gData); } /* bicubic interpolation! */ else if (gDrawMode == 10) { bicubic2x(gHeight, gWidth, h, w, xRes, yRes, max, gData); } /* eagle3x! */ else if (gDrawMode == 11) { eagle3x(gHeight, gWidth, h, w, xRes, yRes, max, gData); } // no matter what draw mode, draw nearest neighbor on the right side // Set matrix mode glMatrixMode(GL_PROJECTION); // push current projection matrix on the matrix stack glPushMatrix(); // Set an ortho projection based on window size glLoadIdentity(); glOrtho(0, xRes * 2, 0, yRes, 0, 1); // Switch back to model-view matrix glMatrixMode(GL_MODELVIEW); // Store current model-view matrix on the stack glPushMatrix(); // Clear the model-view matrix glLoadIdentity(); // You can specify this in window coordinates now glRasterPos2i(2*xRes,0); glPixelZoom(floor(xRes/max), floor(yRes/max)); glDrawPixels(gWidth, gHeight, GL_RGBA, GL_UNSIGNED_BYTE, gData); // Restore the model-view matrix glPopMatrix(); // Switch to projection matrix and restore it glMatrixMode(GL_PROJECTION); glPopMatrix(); }