سؤال

أحد التطبيقات التي قرأتها في صور كبيرة جدًا (jpegs) ولكن يحتاج فقط إلى العمل مع صور أصغر لذلك أقوم بتقسيمها إلى شيء مثل

ImageReadParam param = reader.getDefaultReadParam();
param.setSourceSubsampling(4, 4, 0, 0);
img = reader.read(0);

ومع ذلك، نظرًا لوجود خطأ في قارئ jpeg الذي لا يتعامل مع بعض البيانات التعريفية، فقد رجعت إلى طرق أخرى، أحدها يستخدم JAI لقراءة الصورة ثم تغيير حجمها (الرمز موجود أدناه، ولا يتعين علي استخدام الانعكاس كما هو الحال مع بعض لا تتوفر في بيئات النشر JAI، أعلم أنه يمكنني التصميم حول هذا بشكل أفضل ولكن هذا هو الحال).

try {
Class<?> c = ImageUtil.class.getClassLoader().loadClass("javax.media.jai.JAI");

if (c != null) { 
    URL url = new URL("file://" + file.getAbsolutePath());
    Method m = c.getMethod("create", String.class, Object.class);
    Object pi = m.invoke(null, "url", url);
    img = (BufferedImage) pi.getClass().getMethod("getAsBufferedImage").invoke(pi);
}
} catch (Throwable tt) {
// ...
}

ومع ذلك، فإن بعض الصور تكون كبيرة حقًا، حيث أخرج بين الحين والآخر من استثناءات الذاكرة، هل هناك على أي حال يمكنني جعل JAI يقوم بأخذ عينة فرعية من الصورة عند قراءتها بالطريقة التي أقرأ بها الصور باستخدام ImageReader؟

هل كانت مفيدة؟

المحلول

أفترض أنه تم طرح استثناء نفاد الذاكرة عند محاولة إجراء التحويل إلى BufferedImage؟

إذا كان هذا هو الحال، فربما تفكر في الالتزام بـ RenderedOp الذي يتم إرجاعه بواسطة طريقة إنشاء JAI وبدلاً من ذلك استخدام ParameterBlock وإنشاء JAI آخر لإنتاج الصورة المقاسة؟

ParameterBlock paramBlock = new ParameterBlock();
paramBlock.addSource(((RenderedOp) pi).createInstance()); // Updated this
paramBlock.add(0.5f); // x Scale (Change these two Scale values!)
paramBlock.add(0.5f); // y Scale
paramBlock.add(0.0f); // x Translate
paramBlock.add(0.0f); // y Translate
paramBlock.add(new InterpolationBilinear()); // I think this Interpolation should work...)
RenderedOp resized = JAI.create("scale", paramBlock, null);

أخشى أن الكود أعلاه لم يتم اختباره بالكامل كمعيار قياسي، ولكن يجب أن تبدأ!

بمجرد الانتهاء من تغيير حجم RenderedOp، يجب أن تكون قادرًا على تحويله بأمان إلى BufferedImage إذا كان عليك ذلك.

نصائح أخرى

RenderedOp rop = JAI.create("fileload", file.getAbsolutePath());

ParameterBlock pb = new ParameterBlock();
pb.addSource(rop);
pb.add(0.5f);
pb.add(0.5f);
rop = JAI.create("scale", pb);

// For better looking results, but slower:
// rop = JAI.create("SubsampleAverage", pb);

BufferedImage bufImg = rop.getAsBufferedImage();   
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top