std::size_t DefaultBitImageCommands::selectBitImageMode(const ofPixels_<unsigned char>& binaryPixels, BaseCodes::PrintResolution printResolution) { // width = nL + (nH * 256) // nH is the HIGH part of the WIDTH VALUE. // nL is the LOW part of the WIDTH VALUE. // nH will always be 0 for values less that 256 (1 byte) uint8_t nH = getHighByte(binaryPixels.getWidth()); uint8_t nL = getLowByte(binaryPixels.getWidth()); std::vector<uint8_t> buffer; buffer.push_back(BaseCodes::ESC); buffer.push_back('*'); buffer.push_back(printResolution); buffer.push_back(nL); buffer.push_back(nH); uint8_t currentByte = 0; int bitIndex = 0; for(int x = 0; x < binaryPixels.getWidth(); ++x) { currentByte = 0; bitIndex = 0; for(int y = 0; y < binaryPixels.getHeight(); ++y) { bool binaryValue = binaryPixels[binaryPixels.getPixelIndex(x,y)] < ofColor_<unsigned char>::limit() / 2; currentByte |= binaryValue << (7 - bitIndex); bitIndex++; if(8 == bitIndex) { buffer.push_back(currentByte); currentByte = 0; bitIndex = 0; } } } return writeBytes(buffer); }
bool ofPixels_<PixelType>::pasteInto(ofPixels_<PixelType> &dst, int xTo, int yTo) const{ if (!(isAllocated()) || !(dst.isAllocated()) || getBytesPerPixel() != dst.getBytesPerPixel() || xTo + getWidth()>dst.getWidth() || yTo + getHeight()>dst.getHeight()) return false; int bytesToCopyPerRow = (xTo + getWidth()<=dst.getWidth() ? getWidth() : dst.getWidth()-xTo) * getBytesPerPixel(); int columnsToCopy = yTo + getHeight() <= dst.getHeight() ? getHeight() : dst.getHeight()-yTo; PixelType * dstPix = dst.getData() + ((xTo + yTo*dst.getWidth())*dst.getBytesPerPixel()); const PixelType * srcPix = getData(); int srcStride = getWidth()*getBytesPerPixel(); int dstStride = dst.getWidth()*dst.getBytesPerPixel(); for(int y=0;y<columnsToCopy; y++){ memcpy(dstPix,srcPix,bytesToCopyPerRow); dstPix += dstStride; srcPix += srcStride; } return true; }
ofPixels_<unsigned char> ImageUtils::toGrayscale(const ofPixels_<unsigned char>& pixels) { if (OF_IMAGE_GRAYSCALE == pixels.getImageType()) { return pixels; } ofPixels pix; pix.allocate(pixels.getWidth(), pixels.getHeight(), OF_IMAGE_GRAYSCALE); for (std::size_t x = 0; x < pixels.getWidth(); ++x) { for (std::size_t y = 0; y < pixels.getHeight(); ++y) { ofColor_<unsigned char> c = pixels.getColor(x, y); pix.setColor(x, y, 0.21 * c.r + 0.71 * c.g + 0.07 * c.b); } } return pix; }
void removeIslands(ofPixels_<T>& img) { int w = img.getWidth(), h = img.getHeight(); int ia1=-w-1,ia2=-w-0,ia3=-w+1,ib1=-0-1,ib3=-0+1,ic1=+w-1,ic2=+w-0,ic3=+w+1; T* p = img.getPixels(); for(int y = 1; y + 1 < h; y++) { for(int x = 1; x + 1 < w; x++) { int i = y * w + x; if(p[i]) { if(!p[i+ia1]&&!p[i+ia2]&&!p[i+ia3]&&!p[i+ib1]&&!p[i+ib3]&&!p[i+ic1]&&!p[i+ic2]&&!p[i+ic3]) { p[i] = 0; } } } } }
ofPixels_<unsigned char> ImageUtils::scaleAndCropTo(const ofPixels_<unsigned char>& pixels, int width, int height, ofScaleMode scaleMode) { ofRectangle inRect(0,0,pixels.getWidth(),pixels.getHeight()); ofRectangle outRect(0,0,width,height); inRect.scaleTo(outRect,scaleMode); ofPixels_<unsigned char> inPixels = pixels; inPixels.resize(inRect.getWidth(),inRect.getHeight()); ofPixels_<unsigned char> outPixels; inPixels.cropTo(outPixels, outRect.x - inRect.x, 0, outRect.width, outRect.height); return outPixels; }
void ofImage_<PixelType>::setFromPixels(const ofPixels_<PixelType> & pixels){ setFromPixels(pixels.getPixels(),pixels.getWidth(),pixels.getHeight(),pixels.getImageType()); }
void ofPixels_<PixelType>::copyFrom(const ofPixels_<PixelType> & mom){ if(mom.isAllocated()) { allocate(mom.getWidth(), mom.getHeight(), mom.getPixelFormat()); memcpy(pixels, mom.getData(), getTotalBytes()); } }
bool ofPixels_<PixelType>::blendInto(ofPixels_<PixelType> &dst, int xTo, int yTo) const{ if (!(isAllocated()) || !(dst.isAllocated()) || getBytesPerPixel() != dst.getBytesPerPixel() || xTo + getWidth()>dst.getWidth() || yTo + getHeight()>dst.getHeight() || getNumChannels()==0) return false; std::function<void(const ConstPixel&,Pixel&)> blendFunc; switch(getNumChannels()){ case 1: blendFunc = [](const ConstPixel&src, Pixel&dst){ dst[0] = clampedAdd(src[0], dst[0]); }; break; case 2: blendFunc = [](const ConstPixel&src, Pixel&dst){ dst[0] = clampedAdd(src[0], dst[0] / ofColor_<PixelType>::limit() * (ofColor_<PixelType>::limit() - src[1])); dst[1] = clampedAdd(src[1], dst[1] / ofColor_<PixelType>::limit() * (ofColor_<PixelType>::limit() - src[1])); }; break; case 3: blendFunc = [](const ConstPixel&src, Pixel&dst){ dst[0] = clampedAdd(src[0], dst[0]); dst[1] = clampedAdd(src[1], dst[1]); dst[2] = clampedAdd(src[2], dst[2]); }; break; case 4: blendFunc = [](const ConstPixel&src, Pixel&dst){ dst[0] = clampedAdd(src[0], dst[0] / ofColor_<PixelType>::limit() * (ofColor_<PixelType>::limit() - src[3])); dst[1] = clampedAdd(src[1], dst[1] / ofColor_<PixelType>::limit() * (ofColor_<PixelType>::limit() - src[3])); dst[2] = clampedAdd(src[2], dst[2] / ofColor_<PixelType>::limit() * (ofColor_<PixelType>::limit() - src[3])); dst[3] = clampedAdd(src[3], dst[3] / ofColor_<PixelType>::limit() * (ofColor_<PixelType>::limit() - src[3])); }; break; } auto dstLine = dst.getLine(yTo); for(auto line: getConstLines()){ auto dstPixel = dstLine.getPixels().begin() + xTo; for(auto p: line.getPixels()){ blendFunc(p,dstPixel); dstPixel++; } dstLine++; } return true; }
bool ofPixels_<PixelType>::resizeTo(ofPixels_<PixelType>& dst, ofInterpolationMethod interpMethod) const{ if(&dst == this){ return true; } if (!(isAllocated()) || !(dst.isAllocated()) || getBytesPerPixel() != dst.getBytesPerPixel()) return false; int srcWidth = getWidth(); int srcHeight = getHeight(); int dstWidth = dst.getWidth(); int dstHeight = dst.getHeight(); int bytesPerPixel = getBytesPerPixel(); PixelType * dstPixels = dst.getData(); switch (interpMethod){ //---------------------------------------- case OF_INTERPOLATE_NEAREST_NEIGHBOR:{ int dstIndex = 0; float srcxFactor = (float)srcWidth/dstWidth; float srcyFactor = (float)srcHeight/dstHeight; float srcy = 0.5; for (int dsty=0; dsty<dstHeight; dsty++){ float srcx = 0.5; int srcIndex = int(srcy)*srcWidth; for (int dstx=0; dstx<dstWidth; dstx++){ int pixelIndex = int(srcIndex + srcx) * bytesPerPixel; for (int k=0; k<bytesPerPixel; k++){ dstPixels[dstIndex] = pixels[pixelIndex]; dstIndex++; pixelIndex++; } srcx+=srcxFactor; } srcy+=srcyFactor; } }break; //---------------------------------------- case OF_INTERPOLATE_BILINEAR: // not implemented yet ofLogError("ofPixels") << "resizeTo(): bilinear resize not implemented, not resizing"; break; //---------------------------------------- case OF_INTERPOLATE_BICUBIC: float px1, py1; float px2, py2; float px3, py3; float srcColor = 0; float interpCol; int patchRow; int patchIndex; float patch[16]; int srcRowBytes = srcWidth*bytesPerPixel; int loIndex = (srcRowBytes)+1; int hiIndex = (srcWidth*srcHeight*bytesPerPixel)-(srcRowBytes)-1; for (int dsty=0; dsty<dstHeight; dsty++){ for (int dstx=0; dstx<dstWidth; dstx++){ int dstIndex0 = (dsty*dstWidth + dstx) * bytesPerPixel; float srcxf = srcWidth * (float)dstx/(float)dstWidth; float srcyf = srcHeight * (float)dsty/(float)dstHeight; int srcx = (int) MIN(srcWidth-1, srcxf); int srcy = (int) MIN(srcHeight-1, srcyf); int srcIndex0 = (srcy*srcWidth + srcx) * bytesPerPixel; px1 = srcxf - srcx; py1 = srcyf - srcy; px2 = px1 * px1; px3 = px2 * px1; py2 = py1 * py1; py3 = py2 * py1; for (int k=0; k<bytesPerPixel; k++){ int dstIndex = dstIndex0+k; int srcIndex = srcIndex0+k; for (int dy=0; dy<4; dy++) { patchRow = srcIndex + ((dy-1)*srcRowBytes); for (int dx=0; dx<4; dx++) { patchIndex = patchRow + (dx-1)*bytesPerPixel; if ((patchIndex >= loIndex) && (patchIndex < hiIndex)) { srcColor = pixels[patchIndex]; } patch[dx*4 + dy] = srcColor; } } interpCol = (PixelType)bicubicInterpolate(patch, px1,py1, px2,py2, px3,py3); dstPixels[dstIndex] = interpCol; } } } break; } return true; }
void ofPixels_<PixelType>::copyFrom(const ofPixels_<PixelType> & mom){ if(mom.isAllocated()) { allocate(mom.getWidth(), mom.getHeight(), mom.getNumChannels()); memcpy(pixels, mom.getPixels(), mom.getWidth() * mom.getHeight() * mom.getBytesPerPixel()); } }
void ofPixels_<PixelType>::copyFrom(const ofPixels_<PixelType> & mom){ if(mom.isAllocated()) { allocate(mom.getWidth(), mom.getHeight(), mom.getPixelFormat()); memcpy(pixels, mom.getPixels(), mom.size() * sizeof(PixelType)); } }
std::size_t DefaultBitImageCommands::printImage(const ofPixels_<unsigned char>& pixels, ofAlignHorz alignHorz, float ditherThreshold, float ditherQuantWeight, BaseCodes::PrintResolution printResolution, int printHeadWidth, int printHeadHeight) { int numVerticalDots = 0; int maxHorizontalDots = 0; int verticalScale = 1; switch(printResolution) { case BaseCodes::RESOLUTION_8_DOTS_SINGLE_DENSITY: maxHorizontalDots = printHeadWidth / 2; numVerticalDots = 8; break; case BaseCodes::RESOLUTION_8_DOTS_DOUBLE_DENSITY: maxHorizontalDots = printHeadWidth; numVerticalDots = 8; break; case BaseCodes::RESOLUTION_24_DOTS_SINGLE_DENSITY: maxHorizontalDots = printHeadWidth / 2; numVerticalDots = 24; break; case BaseCodes::RESOLUTION_24_DOTS_DOUBLE_DENSITY: maxHorizontalDots = printHeadWidth; numVerticalDots = 24; break; } std::size_t totalBytesWritten = 0; ofRectangle imageRect(0,0,pixels.getWidth(),pixels.getHeight()); ofRectangle rectangle(0,0,maxHorizontalDots,pixels.getHeight()); imageRect.scaleTo(rectangle, OF_ASPECT_RATIO_KEEP, alignHorz, OF_ALIGN_VERT_TOP, alignHorz, OF_ALIGN_VERT_TOP); int width = rectangle.getWidth(); int height = imageRect.getHeight(); // ensure vertical res if(height != numVerticalDots) { int remainder = height % numVerticalDots; if (remainder != 0) { height = height + numVerticalDots - remainder; } } ofPixels pix = pixels; // get a copy ofPixels toPrint; toPrint.allocate(width, height, pix.getNumChannels()); toPrint.setColor(ofColor(255)); pix.resize(imageRect.getWidth(), imageRect.getHeight()); pix.pasteInto(toPrint,imageRect.getX(),imageRect.getY()); toPrint = ImageUtils::dither(toPrint,ditherThreshold,ditherQuantWeight); cout << pix.getWidth() << " / " << pix.getHeight() << endl; ofPixels bandBuffer; bandBuffer.allocate(toPrint.getWidth(), numVerticalDots, toPrint.getNumChannels()); // go into page mode totalBytesWritten += writeByte(BaseCodes::ESC); totalBytesWritten += writeByte('L'); // set the print area / origin totalBytesWritten += setPageModePrintArea(0,0,toPrint.getWidth(),toPrint.getHeight() * 2); // TODO 2 * works for double vert density for(int y = 0; y < height; y += numVerticalDots) { // set the vertical displacement const uint8_t command[3] = { BaseCodes::ESC, '3', numVerticalDots * 2 }; // TODO 2 * works for double vert density totalBytesWritten += writeBytes(command, 3); bandBuffer.clear(); toPrint.cropTo(bandBuffer,0,y,width,numVerticalDots); totalBytesWritten += selectBitImageMode(bandBuffer, printResolution); totalBytesWritten += writeByte(BaseCodes::LF); // feed a line // set vertical displacement back to normal const uint8_t command0[2] = { BaseCodes::ESC, '2' }; totalBytesWritten += writeBytes(command0, 2); } // totalBytesWritten += writeByte(BaseCodes::LF); // feed a line totalBytesWritten += writeByte(BaseCodes::FF); return totalBytesWritten; }