Ejemplo n.º 1
0
  public static ArthurImage multiply(ArthurImage one, ArthurImage two) {
    BufferedImage image = JavaImageMath.clone(one.bf);
    BufferedImage image2 = JavaImageMath.clone(two.bf);

    WritableRaster r1 = image.getRaster();
    WritableRaster r2 = image2.getRaster();
    int newWidth = Math.max(r1.getWidth(), r2.getWidth());
    int newHeight = Math.max(r1.getHeight(), r2.getHeight());

    BufferedImage collage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);
    WritableRaster raster = collage.getRaster();

    int[] p1 = new int[3];
    int[] p2 = new int[3];
    int[] pixelArray = new int[3];
    for (int y = 0; y < newHeight; y++) {
      for (int x = 0; x < newWidth; x++) {
        p1 = null;
        p2 = null;

        if (x < r1.getWidth() && y < r1.getHeight()) {
          p1 = r1.getPixel(x, y, p1);
        }

        if (x < r2.getWidth() && y < r2.getHeight()) {
          p2 = r2.getPixel(x, y, p2);
        }

        for (int i = 0; i < 3; i++) {
          if (p1 == null && p2 == null) {
            pixelArray[i] = 0;
          } else if (p1 == null && p2 != null) {
            pixelArray[i] = p2[i];
          } else if (p1 != null && p2 == null) {
            pixelArray[i] = p1[i];
          } else {
            pixelArray[i] = (int) ((p1[i] + p2[i]) / 2);
          }
        }
        raster.setPixel(x, y, pixelArray);
      }
    }

    // save image
    String outputFn =
        one.filename.substring(0, one.filename.indexOf(".jpg"))
            + "X"
            + // filename can't contain the / or *characters; decide later
            two.filename.substring(0, two.filename.indexOf(".jpg"))
            + counter
            + ".jpg";
    counter++;

    return new ArthurImage(collage, outputFn);
  }
Ejemplo n.º 2
0
  public static ArthurImage add(ArthurImage one, ArthurColor two) {
    BufferedImage image = JavaImageMath.clone(one.bf);

    double r = two.r.val;
    double g = two.g.val;
    double b = two.g.val;

    WritableRaster raster = image.getRaster();
    int[] pixelArray = new int[3];
    for (int y = 0; y < raster.getHeight(); y++) {
      for (int x = 0; x < raster.getWidth(); x++) {
        pixelArray = raster.getPixel(x, y, pixelArray);
        pixelArray[0] = (int) (3 * pixelArray[0] + r) / 4;
        pixelArray[1] = (int) (3 * pixelArray[1] + g) / 4;
        pixelArray[2] = (int) (3 * pixelArray[2] + b) / 4;
        raster.setPixel(x, y, pixelArray);
      }
    }

    // save image
    String outputFn =
        one.filename.substring(0, one.filename.indexOf(".jpg"))
            + "+"
            + // filename can't contain the / or *characters; decide later
            r
            + g
            + b
            + counter
            + ".jpg";
    counter++;

    return new ArthurImage(image, outputFn);
  }
Ejemplo n.º 3
0
  public static ArthurImage multiply(
      ArthurImage one, ArthurNumber two) { // change to ArthurNumber later
    double f = Math.abs(two.val);
    // get image
    BufferedImage image = JavaImageMath.clone(one.bf);

    // manipulate image
    WritableRaster raster = image.getRaster();
    int width = (int) (raster.getWidth() * f);
    int height = (int) (raster.getHeight() * f);

    BufferedImage collage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    Graphics2D g2d = collage.createGraphics();
    g2d.drawImage(image, 0, 0, width, height, null);
    g2d.dispose();

    // save image
    String outputFn =
        one.filename.substring(0, one.filename.indexOf(".jpg"))
            + "X"
            + // filename can't contain the / or *characters; decide later
            f
            + counter
            + ".jpg";
    counter++;

    return new ArthurImage(collage, outputFn);
  }
Ejemplo n.º 4
0
  public static ArthurImage add(ArthurImage one, ArthurNumber two) {
    BufferedImage image = JavaImageMath.clone(one.bf);
    int num = two.val.intValue();

    WritableRaster raster = image.getRaster();
    int[] pixelArray = new int[3];
    for (int y = 0; y < raster.getHeight(); y++) {
      for (int x = 0; x < raster.getWidth(); x++) {
        pixelArray = raster.getPixel(x, y, pixelArray);
        pixelArray[0] = pixelArray[0] + num;
        pixelArray[1] = pixelArray[1] + num;
        pixelArray[2] = pixelArray[2] + num;
        for (int i = 0; i < 3; i++) {
          if (pixelArray[i] > 255) {
            pixelArray[i] = 255;
          }
        }
        raster.setPixel(x, y, pixelArray);
      }
    }

    // save image
    String outputFn =
        one.filename.substring(0, one.filename.indexOf(".jpg"))
            + "+"
            + // filename can't contain the / or *characters; decide later
            num
            + counter
            + ".jpg";
    counter++;

    return new ArthurImage(image, outputFn);
  }
Ejemplo n.º 5
0
 /**
  * Converts <code>BufferedImage</code> to <code>ByteBuffer</code>.
  *
  * @param bi Input image
  * @return
  */
 public static ByteBuffer convertImageData(BufferedImage bi) {
   byte[] pixelData = ((DataBufferByte) bi.getRaster().getDataBuffer()).getData();
   //        return ByteBuffer.wrap(pixelData);
   ByteBuffer buf = ByteBuffer.allocateDirect(pixelData.length);
   buf.order(ByteOrder.nativeOrder());
   buf.put(pixelData);
   buf.flip();
   return buf;
 }
Ejemplo n.º 6
0
 public static BufferedImage clone(BufferedImage original) {
   WritableRaster raster = original.getRaster();
   BufferedImage clone =
       new BufferedImage(raster.getWidth(), raster.getHeight(), BufferedImage.TYPE_INT_RGB);
   Graphics2D g2d = clone.createGraphics();
   g2d.drawImage(original, 0, 0, null);
   g2d.dispose();
   return clone;
 }
Ejemplo n.º 7
0
  public static ArthurImage divide(ArthurImage one, ArthurImage two) {
    BufferedImage image = JavaImageMath.clone(one.bf);
    BufferedImage image2 = JavaImageMath.clone(two.bf);

    WritableRaster r1 = image.getRaster();
    int width = r1.getWidth();
    int height = r1.getHeight();

    BufferedImage r2resize = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    Graphics2D g2d = r2resize.createGraphics();
    g2d.drawImage(image2, 0, 0, width, height, null);
    g2d.dispose();
    WritableRaster r2 = r2resize.getRaster();

    BufferedImage collage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    WritableRaster raster = collage.getRaster();

    int[] p1 = new int[3];
    int[] p2 = new int[3];
    int[] pixelArray = new int[3];
    for (int y = 0; y < height; y++) {
      for (int x = 0; x < width; x++) {
        p1 = r1.getPixel(x, y, p1);
        p2 = r2.getPixel(x, y, p2);

        for (int i = 0; i < 3; i++) {
          pixelArray[i] = (int) ((p1[i] + p2[i]) / 2);
        }
        raster.setPixel(x, y, pixelArray);
      }
    }

    // save image
    String outputFn =
        one.filename.substring(0, one.filename.indexOf(".jpg"))
            + "D"
            + // filename can't contain the / or *characters; decide later
            two.filename.substring(0, two.filename.indexOf(".jpg"))
            + counter
            + ".jpg";
    counter++;

    return new ArthurImage(collage, outputFn);
  }
Ejemplo n.º 8
0
  public static ArthurImage addition(ArthurImage one, ArthurImage two, int op) {
    BufferedImage image = JavaImageMath.clone(one.bf);
    BufferedImage image2 = JavaImageMath.clone(two.bf);

    WritableRaster r1 = image.getRaster();
    WritableRaster r2 = image2.getRaster();
    int newWidth = r1.getWidth() + r2.getWidth();
    int newHeight = Math.max(r1.getHeight(), r2.getHeight());

    BufferedImage collage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);
    Graphics2D g2d = collage.createGraphics();
    // g2d.setBackground(Color.BLACK);
    g2d.drawImage(image, 0, 0, null);
    g2d.drawImage(image2, r1.getWidth(), 0, null);
    g2d.dispose();

    // save image
    String outputFn;
    if (op == 0) {
      outputFn =
          one.filename.substring(0, one.filename.indexOf(".jpg"))
              + "+"
              + two.filename.substring(0, two.filename.indexOf(".jpg"))
              + counter
              + ".jpg";
    } else {
      outputFn =
          two.filename.substring(0, two.filename.indexOf(".jpg"))
              + "-"
              + one.filename.substring(0, one.filename.indexOf(".jpg"))
              + counter
              + ".jpg";
    }

    counter++;

    return new ArthurImage(collage, outputFn);
  }
Ejemplo n.º 9
0
  /**
   * Returns a ByteBuffer of BufferedImage data. Ensure BufferedImage is of 4BYTE_ABGR type. If
   * imageFormat is set to GL_RGBA, byte stream will be converted.
   */
  private ByteBuffer getByteBuffer(final BufferedImage _image) {
    final DataBuffer buffer = _image.getRaster().getDataBuffer();
    final int type = buffer.getDataType();

    if (type == DataBuffer.TYPE_BYTE) {
      final byte[] data = ((DataBufferByte) buffer).getData();
      if (imageFormat == GL3.GL_RGBA) {
        convertABGRtoRGBA(data);
      }

      return ByteBuffer.wrap(data);
    }

    System.out.println("Failed to determine DataBuffer type.");
    return null;
  }
Ejemplo n.º 10
0
 private static void initImg(BufferedImage img, int pf, int flags) throws Exception {
   WritableRaster wr = img.getRaster();
   int imgType = img.getType();
   if (imgType == BufferedImage.TYPE_INT_RGB
       || imgType == BufferedImage.TYPE_INT_BGR
       || imgType == BufferedImage.TYPE_INT_ARGB
       || imgType == BufferedImage.TYPE_INT_ARGB_PRE) {
     SinglePixelPackedSampleModel sm = (SinglePixelPackedSampleModel) img.getSampleModel();
     int pitch = sm.getScanlineStride();
     DataBufferInt db = (DataBufferInt) wr.getDataBuffer();
     int[] buf = db.getData();
     initIntBuf(buf, img.getWidth(), pitch, img.getHeight(), pf, flags);
   } else {
     ComponentSampleModel sm = (ComponentSampleModel) img.getSampleModel();
     int pitch = sm.getScanlineStride();
     DataBufferByte db = (DataBufferByte) wr.getDataBuffer();
     byte[] buf = db.getData();
     initBuf(buf, img.getWidth(), pitch, img.getHeight(), pf, flags);
   }
 }
Ejemplo n.º 11
0
  public static ArthurImage divide(
      ArthurImage one, ArthurNumber two) { // change to ArthurNumber later
    int f = Math.abs(two.intval());
    // get image
    BufferedImage image = JavaImageMath.clone(one.bf);

    // manipulate image
    WritableRaster raster = image.getRaster();
    int width0 = raster.getWidth();
    int height0 = raster.getHeight();
    int width = width0 / f;
    int height = height0 / f;

    BufferedImage temp = new BufferedImage(width * f, height * f, BufferedImage.TYPE_INT_RGB);
    Graphics2D g2d = temp.createGraphics();
    for (int i = 0; i < f; i++) {
      for (int j = 0; j < f; j++) {
        g2d.drawImage(image, j * width, i * height, width, height, null);
      }
    }
    g2d.dispose();
    BufferedImage collage = new BufferedImage(width0, height0, BufferedImage.TYPE_INT_RGB);
    g2d = collage.createGraphics();
    g2d.drawImage(temp, 0, 0, width0, height0, null);
    g2d.dispose();

    // save image
    String outputFn =
        one.filename.substring(0, one.filename.indexOf(".jpg"))
            + "D"
            + // filename can't contain the / or *characters; decide later
            f
            + counter
            + ".jpg";
    counter++;

    return new ArthurImage(collage, outputFn);
  }
Ejemplo n.º 12
0
  private IFD writeYCbCrImage(
      ImageOutputStream out, BufferedImage image, int comp, TIFFImageWriteParam param)
      throws IOException {
    image = convert(image, BufferedImage.TYPE_INT_RGB);
    try {
      int width = image.getWidth();
      int height = image.getHeight();

      IFD ifd = new IFD(); // entries need to be in tag order !

      int ss = (param == null) ? 0x22 : param.getSubSampling();

      int ssh = (ss >> 4) & 0x0F;
      int ssv = ss & 0x0F;

      if (ssh
          < ssv) { // YCbCrSubsampleVert shall always be less than or equal to YCbCrSubsampleHoriz.
        throw new IOException(
            "Internal error: YCbCrSubsampleVert is not less than YCbCrSubsampleHoriz.");
      }

      //      int ww=((width +ssh-1)/ssh)*ssh;                                   // [1] p.92
      //      int hh=((height+ssv-1)/ssv)*ssv;
      int ww = width;
      int hh = height;

      ifd.add(new DEFactory.NewSubfileTypeDE(2)); // 254 single page of multipage file
      ifd.add(new DEFactory.ImageWidthDE(ww)); // 256
      ifd.add(new DEFactory.ImageLengthDE(hh)); // 257

      DEFactory.BitsPerSampleDE bpss = new DEFactory.BitsPerSampleDE(3);
      bpss.setBitsPerSample(0, 8); // Y
      bpss.setBitsPerSample(1, 8); // Cb
      bpss.setBitsPerSample(2, 8); // Cr
      ifd.add(bpss); // 258

      ifd.add(new DEFactory.CompressionDE(comp)); // 259
      ifd.add(new DEFactory.PhotometricInterpretationDE(YCbCr)); // 262

      int maxrps, maxstripes; // max RowsPerStrip
      if ((1 << 13) <= width) {
        maxrps = 1;
        maxstripes = height; // one row per strip
      } else {
        maxrps = (1 << 13) / width;
        maxstripes = (height + maxrps - 1) / maxrps;
      }
      if (comp == JPEG) {
        maxrps = ((maxrps + 8 * ssv - 1) / (8 * ssv)) * (8 * ssv);
        maxstripes = (height + maxrps - 1) / maxrps;
      }

      DEFactory.StripOffsetsDE offsets = new DEFactory.StripOffsetsDE(maxstripes);
      ifd.add(offsets); // 273
      ifd.add(new DEFactory.SamplesPerPixelDE(3)); // 277
      ifd.add(new DEFactory.RowsPerStripDE(maxrps)); // 278
      DEFactory.StripByteCountsDE counts = new DEFactory.StripByteCountsDE(maxstripes);
      ifd.add(counts); // 279

      if (param == null) {
        ifd.add(new DEFactory.XResolutionDE(72.0)); // 282
        ifd.add(new DEFactory.YResolutionDE(72.0)); // 283
      } else {
        ifd.add(new DEFactory.XResolutionDE(param.getXResolution())); // 282
        ifd.add(new DEFactory.YResolutionDE(param.getYResolution())); // 283
      }
      ifd.add(new DEFactory.ResolutionUnitDE(Inch)); // 296

      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      OutputStream os = baos;
      JPEGOutputStream jpegos = null;

      if (comp == JPEG) {
        jpegos = new JPEGOutputStream(baos);

        int quality = (param == null) ? 50 : (int) (param.getCompressionQuality() * 100);

        jpegos.setZZQuantizationTable(0, JPEGConstants.LQT, quality);
        jpegos.setZZQuantizationTable(1, JPEGConstants.CQT, quality);

        jpegos.setRawDCHuffmanTable(0, JPEGConstants.HLDCTable);
        jpegos.setRawACHuffmanTable(0, JPEGConstants.HLACTable);
        jpegos.setRawDCHuffmanTable(1, JPEGConstants.HCDCTable);
        jpegos.setRawACHuffmanTable(1, JPEGConstants.HCACTable);

        jpegos.defineQuantizationTables();
        jpegos.defineHuffmanTables();
        jpegos.close();

        DEFactory.JPEGTablesDE jpegtables = new DEFactory.JPEGTablesDE(baos.toByteArray());
        ifd.add(jpegtables); // 347

        baos.reset();

        os = jpegos;
      }

      //      CCIR Recommendation 601-1  LumaRed=299/1000 LumaGreen=587/1000 LumeBlue=114/1000
      //      Y  = ( LumaRed * R + LumaGreen * G + LumaBlue * B )
      //      Cb = ( B - Y ) / ( 2 - 2 * LumaBlue )
      //      Cr = ( R - Y ) / ( 2 - 2 * LumaRed )

      double LumaRed = 299.0 / 1000.0;
      double LumaGreen = 587.0 / 1000.0;
      double LumaBlue = 114.0 / 1000.0;

      DEFactory.YCbCrCoefficientsDE YCbCrCoeff = new DEFactory.YCbCrCoefficientsDE();
      YCbCrCoeff.setLumaRed(LumaRed); // Y
      YCbCrCoeff.setLumaGreen(LumaGreen); // Cb
      YCbCrCoeff.setLumaBlue(LumaBlue); // Cr
      ifd.add(YCbCrCoeff); // 529

      DEFactory.YCbCrSubSamplingDE YCbCrSubSampling = new DEFactory.YCbCrSubSamplingDE();
      YCbCrSubSampling.setHoriz(ssh);
      YCbCrSubSampling.setVert(ssv);
      ifd.add(YCbCrSubSampling); // 530

      double RfBY = 0;
      double RfWY = 255;
      double RfBCb = 128;
      double RfWCb = 255;
      double RfBCr = 128;
      double RfWCr = 255;

      DEFactory.ReferenceBlackWhiteDE ReferenceBlackWhite = new DEFactory.ReferenceBlackWhiteDE();
      ReferenceBlackWhite.setY(RfBY, RfWY);
      ReferenceBlackWhite.setCb(RfBCb, RfWCb);
      ReferenceBlackWhite.setCr(RfBCr, RfWCr);
      ifd.add(ReferenceBlackWhite); // 532

      TIFFYCbCrOutputStream ycbcros;
      if (jpegos == null) {
        ycbcros = new TIFFYCbCrOutputStream(os, width, ssv, ssh);
        os = new TIFFSubSamplingOutputStream(ycbcros, width, ssv, ssh);
      } else {
        ycbcros = new TIFFYCbCrOutputStream(os, width, 1, 1); // jpeg does own subsampling
        os = ycbcros;
      }

      ycbcros.setPositioning(1);
      ycbcros.setColourCoefficients(LumaRed, LumaGreen, LumaBlue);
      ycbcros.setRfBWY(RfBY, RfWY);
      ycbcros.setRfBWCb(RfBCb, RfWCb);
      ycbcros.setRfBWCr(RfBCr, RfWCr);

      WritableRaster raster = image.getRaster();
      DataBufferInt buffer = (DataBufferInt) raster.getDataBuffer();
      int[] imgdata = (int[]) buffer.getData();

      int c = 0, index = 0;
      for (int y = 0; y < height; y += maxrps) {

        if ((height - y) < maxrps) {
          maxrps = height - y;
        }

        if (jpegos != null) {
          jpegos.startOfImage();
          int[] hv = {(ssh << 4) | ssv, 0x11, 0x11}; // (Hi<<4)|Vi
          int[] q = {0, 1, 1}; // quantization table Y=0, Cb=Cr=1
          //          jpegos.startOfFrame(((maxrps+ssv-1)/ssv)*ssv,ww,hv,q);
          jpegos.startOfFrame(maxrps, ww, hv, q);
          int[] sel = {0, 1, 1}; // DC,AC code table Y=0, Cb=Cr=1
          jpegos.startOfScan(sel);
        }

        for (int i = 0; i < maxrps; i++) {
          int x = 0;
          while (x < width) {
            c = imgdata[x + (y + i) * width];
            //            c = image.getRGB(x,y+i);
            os.write((c >> 16) & 0x000000FF);
            os.write((c >> 8) & 0x000000FF);
            os.write(c & 0x000000FF);
            x++;
          }
          while (x < ww) {
            os.write((c >> 16) & 0x000000FF);
            os.write((c >> 8) & 0x000000FF);
            os.write(c & 0x000000FF);
            x++;
          }
        }
        os.close();

        byte[] data = baos.toByteArray();
        counts.setCount(index, data.length); // update ifd strip counter array
        offsets.setOffset(index, out.getStreamPosition()); // update ifd image data offset array
        out.write(data); // write to image stream
        baos.reset();
        index++;
      }
      return ifd;
    } catch (Exception e) {
      e.printStackTrace();
      throw new IOException(getClass().getName() + ".writeYCbCrImage:\n\t" + e.getMessage());
    }
  }
Ejemplo n.º 13
0
  private IFD writeRGBImage(
      ImageOutputStream out, BufferedImage image, int comp, TIFFImageWriteParam param)
      throws IOException {
    image = convert(image, BufferedImage.TYPE_INT_RGB);
    try {
      int width = image.getWidth();
      int height = image.getHeight();

      IFD ifd = new IFD(); // entries need to be in tag order !

      ifd.add(new DEFactory.NewSubfileTypeDE(2)); // 254 single page of multipage file
      ifd.add(new DEFactory.ImageWidthDE(width)); // 256
      ifd.add(new DEFactory.ImageLengthDE(height)); // 257

      DEFactory.BitsPerSampleDE bpss = new DEFactory.BitsPerSampleDE(3);
      bpss.setBitsPerSample(0, 8); // red
      bpss.setBitsPerSample(1, 8); // green
      bpss.setBitsPerSample(2, 8); // blue
      ifd.add(bpss); // 258

      ifd.add(new DEFactory.CompressionDE(comp)); // 259
      ifd.add(new DEFactory.PhotometricInterpretationDE(RGB)); // 262

      int maxrps, maxstripes; // max RowsPerStrip
      if ((1 << 13) <= width) {
        maxrps = 1;
        maxstripes = height; // one row per strip
      } else {
        maxrps = (1 << 13) / width;
        maxstripes = (height + maxrps - 1) / maxrps;
      }
      if (comp == JPEG) {
        maxrps = ((maxrps + 8 - 1) / 8) * 8;
        maxstripes = (height + maxrps - 1) / maxrps;
      }
      DEFactory.StripOffsetsDE offsets = new DEFactory.StripOffsetsDE(maxstripes);
      ifd.add(offsets); // 273
      ifd.add(new DEFactory.SamplesPerPixelDE(3)); // 277
      ifd.add(new DEFactory.RowsPerStripDE(maxrps)); // 278
      DEFactory.StripByteCountsDE counts = new DEFactory.StripByteCountsDE(maxstripes);
      ifd.add(counts); // 279
      if (param == null) {
        ifd.add(new DEFactory.XResolutionDE(72.0)); // 282
        ifd.add(new DEFactory.YResolutionDE(72.0)); // 283
      } else {
        ifd.add(new DEFactory.XResolutionDE(param.getXResolution())); // 282
        ifd.add(new DEFactory.YResolutionDE(param.getYResolution())); // 283
      }
      ifd.add(new DEFactory.ResolutionUnitDE(Inch)); // 296

      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      OutputStream os = baos;
      JPEGOutputStream jpegos = null;

      if (comp == JPEG) { // add JPEGTables tag
        jpegos = new JPEGOutputStream(baos);

        int quality = (param == null) ? 50 : (int) (param.getCompressionQuality() * 100);

        jpegos.setZZQuantizationTable(0, JPEGConstants.LQT, quality);
        jpegos.setRawDCHuffmanTable(0, JPEGConstants.HLDCTable);
        jpegos.setRawACHuffmanTable(0, JPEGConstants.HLACTable);

        jpegos.defineQuantizationTables();
        jpegos.defineHuffmanTables();
        jpegos.close();

        DEFactory.JPEGTablesDE jpegtables = new DEFactory.JPEGTablesDE(baos.toByteArray());
        ifd.add(jpegtables); // 347

        baos.reset();

        os = jpegos;
      }

      WritableRaster raster = image.getRaster();
      DataBufferInt buffer = (DataBufferInt) raster.getDataBuffer();
      int[] imgdata = (int[]) buffer.getData();

      int index = 0;
      for (int y = 0; y < height; y += maxrps) {
        /*
        Assume rgb image.

        Each strip: evaluate r g b colour
                    save in byte array
                    write to image file
        */

        if ((height - y) < maxrps) {
          maxrps = height - y;
        }

        if (jpegos != null) { // jpeg: SOI,SOF,SOS marker
          jpegos.startOfImage();
          int[] hv = {0x11, 0x11, 0x11}; // (Hi<<4)|Vi
          int[] q = {0, 0, 0}; // quantization table 0
          jpegos.startOfFrame(maxrps, width, hv, q);
          int[] sel = {0, 0, 0}; // DC,AC code table 0
          jpegos.startOfScan(sel);
        }

        for (int i = 0; i < maxrps; i++) { // write RGB data
          for (int x = 0; x < width; x++) {
            int c = imgdata[x + (y + i) * width];
            os.write((c >> 16) & 0x000000FF);
            os.write((c >> 8) & 0x000000FF);
            os.write(c & 0x000000FF);
          }
        }
        os.close(); // jpeg: EOI marker

        byte[] data = baos.toByteArray();
        counts.setCount(index, data.length); // update ifd strip counter array
        offsets.setOffset(index, out.getStreamPosition()); // update ifd image data offset array
        out.write(data); // write to image stream
        baos.reset();
        index++;
      }
      return ifd;
    } catch (Exception e) {
      e.printStackTrace();
      throw new IOException(getClass().getName() + ".writeRGBImage:\n\t" + e.getMessage());
    }
  }