public Stream GetImage(State p_state) { string fname = ConfigurationManager.AppSettings["JP2CachePath"] + p_state.File; if (!File.Exists(fname)) { throw new IIIFException(getErrorXml(new Error { Code = "i3f_200", Message = p_state.File + " does not exist" })); } try { return GetImageUsingKDUExpand(p_state); } catch (IIIFException e) { throw e; } catch (Exception e) { throw e; } }
private Stream GetImageUsingKDUExpand(State p_state) { try { string fname = ConfigurationManager.AppSettings["JP2CachePath"] + p_state.File; float starty = 0; float startx = 0; double tileheight = 1; double tilewidth = 1; string[] regions = null; float scale = 0; float scalex = 0; float scaley = 0; Metadata imageSize = GetJP2Metadata(fname); regions = p_state.Region.Split(new char[] { ',' }); if (regions.Length == 4) { if (!regions[0].StartsWith("%")) { tilewidth = int.Parse(regions[2]); tileheight = int.Parse(regions[3]); } else { tilewidth = double.Parse(regions[2]) * imageSize.Width; tileheight = double.Parse(regions[3]) * imageSize.Height; } } // assume all region returned else { startx = 0; starty = 0; } float wScale = (float)p_state.Width / imageSize.Width; float hScale = (float)p_state.Height / imageSize.Height; scale = scalex = scaley = 1; startx = 0; starty = 0; switch (p_state.SizeType) { case "resize": if (p_state.Region.Equals("all")) { scalex = wScale; scaley = hScale; if (p_state.SizeType.Equals("best")) { if (scalex < scaley) { scale = scalex; } else { scale = scaley; } } else { if (scalex > scaley) { scale = scalex; } else { scale = scaley; } } tilewidth = Convert.ToInt32(imageSize.Width * scale); tileheight = Convert.ToInt32(imageSize.Height * scale); } else if (p_state.Width != 0 && p_state.Height != 0) { if (tilewidth > 0) scalex = (float)(p_state.Width / tilewidth); else scalex = wScale; if (tileheight > 0) scaley = (float)(p_state.Height / tileheight); else scaley = hScale; if (p_state.Width == p_state.Height) { scale = scalex; // both scales should be the same so shouldn't matter } else if (p_state.Width > p_state.Height) { scale = scalex; } else { scale = scaley; } } else if (p_state.Width > p_state.Height) { if (tilewidth > 0) scale = (float)(p_state.Width / tilewidth); else scale = wScale; scaley = scalex = scale; } else { if (tileheight > 0) scale = (float)(p_state.Height / tileheight); else scale = hScale; } // get all if (!p_state.SizeType.Equals("resize") && p_state.Region.Equals("all")) { if (p_state.Width != 0) tilewidth = p_state.Width; if (p_state.Height != 0) tileheight = p_state.Height; } break; case "best": if (tilewidth > 0) scalex = (float)(p_state.Width / tilewidth); else scalex = wScale; if (tileheight > 0) scaley = (float)(p_state.Height / tileheight); else scaley = hScale; if (scalex < scaley) scale = scalex; else scale = scaley; // get all if (p_state.Region.Equals("all")) { tileheight = int.Parse(Math.Round(imageSize.Height * scale).ToString()); tilewidth = int.Parse(Math.Round(imageSize.Width * scale).ToString()); } break; case "proportion": //scale = scalex = scaley = p_state.Size; scale = p_state.Size; // get all if (p_state.Region.Equals("all")) { tileheight = int.Parse(Math.Round(imageSize.Height * scale).ToString()); tilewidth = int.Parse(Math.Round(imageSize.Width * scale).ToString()); } break; default: if (wScale < hScale) scale = wScale; else scale = hScale; scalex = scaley = scale; break; } regions = p_state.Region.Split(new char[] { ',' }); string region = ""; if (regions.Length == 4) { // for percentage regions if (p_state.Region.StartsWith("%")) { startx = float.Parse(regions[0].Substring(1)); starty = float.Parse(regions[1]); tilewidth = float.Parse(regions[2]); tileheight = float.Parse(regions[3]); } else { startx = float.Parse(regions[0]) / imageSize.Width; starty = float.Parse(regions[1]) / imageSize.Height; tilewidth = float.Parse(regions[2]) / imageSize.Width; tileheight = float.Parse(regions[3]) / imageSize.Height; } region = "{" + starty + "," + startx + "},{" + tileheight + "," + tilewidth + "}"; } if (starty > 1 || startx > 1 || startx + tilewidth < 0 || starty + tileheight < 0) { throw new IIIFException(getErrorXml(new Error { Code = "i3f_400", Message = "Invalid region specified" })); } // try to get the closest possible size to the one we want in order to reduce the tile size // when creating an image tile int reduce = Convert.ToInt32(1 / scale); if (reduce > 0) reduce = Convert.ToInt32(Math.Floor(Math.Log(reduce, 2.5))); p_state.Reduce = reduce; string outputFile = ConfigurationManager.AppSettings["JP2CachePath"] + p_state.Target.Replace(".jpg", ".bmp"); ProcessStartInfo start = new ProcessStartInfo(); start.FileName = ConfigurationManager.AppSettings["ExpanderPath"]; start.UseShellExecute = false; start.RedirectStandardOutput = false; start.RedirectStandardError = true; start.CreateNoWindow = true; start.Arguments = "-resilient -quiet -i \"" + fname + "\" -o \"" + outputFile + "\" -reduce " + reduce + (string.IsNullOrEmpty(region) ? "" : " -region " + region); Process proc = Process.Start(start); proc.WaitForExit(); BufferedStream bs = new BufferedStream(new FileStream(outputFile, FileMode.Open)); int length = (int)bs.Length; byte[] imageBits = new byte[length]; // read the digital bits of the image into the byte array bs.Read(imageBits, 0, length); Image img = Image.FromStream(bs); Bitmap bmp = new Bitmap(img); MemoryStream stream = new MemoryStream(); bmp.Save(stream, ImageFormat.Jpeg); // remove temporary bmp file img.Dispose(); bs.Close(); bs.Dispose(); File.Delete(outputFile); return stream; } catch (Exception) { throw; } }
private void GetImage(IAsyncResult p_res) { ImageRequestState state = (ImageRequestState)p_res.AsyncState; if (state.err != null) { asynch.CompleteCall(); } else { lock (lockobj) { try { Extractor kdu = new Extractor(); State kdu_state = new State(); kdu_state.File = state.identifier.EndsWith(".jp2") ? state.identifier : state.identifier + ".jp2"; kdu_state.SizeType = state.sizeType; kdu_state.Size = string.IsNullOrEmpty(state.size) ? 0 : float.Parse(state.size); kdu_state.Width = string.IsNullOrEmpty(state.width) ? 0 : int.Parse(state.width); kdu_state.Height = string.IsNullOrEmpty(state.height) ? 0 : int.Parse(state.height); kdu_state.Region = state.region; kdu_state.Format = state.format; kdu_state.Quality = state.quality; Stream stream = kdu.GetImage(kdu_state); Image img = Image.FromStream(stream); if (state.sizeType.Equals("resize")) { int sizeWidth = img.Width; int sizeHeight = img.Height; if (!string.IsNullOrEmpty(state.width) && !string.IsNullOrEmpty(state.height)) { sizeWidth = Convert.ToInt32(state.width); sizeHeight = Convert.ToInt32(state.height); } else if (!string.IsNullOrEmpty(state.width)) { sizeWidth = Convert.ToInt32(state.width); sizeHeight = (int)(((float)sizeWidth / img.Width) * sizeHeight); } else if (!string.IsNullOrEmpty(state.height)) { sizeHeight = Convert.ToInt32(state.height); sizeWidth = (int)(((float)sizeHeight / img.Height) * sizeWidth); } img = ResizeImage(img, sizeWidth, sizeHeight); } else if (state.sizeType.Equals("best")) { int sizeWidth = Convert.ToInt32(state.width); int sizeHeight = Convert.ToInt32(state.height); double regionWidth = img.Width; if (!string.IsNullOrEmpty(state.regionWidth)) regionWidth = Convert.ToDouble(state.regionWidth); double regionHeight = img.Height; if (!string.IsNullOrEmpty(state.regionHeight)) regionHeight = Convert.ToDouble(state.regionHeight); double scalex = sizeWidth / regionWidth; double scaley = sizeHeight / regionHeight; if (scalex < scaley) img = ResizeImage(img, (int)(regionWidth * scalex), (int)(regionHeight * scalex)); else img = ResizeImage(img, (int)(regionWidth * scaley), (int)(regionHeight * scaley)); } else if (state.sizeType.Equals("proportion")) { double regionWidth = 0; double regionHeight = 0; if (state.region.Equals("all")) { XmlDocument doc = new XmlDocument(); doc.LoadXml(kdu.GetMetadata(state.identifier.EndsWith(".jp2") ? state.identifier : state.identifier + ".jp2")); regionWidth = Convert.ToInt32(doc.GetElementsByTagName("Width")[0].InnerText); regionHeight = Convert.ToInt32(doc.GetElementsByTagName("Height")[0].InnerText); } else if (state.region.StartsWith("%")) { XmlDocument doc = new XmlDocument(); doc.LoadXml(kdu.GetMetadata(state.identifier.EndsWith(".jp2") ? state.identifier : state.identifier + ".jp2")); regionWidth = Convert.ToDouble(state.regionWidth) * Convert.ToInt32(doc.GetElementsByTagName("Width")[0].InnerText); regionHeight = Convert.ToDouble(state.regionHeight) * Convert.ToInt32(doc.GetElementsByTagName("Height")[0].InnerText); } else { regionWidth = Convert.ToInt32(state.regionWidth); regionHeight = Convert.ToInt32(state.regionHeight); } regionWidth *= Convert.ToDouble(state.size); regionHeight *= Convert.ToDouble(state.size); if (regionWidth < 1 || regionHeight < 1) { state.err = new error(); state.err.parameter = "region / size"; state.err.text = "Invalid region /size specified"; state.err.statusCode = System.Net.HttpStatusCode.BadRequest; } else { img = ResizeImage(img, (int)regionWidth, (int)regionHeight); } } if (state.err == null) { if (!string.IsNullOrEmpty(state.quality)) { if (state.quality.Equals("grey")) img = MakeGrayscale(new Bitmap(img)); else if (state.quality.Equals("bitonal")) img = MakeBitonal(new Bitmap(img)); } switch (state.rotation) { case "90": img.RotateFlip(RotateFlipType.Rotate90FlipNone); break; case "180": img.RotateFlip(RotateFlipType.Rotate180FlipNone); break; case "270": img.RotateFlip(RotateFlipType.Rotate270FlipNone); break; } _bitmap = new Bitmap(img); } } catch (IIIFException e) { state.err = new error(); try { XmlDocument doc = new XmlDocument(); doc.LoadXml(e.Message); if (doc.GetElementsByTagName("Code")[0].InnerText.Contains("i3f_200")) { state.err.parameter = "identifier"; state.err.text = doc.GetElementsByTagName("Message")[0].InnerText; state.err.statusCode = System.Net.HttpStatusCode.NotFound; } else if (doc.GetElementsByTagName("Code")[0].InnerText.Contains("i3f_400")) { state.err.parameter = "region"; state.err.text = doc.GetElementsByTagName("Message")[0].InnerText; state.err.statusCode = System.Net.HttpStatusCode.BadRequest; } else { state.err.parameter = "unknown"; state.err.text = e.Message; state.err.statusCode = System.Net.HttpStatusCode.BadRequest; } } catch (Exception ex) { state.err.parameter = "unknown"; state.err.text = ex.Message; state.err.statusCode = System.Net.HttpStatusCode.BadRequest; } } catch (Exception e) { state.err = new error(); state.err.parameter = "unknown"; state.err.text = e.Message; state.err.statusCode = System.Net.HttpStatusCode.BadRequest; } finally { asynch.CompleteCall(); } } } }